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
This commit is contained in:
Konstantin Belousov 2024-05-13 20:17:47 +03:00
parent 53725168e1
commit 87a1565275
6 changed files with 111 additions and 0 deletions

View file

@ -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,

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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

View file

@ -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

View file

@ -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 */