git: 07b7dec1fe42 - stable/13 - SysV IPC: provide in-kernel helpers to obtain ipcs(8)-like information

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 23 May 2024 00:28:06 UTC
The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=07b7dec1fe4296cdf470013087180a80a0d4a2cf

commit 07b7dec1fe4296cdf470013087180a80a0d4a2cf
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-05-13 17:17:47 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-05-22 23:47:23 +0000

    SysV IPC: provide in-kernel helpers to obtain ipcs(8)-like information
    
    PR:     278949
    
    (cherry picked from commit 87a156527563d0728bff355093e26943da3d7fad)
---
 sys/kern/sysv_msg.c | 34 ++++++++++++++++++++++++++++++++++
 sys/kern/sysv_sem.c | 33 +++++++++++++++++++++++++++++++++
 sys/kern/sysv_shm.c | 36 ++++++++++++++++++++++++++++++++++++
 sys/sys/msg.h       |  3 +++
 sys/sys/sem.h       |  3 +++
 sys/sys/shm.h       |  2 ++
 6 files changed, 111 insertions(+)

diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index 5f08a867f5a9..1b73634eea24 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -1477,6 +1477,40 @@ sysctl_msqids(SYSCTL_HANDLER_ARGS)
 	return (error);
 }
 
+int
+kern_get_msqids(struct thread *td, struct msqid_kernel **res, size_t *sz)
+{
+	struct msqid_kernel *pmsqk;
+	struct prison *pr, *rpr;
+	int i, mi;
+
+	*sz = mi = msginfo.msgmni;
+	if (res == NULL)
+		return (0);
+
+	pr = td->td_ucred->cr_prison;
+	rpr = msg_find_prison(td->td_ucred);
+	*res = malloc(sizeof(struct msqid_kernel) * mi, M_TEMP, M_WAITOK);
+	for (i = 0; i < mi; i++) {
+		pmsqk = &(*res)[i];
+		mtx_lock(&msq_mtx);
+		if (msqids[i].u.msg_qbytes == 0 || rpr == NULL ||
+		    msq_prison_cansee(rpr, &msqids[i]) != 0)
+			bzero(pmsqk, sizeof(*pmsqk));
+		else {
+			*pmsqk = msqids[i];
+			if (pmsqk->cred->cr_prison != pr)
+				pmsqk->u.msg_perm.key = IPC_PRIVATE;
+		}
+		mtx_unlock(&msq_mtx);
+		pmsqk->u.__msg_first = NULL;
+		pmsqk->u.__msg_last = NULL;
+		pmsqk->label = NULL;
+		pmsqk->cred = NULL;
+	}
+	return (0);
+}
+
 SYSCTL_INT(_kern_ipc, OID_AUTO, msgmax, CTLFLAG_RD, &msginfo.msgmax, 0,
     "Maximum message size");
 SYSCTL_INT(_kern_ipc, OID_AUTO, msgmni, CTLFLAG_RDTUN, &msginfo.msgmni, 0,
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 381c1ac4f71b..8a10c1ed90ce 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -1574,6 +1574,39 @@ sysctl_sema(SYSCTL_HANDLER_ARGS)
 	return (error);
 }
 
+int
+kern_get_sema(struct thread *td, struct semid_kernel **res, size_t *sz)
+{
+	struct prison *pr, *rpr;
+	struct semid_kernel *psemak;
+	int i, mi;
+
+	*sz = mi = seminfo.semmni;
+	if (res == NULL)
+		return (0);
+
+	pr = td->td_ucred->cr_prison;
+	rpr = sem_find_prison(td->td_ucred);
+	*res = malloc(sizeof(struct semid_kernel) * mi, M_TEMP, M_WAITOK);
+	for (i = 0; i < mi; i++) {
+		psemak = &(*res)[i];
+		mtx_lock(&sema_mtx[i]);
+		if ((sema[i].u.sem_perm.mode & SEM_ALLOC) == 0 ||
+		    rpr == NULL || sem_prison_cansee(rpr, &sema[i]) != 0)
+			bzero(psemak, sizeof(*psemak));
+		else {
+			*psemak = sema[i];
+			if (psemak->cred->cr_prison != pr)
+				psemak->u.sem_perm.key = IPC_PRIVATE;
+		}
+		mtx_unlock(&sema_mtx[i]);
+		psemak->u.__sem_base = NULL;
+		psemak->label = NULL;
+		psemak->cred = NULL;
+	}
+	return (0);
+}
+
 static int
 sem_prison_check(void *obj, void *data)
 {
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index 1da95b86c9ba..7d38747b585d 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -1089,6 +1089,42 @@ sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
 	return (error);
 }
 
+int
+kern_get_shmsegs(struct thread *td, struct shmid_kernel **res, size_t *sz)
+{
+	struct shmid_kernel *pshmseg;
+	struct prison *pr, *rpr;
+	int i;
+
+	SYSVSHM_LOCK();
+	*sz = shmalloced;
+	if (res == NULL)
+		goto out;
+
+	pr = td->td_ucred->cr_prison;
+	rpr = shm_find_prison(td->td_ucred);
+	*res = malloc(sizeof(struct shmid_kernel) * shmalloced, M_TEMP,
+	    M_WAITOK);
+	for (i = 0; i < shmalloced; i++) {
+		pshmseg = &(*res)[i];
+		if ((shmsegs[i].u.shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
+		    rpr == NULL || shm_prison_cansee(rpr, &shmsegs[i]) != 0) {
+			bzero(pshmseg, sizeof(*pshmseg));
+			pshmseg->u.shm_perm.mode = SHMSEG_FREE;
+		} else {
+			*pshmseg = shmsegs[i];
+			if (pshmseg->cred->cr_prison != pr)
+				pshmseg->u.shm_perm.key = IPC_PRIVATE;
+		}
+		pshmseg->object = NULL;
+		pshmseg->label = NULL;
+		pshmseg->cred = NULL;
+	}
+out:
+	SYSVSHM_UNLOCK();
+	return (0);
+}
+
 static int
 shm_prison_check(void *obj, void *data)
 {
diff --git a/sys/sys/msg.h b/sys/sys/msg.h
index 29fb8c2106b5..d8c950e66c47 100644
--- a/sys/sys/msg.h
+++ b/sys/sys/msg.h
@@ -152,6 +152,9 @@ struct msqid_kernel {
 #ifdef _KERNEL
 extern struct msginfo	msginfo;
 
+int	kern_get_msqids(struct thread *td, struct msqid_kernel **res,
+	    size_t *sz);
+
 #else /* _KERNEL */
 
 __BEGIN_DECLS
diff --git a/sys/sys/sem.h b/sys/sys/sem.h
index 05b69f64cd05..5634f4b0cfcc 100644
--- a/sys/sys/sem.h
+++ b/sys/sys/sem.h
@@ -142,6 +142,9 @@ extern struct seminfo	seminfo;
  */
 void	semexit(struct proc *p);
 
+int	kern_get_sema(struct thread *td, struct semid_kernel **res,
+	    size_t *sz);
+
 #else /* !_KERNEL */
 
 __BEGIN_DECLS
diff --git a/sys/sys/shm.h b/sys/sys/shm.h
index 9c6dad5d43cc..a1aa6ca54c60 100644
--- a/sys/sys/shm.h
+++ b/sys/sys/shm.h
@@ -158,6 +158,8 @@ extern struct shminfo	shminfo;
 
 void	shmexit(struct vmspace *);
 void	shmfork(struct proc *, struct proc *);
+int	kern_get_shmsegs(struct thread *td, struct shmid_kernel **res,
+	    size_t *sz);
 
 #else /* !_KERNEL */