Add kern.ipc.{msqids,semsegs,sema} sysctls for FreeBSD32.
Stop leaking kernel pointers though theses sysctls and make sure that the padding in the structures is zeroed on allocation to avoid other leaks. Reviewed by: gordon, kib Obtained from: CheriBSD MFC after: 1 week Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D13459
This commit is contained in:
parent
49bc1b104e
commit
0fd25723bc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=328799
@ -49,6 +49,18 @@ struct semid_ds32 {
|
||||
int32_t sem_ctime;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct semid_kernel32 {
|
||||
/* Data structure exposed to user space. */
|
||||
struct semid_ds32 u;
|
||||
|
||||
/* Kernel-private components of the semaphore. */
|
||||
int32_t label;
|
||||
int32_t cred;
|
||||
};
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
||||
union semun32 {
|
||||
int val;
|
||||
uint32_t buf;
|
||||
@ -69,6 +81,17 @@ struct msqid_ds32 {
|
||||
int32_t msg_ctime;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct msqid_kernel32 {
|
||||
/* Data structure exposed to user space. */
|
||||
struct msqid_ds32 u;
|
||||
|
||||
/* Kernel-private components of the message queue. */
|
||||
uint32_t label;
|
||||
uint32_t cred;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct shmid_ds32 {
|
||||
struct ipc_perm32 shm_perm;
|
||||
int32_t shm_segsz;
|
||||
@ -80,6 +103,15 @@ struct shmid_ds32 {
|
||||
int32_t shm_ctime;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct shmid_kernel32 {
|
||||
struct shmid_ds32 u;
|
||||
int32_t *object;
|
||||
int32_t *label;
|
||||
int32_t *cred;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct shm_info32 {
|
||||
int32_t used_ids;
|
||||
uint32_t shm_tot;
|
||||
|
@ -229,7 +229,7 @@ msginit()
|
||||
msgmaps = malloc(sizeof(struct msgmap) * msginfo.msgseg, M_MSG, M_WAITOK);
|
||||
msghdrs = malloc(sizeof(struct msg) * msginfo.msgtql, M_MSG, M_WAITOK);
|
||||
msqids = malloc(sizeof(struct msqid_kernel) * msginfo.msgmni, M_MSG,
|
||||
M_WAITOK);
|
||||
M_WAITOK | M_ZERO);
|
||||
|
||||
/*
|
||||
* msginfo.msgssz should be a power of two for efficiency reasons.
|
||||
@ -1418,7 +1418,12 @@ static int
|
||||
sysctl_msqids(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct msqid_kernel tmsqk;
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
struct msqid_kernel32 tmsqk32;
|
||||
#endif
|
||||
struct prison *pr, *rpr;
|
||||
void *outaddr;
|
||||
size_t outsize;
|
||||
int error, i;
|
||||
|
||||
pr = req->td->td_ucred->cr_prison;
|
||||
@ -1435,7 +1440,40 @@ sysctl_msqids(SYSCTL_HANDLER_ARGS)
|
||||
tmsqk.u.msg_perm.key = IPC_PRIVATE;
|
||||
}
|
||||
mtx_unlock(&msq_mtx);
|
||||
error = SYSCTL_OUT(req, &tmsqk, sizeof(tmsqk));
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (SV_CURPROC_FLAG(SV_ILP32)) {
|
||||
bzero(&tmsqk32, sizeof(tmsqk32));
|
||||
freebsd32_ipcperm_out(&tmsqk.u.msg_perm,
|
||||
&tmsqk32.u.msg_perm);
|
||||
/* Don't copy u.msg_first or u.msg_last */
|
||||
CP(tmsqk, tmsqk32, u.msg_cbytes);
|
||||
CP(tmsqk, tmsqk32, u.msg_qnum);
|
||||
CP(tmsqk, tmsqk32, u.msg_qbytes);
|
||||
CP(tmsqk, tmsqk32, u.msg_lspid);
|
||||
CP(tmsqk, tmsqk32, u.msg_lrpid);
|
||||
CP(tmsqk, tmsqk32, u.msg_stime);
|
||||
CP(tmsqk, tmsqk32, u.msg_rtime);
|
||||
CP(tmsqk, tmsqk32, u.msg_ctime);
|
||||
/* Don't copy label or cred */
|
||||
outaddr = &tmsqk32;
|
||||
outsize = sizeof(tmsqk32);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Don't leak kernel pointers */
|
||||
tmsqk.u.msg_first = NULL;
|
||||
tmsqk.u.msg_last = NULL;
|
||||
tmsqk.label = NULL;
|
||||
tmsqk.cred = NULL;
|
||||
/*
|
||||
* XXX: some padding also exists, but we take care to
|
||||
* allocate our pool of msqid_kernel structs with
|
||||
* zeroed memory so this should be OK.
|
||||
*/
|
||||
outaddr = &tmsqk;
|
||||
outsize = sizeof(tmsqk);
|
||||
}
|
||||
error = SYSCTL_OUT(req, outaddr, outsize);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ seminit(void)
|
||||
|
||||
sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK);
|
||||
sema = malloc(sizeof(struct semid_kernel) * seminfo.semmni, M_SEM,
|
||||
M_WAITOK);
|
||||
M_WAITOK | M_ZERO);
|
||||
sema_mtx = malloc(sizeof(struct mtx) * seminfo.semmni, M_SEM,
|
||||
M_WAITOK | M_ZERO);
|
||||
semu = malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK);
|
||||
@ -1487,6 +1487,11 @@ sysctl_sema(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct prison *pr, *rpr;
|
||||
struct semid_kernel tsemak;
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
struct semid_kernel32 tsemak32;
|
||||
#endif
|
||||
void *outaddr;
|
||||
size_t outsize;
|
||||
int error, i;
|
||||
|
||||
pr = req->td->td_ucred->cr_prison;
|
||||
@ -1503,7 +1508,28 @@ sysctl_sema(SYSCTL_HANDLER_ARGS)
|
||||
tsemak.u.sem_perm.key = IPC_PRIVATE;
|
||||
}
|
||||
mtx_unlock(&sema_mtx[i]);
|
||||
error = SYSCTL_OUT(req, &tsemak, sizeof(tsemak));
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (SV_CURPROC_FLAG(SV_ILP32)) {
|
||||
bzero(&tsemak32, sizeof(tsemak32));
|
||||
freebsd32_ipcperm_out(&tsemak.u.sem_perm,
|
||||
&tsemak32.u.sem_perm);
|
||||
/* Don't copy u.sem_base */
|
||||
CP(tsemak, tsemak32, u.sem_nsems);
|
||||
CP(tsemak, tsemak32, u.sem_otime);
|
||||
CP(tsemak, tsemak32, u.sem_ctime);
|
||||
/* Don't copy label or cred */
|
||||
outaddr = &tsemak32;
|
||||
outsize = sizeof(tsemak32);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
tsemak.u.sem_base = NULL;
|
||||
tsemak.label = NULL;
|
||||
tsemak.cred = NULL;
|
||||
outaddr = &tsemak;
|
||||
outsize = sizeof(tsemak);
|
||||
}
|
||||
error = SYSCTL_OUT(req, outaddr, outsize);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
@ -866,7 +866,8 @@ shmrealloc(void)
|
||||
if (shmalloced >= shminfo.shmmni)
|
||||
return;
|
||||
|
||||
newsegs = malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM, M_WAITOK);
|
||||
newsegs = malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM,
|
||||
M_WAITOK | M_ZERO);
|
||||
for (i = 0; i < shmalloced; i++)
|
||||
bcopy(&shmsegs[i], &newsegs[i], sizeof(newsegs[0]));
|
||||
for (; i < shminfo.shmmni; i++) {
|
||||
@ -944,7 +945,8 @@ shminit(void)
|
||||
}
|
||||
}
|
||||
shmalloced = shminfo.shmmni;
|
||||
shmsegs = malloc(shmalloced * sizeof(shmsegs[0]), M_SHM, M_WAITOK);
|
||||
shmsegs = malloc(shmalloced * sizeof(shmsegs[0]), M_SHM,
|
||||
M_WAITOK|M_ZERO);
|
||||
for (i = 0; i < shmalloced; i++) {
|
||||
shmsegs[i].u.shm_perm.mode = SHMSEG_FREE;
|
||||
shmsegs[i].u.shm_perm.seq = 0;
|
||||
@ -1031,7 +1033,12 @@ static int
|
||||
sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct shmid_kernel tshmseg;
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
struct shmid_kernel32 tshmseg32;
|
||||
#endif
|
||||
struct prison *pr, *rpr;
|
||||
void *outaddr;
|
||||
size_t outsize;
|
||||
int error, i;
|
||||
|
||||
SYSVSHM_LOCK();
|
||||
@ -1048,7 +1055,31 @@ sysctl_shmsegs(SYSCTL_HANDLER_ARGS)
|
||||
if (tshmseg.cred->cr_prison != pr)
|
||||
tshmseg.u.shm_perm.key = IPC_PRIVATE;
|
||||
}
|
||||
error = SYSCTL_OUT(req, &tshmseg, sizeof(tshmseg));
|
||||
#ifdef COMPAT_FREEBSD32
|
||||
if (SV_CURPROC_FLAG(SV_ILP32)) {
|
||||
bzero(&tshmseg32, sizeof(tshmseg32));
|
||||
freebsd32_ipcperm_out(&tshmseg.u.shm_perm,
|
||||
&tshmseg32.u.shm_perm);
|
||||
CP(tshmseg, tshmseg32, u.shm_segsz);
|
||||
CP(tshmseg, tshmseg32, u.shm_lpid);
|
||||
CP(tshmseg, tshmseg32, u.shm_cpid);
|
||||
CP(tshmseg, tshmseg32, u.shm_nattch);
|
||||
CP(tshmseg, tshmseg32, u.shm_atime);
|
||||
CP(tshmseg, tshmseg32, u.shm_dtime);
|
||||
CP(tshmseg, tshmseg32, u.shm_ctime);
|
||||
/* Don't copy object, label, or cred */
|
||||
outaddr = &tshmseg32;
|
||||
outsize = sizeof(tshmseg32);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
tshmseg.object = NULL;
|
||||
tshmseg.label = NULL;
|
||||
tshmseg.cred = NULL;
|
||||
outaddr = &tshmseg;
|
||||
outsize = sizeof(tshmseg);
|
||||
}
|
||||
error = SYSCTL_OUT(req, outaddr, outsize);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user