diff options
author | jhb <jhb@FreeBSD.org> | 2006-07-08 19:51:38 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2006-07-08 19:51:38 +0000 |
commit | 5e8693a9761d7a5f4bb3b200c9218a2ad3223215 (patch) | |
tree | 50e5dbd1552ef725ecb5f25f6453ca31d8d3b39c /sys/compat | |
parent | f7c9fd2027eb791acb31a33df08af462cc6322a4 (diff) | |
download | FreeBSD-src-5e8693a9761d7a5f4bb3b200c9218a2ad3223215.zip FreeBSD-src-5e8693a9761d7a5f4bb3b200c9218a2ad3223215.tar.gz |
Rework kern_semctl a bit to always assume the UIO_SYSSPACE case. This
mostly consists of pushing a few copyin's and copyout's up into
__semctl() as all the other callers were already doing the UIO_SYSSPACE
case. This also changes kern_semctl() to set the return value in a passed
in pointer to a register_t rather than td->td_retval[0] directly so that
callers can only set td->td_retval[0] if all the various copyout's succeed.
As a result of these changes, kern_semctl() no longer does copyin/copyout
(except for GETALL/SETALL) so simplify the locking to acquire the semakptr
mutex before the MAC check and hold it all the way until the end of the
big switch statement. The GETALL/SETALL cases have to temporarily drop it
while they do copyin/malloc and copyout. Also, simplify the SETALL case to
remove handling for a non-existent race condition.
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/linux/linux_ipc.c | 23 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_ipc.c | 20 |
2 files changed, 24 insertions, 19 deletions
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c index 2e6dabf..2cd63f0 100644 --- a/sys/compat/linux/linux_ipc.c +++ b/sys/compat/linux/linux_ipc.c @@ -494,6 +494,7 @@ linux_semctl(struct thread *td, struct linux_semctl_args *args) struct l_seminfo linux_seminfo; struct semid_ds semid; union semun semun; + register_t rval; int cmd, error; switch (args->cmd & ~LINUX_IPC_64) { @@ -524,25 +525,25 @@ linux_semctl(struct thread *td, struct linux_semctl_args *args) return (error); linux_to_bsd_semid_ds(&linux_semid, &semid); semun.buf = &semid; - return kern_semctl(td, args->semid, args->semnum, cmd, &semun, - UIO_SYSSPACE); + return (kern_semctl(td, args->semid, args->semnum, cmd, &semun, + td->td_retval)); case LINUX_IPC_STAT: case LINUX_SEM_STAT: - if((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT) + if ((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT) cmd = IPC_STAT; else cmd = SEM_STAT; semun.buf = &semid; error = kern_semctl(td, args->semid, args->semnum, cmd, &semun, - UIO_SYSSPACE); + &rval); if (error) return (error); - td->td_retval[0] = (cmd == SEM_STAT) ? - IXSEQ_TO_IPCID(args->semid, semid.sem_perm) : - 0; 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))); + error = linux_semid_pushdown(args->cmd & LINUX_IPC_64, + &linux_semid, (caddr_t)PTRIN(args->arg.buf)); + if (error == 0) + td->td_retval[0] = (cmd == SEM_STAT) ? rval : 0; + return (error); case LINUX_IPC_INFO: case LINUX_SEM_INFO: bcopy(&seminfo, &linux_seminfo, sizeof(linux_seminfo) ); @@ -567,8 +568,8 @@ linux_semctl(struct thread *td, struct linux_semctl_args *args) args->cmd & ~LINUX_IPC_64); return EINVAL; } - return kern_semctl(td, args->semid, args->semnum, cmd, &semun, - UIO_USERSPACE); + return (kern_semctl(td, args->semid, args->semnum, cmd, &semun, + td->td_retval)); } int diff --git a/sys/compat/svr4/svr4_ipc.c b/sys/compat/svr4/svr4_ipc.c index ad1fb0f..317239c 100644 --- a/sys/compat/svr4/svr4_ipc.c +++ b/sys/compat/svr4/svr4_ipc.c @@ -209,6 +209,7 @@ svr4_semctl(td, v) struct svr4_semid_ds ss; struct semid_ds bs; union semun semun; + register_t rval; int cmd, error; switch (uap->cmd) { @@ -244,21 +245,24 @@ svr4_semctl(td, v) cmd = IPC_STAT; semun.buf = &bs; error = kern_semctl(td, uap->semid, uap->semnum, cmd, &semun, - UIO_SYSSPACE); + &rval); if (error) - return error; + return (error); bsd_to_svr4_semid_ds(&bs, &ss); - return copyout(&ss, uap->arg.buf, sizeof(ss)); + error = copyout(&ss, uap->arg.buf, sizeof(ss)); + if (error == 0) + td->td_retval[0] = rval; + return (error); case SVR4_IPC_SET: cmd = IPC_SET; error = copyin(uap->arg.buf, (caddr_t) &ss, sizeof ss); if (error) - return error; + return (error); svr4_to_bsd_semid_ds(&ss, &bs); semun.buf = &bs; - return kern_semctl(td, uap->semid, uap->semnum, cmd, &semun, - UIO_SYSSPACE); + return (kern_semctl(td, uap->semid, uap->semnum, cmd, &semun, + td->td_retval)); case SVR4_IPC_RMID: cmd = IPC_RMID; @@ -268,8 +272,8 @@ svr4_semctl(td, v) return EINVAL; } - return kern_semctl(td, uap->semid, uap->semnum, cmd, &uap->arg, - UIO_USERSPACE); + return (kern_semctl(td, uap->semid, uap->semnum, cmd, &uap->arg, + td->td_retval)); } struct svr4_sys_semget_args { |