aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2024-05-13 17:17:47 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2024-05-16 17:53:31 +0000
commit87a156527563d0728bff355093e26943da3d7fad (patch)
tree0296d740f34f7ce2b2d97f6c7ad0bbd735838313
parent53725168e1b631be0e60f888ba5e63e140b57766 (diff)
downloadsrc-87a156527563d0728bff355093e26943da3d7fad.tar.gz
src-87a156527563d0728bff355093e26943da3d7fad.zip
SysV IPC: provide in-kernel helpers to obtain ipcs(8)-like information
PR: 278949 Reviewed by: markj Tested by: Ricardo Branco <rbranco@suse.de> Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D45175
-rw-r--r--sys/kern/sysv_msg.c34
-rw-r--r--sys/kern/sysv_sem.c33
-rw-r--r--sys/kern/sysv_shm.c36
-rw-r--r--sys/sys/msg.h3
-rw-r--r--sys/sys/sem.h3
-rw-r--r--sys/sys/shm.h2
6 files changed, 111 insertions, 0 deletions
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index 078151627dfc..0620fbd175af 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 6a668906ebd0..d8c10f837105 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 8f67cb63f33c..835b44ab332a 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 */