mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-18 15:30:21 +00:00
- Add a kern_semctl() helper function for __semctl(). It accepts a pointer
to a copied-in copy of the 'union semun' and a uioseg to indicate which memory space the 'buf' pointer of the union points to. This is then used in linux_semctl() and svr4_sys_semctl() to eliminate use of the stackgap. - Mark linux_ipc() and svr4_sys_semsys() MPSAFE.
This commit is contained in:
parent
1727deefa8
commit
49d409a108
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=159991
@ -212,7 +212,7 @@
|
||||
struct l_rusage *rusage); }
|
||||
115 AUE_SWAPOFF MSTD { int linux_swapoff(void); }
|
||||
116 AUE_NULL MSTD { int linux_sysinfo(struct l_sysinfo *info); }
|
||||
117 AUE_NULL STD { int linux_ipc(l_uint what, l_int arg1, \
|
||||
117 AUE_NULL MSTD { int linux_ipc(l_uint what, l_int arg1, \
|
||||
l_int arg2, l_int arg3, void *ptr, \
|
||||
l_long arg5); }
|
||||
118 AUE_FSYNC MNOPROTO { int fsync(int fd); }
|
||||
|
@ -491,69 +491,56 @@ int
|
||||
linux_semctl(struct thread *td, struct linux_semctl_args *args)
|
||||
{
|
||||
struct l_semid_ds linux_semid;
|
||||
struct __semctl_args /* {
|
||||
int semid;
|
||||
int semnum;
|
||||
int cmd;
|
||||
union semun *arg;
|
||||
} */ bsd_args;
|
||||
struct l_seminfo linux_seminfo;
|
||||
int error;
|
||||
union semun *unptr;
|
||||
caddr_t sg;
|
||||
|
||||
sg = stackgap_init();
|
||||
|
||||
/* Make sure the arg parameter can be copied in. */
|
||||
unptr = stackgap_alloc(&sg, sizeof(union semun));
|
||||
bcopy(&args->arg, unptr, sizeof(union semun));
|
||||
|
||||
bsd_args.semid = args->semid;
|
||||
bsd_args.semnum = args->semnum;
|
||||
bsd_args.arg = unptr;
|
||||
struct semid_ds semid;
|
||||
union semun semun;
|
||||
int cmd, error;
|
||||
|
||||
switch (args->cmd & ~LINUX_IPC_64) {
|
||||
case LINUX_IPC_RMID:
|
||||
bsd_args.cmd = IPC_RMID;
|
||||
cmd = IPC_RMID;
|
||||
break;
|
||||
case LINUX_GETNCNT:
|
||||
bsd_args.cmd = GETNCNT;
|
||||
cmd = GETNCNT;
|
||||
break;
|
||||
case LINUX_GETPID:
|
||||
bsd_args.cmd = GETPID;
|
||||
cmd = GETPID;
|
||||
break;
|
||||
case LINUX_GETVAL:
|
||||
bsd_args.cmd = GETVAL;
|
||||
cmd = GETVAL;
|
||||
break;
|
||||
case LINUX_GETZCNT:
|
||||
bsd_args.cmd = GETZCNT;
|
||||
cmd = GETZCNT;
|
||||
break;
|
||||
case LINUX_SETVAL:
|
||||
bsd_args.cmd = SETVAL;
|
||||
cmd = SETVAL;
|
||||
semun.val = args->arg.val;
|
||||
break;
|
||||
case LINUX_IPC_SET:
|
||||
bsd_args.cmd = IPC_SET;
|
||||
cmd = IPC_SET;
|
||||
error = linux_semid_pullup(args->cmd & LINUX_IPC_64,
|
||||
&linux_semid, (caddr_t)PTRIN(args->arg.buf));
|
||||
if (error)
|
||||
return (error);
|
||||
unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
|
||||
linux_to_bsd_semid_ds(&linux_semid, unptr->buf);
|
||||
return __semctl(td, &bsd_args);
|
||||
linux_to_bsd_semid_ds(&linux_semid, &semid);
|
||||
semun.buf = &semid;
|
||||
return kern_semctl(td, args->semid, args->semnum, cmd, &semun,
|
||||
UIO_SYSSPACE);
|
||||
case LINUX_IPC_STAT:
|
||||
case LINUX_SEM_STAT:
|
||||
if((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT)
|
||||
bsd_args.cmd = IPC_STAT;
|
||||
cmd = IPC_STAT;
|
||||
else
|
||||
bsd_args.cmd = SEM_STAT;
|
||||
unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
|
||||
error = __semctl(td, &bsd_args);
|
||||
cmd = SEM_STAT;
|
||||
semun.buf = &semid;
|
||||
error = kern_semctl(td, args->semid, args->semnum, cmd, &semun,
|
||||
UIO_SYSSPACE);
|
||||
if (error)
|
||||
return error;
|
||||
td->td_retval[0] = (bsd_args.cmd == SEM_STAT) ?
|
||||
IXSEQ_TO_IPCID(bsd_args.semid, unptr->buf->sem_perm) :
|
||||
return (error);
|
||||
td->td_retval[0] = (cmd == SEM_STAT) ?
|
||||
IXSEQ_TO_IPCID(args->semid, semid.sem_perm) :
|
||||
0;
|
||||
bsd_to_linux_semid_ds(unptr->buf, &linux_semid);
|
||||
bsd_to_linux_semid_ds(&semid, &linux_semid);
|
||||
return (linux_semid_pushdown(args->cmd & LINUX_IPC_64,
|
||||
&linux_semid, (caddr_t)PTRIN(args->arg.buf)));
|
||||
case LINUX_IPC_INFO:
|
||||
@ -580,7 +567,8 @@ linux_semctl(struct thread *td, struct linux_semctl_args *args)
|
||||
args->cmd & ~LINUX_IPC_64);
|
||||
return EINVAL;
|
||||
}
|
||||
return __semctl(td, &bsd_args);
|
||||
return kern_semctl(td, args->semid, args->semnum, cmd, &semun,
|
||||
UIO_USERSPACE);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -105,8 +105,6 @@ static void bsd_to_svr4_semid_ds(const struct semid_ds *,
|
||||
struct svr4_semid_ds *);
|
||||
static void svr4_to_bsd_semid_ds(const struct svr4_semid_ds *,
|
||||
struct semid_ds *);
|
||||
static int svr4_setsemun(caddr_t *sgp, union semun **argp,
|
||||
union semun *usp);
|
||||
static int svr4_semop(struct thread *, void *);
|
||||
static int svr4_semget(struct thread *, void *);
|
||||
static int svr4_semctl(struct thread *, void *);
|
||||
@ -194,16 +192,6 @@ svr4_to_bsd_semid_ds(sds, bds)
|
||||
bds->sem_pad2 = sds->sem_pad2;
|
||||
}
|
||||
|
||||
static int
|
||||
svr4_setsemun(sgp, argp, usp)
|
||||
caddr_t *sgp;
|
||||
union semun **argp;
|
||||
union semun *usp;
|
||||
{
|
||||
*argp = stackgap_alloc(sgp, sizeof(union semun));
|
||||
return copyout((caddr_t)usp, *argp, sizeof(union semun));
|
||||
}
|
||||
|
||||
struct svr4_sys_semctl_args {
|
||||
int what;
|
||||
int semid;
|
||||
@ -217,108 +205,71 @@ svr4_semctl(td, v)
|
||||
struct thread *td;
|
||||
void *v;
|
||||
{
|
||||
int error;
|
||||
struct svr4_sys_semctl_args *uap = v;
|
||||
struct __semctl_args ap;
|
||||
struct svr4_semid_ds ss;
|
||||
struct semid_ds bs, *bsp;
|
||||
caddr_t sg = stackgap_init();
|
||||
|
||||
ap.semid = uap->semid;
|
||||
ap.semnum = uap->semnum;
|
||||
struct semid_ds bs;
|
||||
union semun semun;
|
||||
int cmd, error;
|
||||
|
||||
switch (uap->cmd) {
|
||||
case SVR4_SEM_GETZCNT:
|
||||
cmd = GETZCNT;
|
||||
break;
|
||||
|
||||
case SVR4_SEM_GETNCNT:
|
||||
cmd = GETNCNT;
|
||||
break;
|
||||
|
||||
case SVR4_SEM_GETPID:
|
||||
cmd = GETPID;
|
||||
break;
|
||||
|
||||
case SVR4_SEM_GETVAL:
|
||||
switch (uap->cmd) {
|
||||
case SVR4_SEM_GETZCNT:
|
||||
ap.cmd = GETZCNT;
|
||||
break;
|
||||
case SVR4_SEM_GETNCNT:
|
||||
ap.cmd = GETNCNT;
|
||||
break;
|
||||
case SVR4_SEM_GETPID:
|
||||
ap.cmd = GETPID;
|
||||
break;
|
||||
case SVR4_SEM_GETVAL:
|
||||
ap.cmd = GETVAL;
|
||||
break;
|
||||
}
|
||||
return __semctl(td, &ap);
|
||||
cmd = GETVAL;
|
||||
break;
|
||||
|
||||
case SVR4_SEM_SETVAL:
|
||||
error = svr4_setsemun(&sg, &ap.arg, &uap->arg);
|
||||
if (error)
|
||||
return error;
|
||||
ap.cmd = SETVAL;
|
||||
return __semctl(td, &ap);
|
||||
cmd = SETVAL;
|
||||
break;
|
||||
|
||||
case SVR4_SEM_GETALL:
|
||||
error = svr4_setsemun(&sg, &ap.arg, &uap->arg);
|
||||
if (error)
|
||||
return error;
|
||||
ap.cmd = GETVAL;
|
||||
return __semctl(td, &ap);
|
||||
cmd = GETVAL;
|
||||
break;
|
||||
|
||||
case SVR4_SEM_SETALL:
|
||||
error = svr4_setsemun(&sg, &ap.arg, &uap->arg);
|
||||
if (error)
|
||||
return error;
|
||||
ap.cmd = SETVAL;
|
||||
return __semctl(td, &ap);
|
||||
cmd = SETVAL;
|
||||
break;
|
||||
|
||||
case SVR4_IPC_STAT:
|
||||
ap.cmd = IPC_STAT;
|
||||
bsp = stackgap_alloc(&sg, sizeof(bs));
|
||||
error = svr4_setsemun(&sg, &ap.arg,
|
||||
(union semun *)&bsp);
|
||||
cmd = IPC_STAT;
|
||||
semun.buf = &bs;
|
||||
error = kern_semctl(td, uap->semid, uap->semnum, cmd, &semun,
|
||||
UIO_SYSSPACE);
|
||||
if (error)
|
||||
return error;
|
||||
if ((error = __semctl(td, &ap)) != 0)
|
||||
return error;
|
||||
error = copyin((caddr_t)bsp, (caddr_t)&bs, sizeof(bs));
|
||||
if (error)
|
||||
return error;
|
||||
bsd_to_svr4_semid_ds(&bs, &ss);
|
||||
return copyout(&ss, uap->arg.buf, sizeof(ss));
|
||||
|
||||
case SVR4_IPC_SET:
|
||||
ap.cmd = IPC_SET;
|
||||
bsp = stackgap_alloc(&sg, sizeof(bs));
|
||||
error = svr4_setsemun(&sg, &ap.arg,
|
||||
(union semun *)&bsp);
|
||||
if (error)
|
||||
return error;
|
||||
cmd = IPC_SET;
|
||||
error = copyin(uap->arg.buf, (caddr_t) &ss, sizeof ss);
|
||||
if (error)
|
||||
return error;
|
||||
svr4_to_bsd_semid_ds(&ss, &bs);
|
||||
error = copyout(&bs, bsp, sizeof(bs));
|
||||
if (error)
|
||||
return error;
|
||||
return __semctl(td, &ap);
|
||||
semun.buf = &bs;
|
||||
return kern_semctl(td, uap->semid, uap->semnum, cmd, &semun,
|
||||
UIO_SYSSPACE);
|
||||
|
||||
case SVR4_IPC_RMID:
|
||||
ap.cmd = IPC_RMID;
|
||||
bsp = stackgap_alloc(&sg, sizeof(bs));
|
||||
error = svr4_setsemun(&sg, &ap.arg,
|
||||
(union semun *)&bsp);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyin(uap->arg.buf, &ss, sizeof ss);
|
||||
if (error)
|
||||
return error;
|
||||
svr4_to_bsd_semid_ds(&ss, &bs);
|
||||
error = copyout(&bs, bsp, sizeof(bs));
|
||||
if (error)
|
||||
return error;
|
||||
return __semctl(td, &ap);
|
||||
cmd = IPC_RMID;
|
||||
break;
|
||||
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return kern_semctl(td, uap->semid, uap->semnum, cmd, &uap->arg,
|
||||
UIO_USERSPACE);
|
||||
}
|
||||
|
||||
struct svr4_sys_semget_args {
|
||||
|
@ -102,7 +102,7 @@
|
||||
51 AUE_NULL UNIMPL acct
|
||||
52 AUE_NULL STD { int svr4_sys_shmsys(int what, int a2, \
|
||||
int a3, int a4, int a5); }
|
||||
53 AUE_NULL STD { int svr4_sys_semsys(int what, int a2, \
|
||||
53 AUE_NULL MSTD { int svr4_sys_semsys(int what, int a2, \
|
||||
int a3, int a4, int a5); }
|
||||
54 AUE_NULL STD { int svr4_sys_ioctl(int fd, u_long com, \
|
||||
caddr_t data); }
|
||||
|
@ -213,7 +213,7 @@
|
||||
struct l_rusage *rusage); }
|
||||
115 AUE_SWAPOFF MSTD { int linux_swapoff(void); }
|
||||
116 AUE_NULL MSTD { int linux_sysinfo(struct l_sysinfo *info); }
|
||||
117 AUE_NULL STD { int linux_ipc(l_uint what, l_int arg1, \
|
||||
117 AUE_NULL MSTD { int linux_ipc(l_uint what, l_int arg1, \
|
||||
l_int arg2, l_int arg3, void *ptr, \
|
||||
l_long arg5); }
|
||||
118 AUE_FSYNC MNOPROTO { int fsync(int fd); }
|
||||
|
@ -53,8 +53,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/sem.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/mac.h>
|
||||
@ -554,12 +556,35 @@ __semctl(td, uap)
|
||||
struct thread *td;
|
||||
struct __semctl_args *uap;
|
||||
{
|
||||
int semid = uap->semid;
|
||||
int semnum = uap->semnum;
|
||||
int cmd = uap->cmd;
|
||||
u_short *array;
|
||||
union semun *arg = uap->arg;
|
||||
union semun real_arg;
|
||||
union semun *arg;
|
||||
int error;
|
||||
|
||||
switch (uap->cmd) {
|
||||
case SEM_STAT:
|
||||
case IPC_SET:
|
||||
case IPC_STAT:
|
||||
case GETALL:
|
||||
case SETVAL:
|
||||
case SETALL:
|
||||
error = copyin(uap->arg, &real_arg, sizeof(real_arg));
|
||||
if (error)
|
||||
return (error);
|
||||
arg = &real_arg;
|
||||
break;
|
||||
default:
|
||||
arg = NULL;
|
||||
break;
|
||||
}
|
||||
return (kern_semctl(td, uap->semid, uap->semnum, uap->cmd, arg,
|
||||
UIO_USERSPACE));
|
||||
}
|
||||
|
||||
int
|
||||
kern_semctl(struct thread *td, int semid, int semnum, int cmd, union semun *arg,
|
||||
enum uio_seg bufseg)
|
||||
{
|
||||
u_short *array;
|
||||
struct ucred *cred = td->td_ucred;
|
||||
int i, rval, error;
|
||||
struct semid_ds sbuf;
|
||||
@ -578,8 +603,6 @@ __semctl(td, uap)
|
||||
case SEM_STAT:
|
||||
if (semid < 0 || semid >= seminfo.semmni)
|
||||
return (EINVAL);
|
||||
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
return (error);
|
||||
semakptr = &sema[semid];
|
||||
sema_mtxp = &sema_mtx[semid];
|
||||
mtx_lock(sema_mtxp);
|
||||
@ -598,8 +621,11 @@ __semctl(td, uap)
|
||||
}
|
||||
#endif
|
||||
mtx_unlock(sema_mtxp);
|
||||
error = copyout(&semakptr->u, real_arg.buf,
|
||||
sizeof(struct semid_ds));
|
||||
if (bufseg == UIO_USERSPACE)
|
||||
error = copyout(&semakptr->u, arg->buf,
|
||||
sizeof(struct semid_ds));
|
||||
else
|
||||
bcopy(&semakptr->u, arg->buf, sizeof(struct semid_ds));
|
||||
rval = IXSEQ_TO_IPCID(semid, semakptr->u.sem_perm);
|
||||
if (error == 0)
|
||||
td->td_retval[0] = rval;
|
||||
@ -629,7 +655,7 @@ __semctl(td, uap)
|
||||
switch (cmd) {
|
||||
case IPC_RMID:
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
|
||||
goto done2;
|
||||
@ -654,12 +680,14 @@ __semctl(td, uap)
|
||||
break;
|
||||
|
||||
case IPC_SET:
|
||||
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
goto done2;
|
||||
if ((error = copyin(real_arg.buf, &sbuf, sizeof(sbuf))) != 0)
|
||||
goto done2;
|
||||
if (bufseg == UIO_USERSPACE) {
|
||||
error = copyin(arg->buf, &sbuf, sizeof(sbuf));
|
||||
if (error)
|
||||
goto done2;
|
||||
} else
|
||||
bcopy(arg->buf, &sbuf, sizeof(sbuf));
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M)))
|
||||
goto done2;
|
||||
@ -671,22 +699,23 @@ __semctl(td, uap)
|
||||
break;
|
||||
|
||||
case IPC_STAT:
|
||||
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
goto done2;
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
|
||||
goto done2;
|
||||
sbuf = semakptr->u;
|
||||
mtx_unlock(sema_mtxp);
|
||||
error = copyout(&semakptr->u, real_arg.buf,
|
||||
sizeof(struct semid_ds));
|
||||
if (bufseg == UIO_USERSPACE)
|
||||
error = copyout(&semakptr->u, arg->buf,
|
||||
sizeof(struct semid_ds));
|
||||
else
|
||||
bcopy(&semakptr->u, arg->buf, sizeof(struct semid_ds));
|
||||
break;
|
||||
|
||||
case GETNCNT:
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
|
||||
goto done2;
|
||||
@ -699,7 +728,7 @@ __semctl(td, uap)
|
||||
|
||||
case GETPID:
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
|
||||
goto done2;
|
||||
@ -712,7 +741,7 @@ __semctl(td, uap)
|
||||
|
||||
case GETVAL:
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
|
||||
goto done2;
|
||||
@ -724,25 +753,31 @@ __semctl(td, uap)
|
||||
break;
|
||||
|
||||
case GETALL:
|
||||
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
goto done2;
|
||||
/*
|
||||
* Given the fact that this copies out a variable amount
|
||||
* of data into userland, I don't see any feasible way of
|
||||
* doing this with a kmem copy of the userland buffer.
|
||||
*/
|
||||
if (bufseg == UIO_SYSSPACE)
|
||||
return (EINVAL);
|
||||
|
||||
array = malloc(sizeof(*array) * semakptr->u.sem_nsems, M_TEMP,
|
||||
M_WAITOK);
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
|
||||
goto done2;
|
||||
for (i = 0; i < semakptr->u.sem_nsems; i++)
|
||||
array[i] = semakptr->u.sem_base[i].semval;
|
||||
mtx_unlock(sema_mtxp);
|
||||
error = copyout(array, real_arg.array,
|
||||
i * sizeof(real_arg.array[0]));
|
||||
error = copyout(array, arg->array,
|
||||
i * sizeof(arg->array[0]));
|
||||
break;
|
||||
|
||||
case GETZCNT:
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R)))
|
||||
goto done2;
|
||||
@ -754,10 +789,8 @@ __semctl(td, uap)
|
||||
break;
|
||||
|
||||
case SETVAL:
|
||||
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
goto done2;
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W)))
|
||||
goto done2;
|
||||
@ -765,11 +798,11 @@ __semctl(td, uap)
|
||||
error = EINVAL;
|
||||
goto done2;
|
||||
}
|
||||
if (real_arg.val < 0 || real_arg.val > seminfo.semvmx) {
|
||||
if (arg->val < 0 || arg->val > seminfo.semvmx) {
|
||||
error = ERANGE;
|
||||
goto done2;
|
||||
}
|
||||
semakptr->u.sem_base[semnum].semval = real_arg.val;
|
||||
semakptr->u.sem_base[semnum].semval = arg->val;
|
||||
SEMUNDO_LOCK();
|
||||
semundo_clear(semid, semnum);
|
||||
SEMUNDO_UNLOCK();
|
||||
@ -777,20 +810,25 @@ __semctl(td, uap)
|
||||
break;
|
||||
|
||||
case SETALL:
|
||||
/*
|
||||
* Given the fact that this copies in variable amounts of
|
||||
* userland data in a loop, I don't see any feasible way
|
||||
* of doing this with a kmem copy of the userland buffer.
|
||||
*/
|
||||
if (bufseg == UIO_SYSSPACE)
|
||||
return (EINVAL);
|
||||
mtx_lock(sema_mtxp);
|
||||
raced:
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
count = semakptr->u.sem_nsems;
|
||||
mtx_unlock(sema_mtxp);
|
||||
if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0)
|
||||
goto done2;
|
||||
array = malloc(sizeof(*array) * count, M_TEMP, M_WAITOK);
|
||||
error = copyin(real_arg.array, array, count * sizeof(*array));
|
||||
error = copyin(arg->array, array, count * sizeof(*array));
|
||||
if (error)
|
||||
break;
|
||||
mtx_lock(sema_mtxp);
|
||||
if ((error = semvalid(uap->semid, semakptr)) != 0)
|
||||
if ((error = semvalid(semid, semakptr)) != 0)
|
||||
goto done2;
|
||||
/* we could have raced? */
|
||||
if (count != semakptr->u.sem_nsems) {
|
||||
|
@ -41,6 +41,7 @@ struct msghdr;
|
||||
struct msqid_ds;
|
||||
struct rlimit;
|
||||
struct rusage;
|
||||
union semun;
|
||||
struct sockaddr;
|
||||
struct stat;
|
||||
struct kevent;
|
||||
@ -123,6 +124,8 @@ int kern_rename(struct thread *td, char *from, char *to,
|
||||
int kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg);
|
||||
int kern_sched_rr_get_interval(struct thread *td, pid_t pid,
|
||||
struct timespec *ts);
|
||||
int kern_semctl(struct thread *td, int semid, int semnum, int cmd,
|
||||
union semun *arg, enum uio_seg bufseg);
|
||||
int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
|
||||
fd_set *fd_ex, struct timeval *tvp);
|
||||
int kern_sendfile(struct thread *td, struct sendfile_args *uap,
|
||||
|
Loading…
Reference in New Issue
Block a user