Redo the changes to the SYSV IPC sysctl functions from r298585, so they

don't (mis)use sbufs.

PR:		48471
This commit is contained in:
Jamie Gritton 2016-04-26 18:17:44 +00:00
parent be0edef163
commit 5579267b08
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298656
3 changed files with 50 additions and 83 deletions

View File

@ -65,7 +65,6 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/msg.h>
#include <sys/racct.h>
#include <sys/sbuf.h>
#include <sys/sx.h>
#include <sys/syscall.h>
#include <sys/syscallsubr.h>
@ -1423,38 +1422,28 @@ sys_msgrcv(td, uap)
static int
sysctl_msqids(SYSCTL_HANDLER_ARGS)
{
struct sbuf sb;
struct msqid_kernel tmp, empty;
struct msqid_kernel *msqkptr;
struct prison *rpr;
struct msqid_kernel tmsqk;
struct prison *pr, *rpr;
int error, i;
error = sysctl_wire_old_buffer(req, 0);
if (error != 0)
goto done;
pr = req->td->td_ucred->cr_prison;
rpr = msg_find_prison(req->td->td_ucred);
sbuf_new_for_sysctl(&sb, NULL, sizeof(struct msqid_kernel) *
msginfo.msgmni, req);
bzero(&empty, sizeof(empty));
error = 0;
for (i = 0; i < msginfo.msgmni; i++) {
msqkptr = &msqids[i];
if (msqkptr->u.msg_qbytes == 0 || rpr == NULL ||
msq_prison_cansee(rpr, msqkptr) != 0) {
msqkptr = &empty;
} else if (req->td->td_ucred->cr_prison !=
msqkptr->cred->cr_prison) {
bcopy(msqkptr, &tmp, sizeof(tmp));
msqkptr = &tmp;
msqkptr->u.msg_perm.key = IPC_PRIVATE;
mtx_lock(&msq_mtx);
if (msqids[i].u.msg_qbytes == 0 || rpr == NULL ||
msq_prison_cansee(rpr, &msqids[i]) != 0)
bzero(&tmsqk, sizeof(tmsqk));
else {
tmsqk = msqids[i];
if (tmsqk.cred->cr_prison != pr)
tmsqk.u.msg_perm.key = IPC_PRIVATE;
}
sbuf_bcat(&sb, msqkptr, sizeof(*msqkptr));
mtx_unlock(&msq_mtx);
error = SYSCTL_OUT(req, &tmsqk, sizeof(tmsqk));
if (error != 0)
break;
}
error = sbuf_finish(&sb);
sbuf_delete(&sb);
done:
return (error);
}
@ -1470,7 +1459,8 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, msgssz, CTLFLAG_RDTUN, &msginfo.msgssz, 0,
"Size of a message segment");
SYSCTL_INT(_kern_ipc, OID_AUTO, msgseg, CTLFLAG_RDTUN, &msginfo.msgseg, 0,
"Number of message segments");
SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLTYPE_OPAQUE | CTLFLAG_RD,
SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids,
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
NULL, 0, sysctl_msqids, "", "Message queue IDs");
static int

View File

@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/racct.h>
#include <sys/sbuf.h>
#include <sys/sem.h>
#include <sys/sx.h>
#include <sys/syscall.h>
@ -220,7 +219,8 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, semvmx, CTLFLAG_RWTUN, &seminfo.semvmx, 0,
"Semaphore maximum value");
SYSCTL_INT(_kern_ipc, OID_AUTO, semaem, CTLFLAG_RWTUN, &seminfo.semaem, 0,
"Adjust on exit max value");
SYSCTL_PROC(_kern_ipc, OID_AUTO, sema, CTLTYPE_OPAQUE | CTLFLAG_RD,
SYSCTL_PROC(_kern_ipc, OID_AUTO, sema,
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
NULL, 0, sysctl_sema, "", "Semaphore id pool");
static struct syscall_helper_data sem_syscalls[] = {
@ -1465,38 +1465,28 @@ semexit_myhook(void *arg, struct proc *p)
static int
sysctl_sema(SYSCTL_HANDLER_ARGS)
{
struct prison *rpr;
struct sbuf sb;
struct semid_kernel tmp, empty;
struct semid_kernel *semakptr;
struct prison *pr, *rpr;
struct semid_kernel tsemak;
int error, i;
error = sysctl_wire_old_buffer(req, 0);
if (error != 0)
goto done;
pr = req->td->td_ucred->cr_prison;
rpr = sem_find_prison(req->td->td_ucred);
sbuf_new_for_sysctl(&sb, NULL, sizeof(struct semid_kernel) *
seminfo.semmni, req);
bzero(&empty, sizeof(empty));
error = 0;
for (i = 0; i < seminfo.semmni; i++) {
semakptr = &sema[i];
if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
rpr == NULL || sem_prison_cansee(rpr, semakptr) != 0) {
semakptr = &empty;
} else if (req->td->td_ucred->cr_prison !=
semakptr->cred->cr_prison) {
bcopy(semakptr, &tmp, sizeof(tmp));
semakptr = &tmp;
semakptr->u.sem_perm.key = IPC_PRIVATE;
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(&tsemak, sizeof(tsemak));
else {
tsemak = sema[i];
if (tsemak.cred->cr_prison != pr)
tsemak.u.sem_perm.key = IPC_PRIVATE;
}
sbuf_bcat(&sb, semakptr, sizeof(*semakptr));
mtx_unlock(&sema_mtx[i]);
error = SYSCTL_OUT(req, &tsemak, sizeof(tsemak));
if (error != 0)
break;
}
error = sbuf_finish(&sb);
sbuf_delete(&sb);
done:
return (error);
}

View File

@ -80,7 +80,6 @@ __FBSDID("$FreeBSD$");
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
#include <sys/sbuf.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/syscallsubr.h>
@ -1009,40 +1008,28 @@ shmunload(void)
static int
sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
{
struct prison *rpr;
struct sbuf sb;
struct shmid_kernel tmp, empty;
struct shmid_kernel *shmseg;
struct shmid_kernel tshmseg;
struct prison *pr, *rpr;
int error, i;
SYSVSHM_LOCK();
error = sysctl_wire_old_buffer(req, 0);
if (error != 0)
goto done;
pr = req->td->td_ucred->cr_prison;
rpr = shm_find_prison(req->td->td_ucred);
sbuf_new_for_sysctl(&sb, NULL, shmalloced * sizeof(shmsegs[0]), req);
bzero(&empty, sizeof(empty));
empty.u.shm_perm.mode = SHMSEG_FREE;
error = 0;
for (i = 0; i < shmalloced; i++) {
shmseg = &shmsegs[i];
if ((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
if ((shmsegs[i].u.shm_perm.mode & SHMSEG_ALLOCATED) == 0 ||
rpr == NULL || shm_prison_cansee(rpr, &shmsegs[i]) != 0) {
shmseg = &empty;
} else if (req->td->td_ucred->cr_prison !=
shmseg->cred->cr_prison) {
bcopy(shmseg, &tmp, sizeof(tmp));
shmseg = &tmp;
shmseg->u.shm_perm.key = IPC_PRIVATE;
bzero(&tshmseg, sizeof(tshmseg));
tshmseg.u.shm_perm.mode = SHMSEG_FREE;
} else {
tshmseg = shmsegs[i];
if (tshmseg.cred->cr_prison != pr)
tshmseg.u.shm_perm.key = IPC_PRIVATE;
}
sbuf_bcat(&sb, shmseg, sizeof(*shmseg));
error = SYSCTL_OUT(req, &tshmseg, sizeof(tshmseg));
if (error != 0)
break;
}
error = sbuf_finish(&sb);
sbuf_delete(&sb);
done:
SYSVSHM_UNLOCK();
return (error);
}