summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-07-08 19:51:38 +0000
committerjhb <jhb@FreeBSD.org>2006-07-08 19:51:38 +0000
commit5e8693a9761d7a5f4bb3b200c9218a2ad3223215 (patch)
tree50e5dbd1552ef725ecb5f25f6453ca31d8d3b39c /sys/compat
parentf7c9fd2027eb791acb31a33df08af462cc6322a4 (diff)
downloadFreeBSD-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.c23
-rw-r--r--sys/compat/svr4/svr4_ipc.c20
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 {
OpenPOWER on IntegriCloud