diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-07-14 23:45:12 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-07-14 23:45:12 +0000 |
commit | 1f938370d0925923855d0aa555c61e0021e813d4 (patch) | |
tree | dd1070107bd0640c4efcc4942d08cd1a28e898ea /sys/compat/common | |
parent | 2936cdf8e0c9bb397150cbee125b4456fee40aab (diff) |
Because mode_t is used in struct ipc_perm we need new versions of
the msgctl, semctl, and shmctl system calls. This moves the old
versions to COMPAT_35 and adds new ones.
WARNING: While this fixes things like shared memory in the X server
for old (pre-mode_t change) binaries, it will break binaries that
use shared memory built between the time of the mode_t change (Jul
13th) and now. If you rebuild X during that interval you will need
to do it again after updating the rest of userland.
Diffstat (limited to 'sys/compat/common')
-rw-r--r-- | sys/compat/common/kern_ipc_35.c | 186 |
1 files changed, 185 insertions, 1 deletions
diff --git a/sys/compat/common/kern_ipc_35.c b/sys/compat/common/kern_ipc_35.c index d3956b24070..b926fd866d5 100644 --- a/sys/compat/common/kern_ipc_35.c +++ b/sys/compat/common/kern_ipc_35.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_ipc_35.c,v 1.1 2004/05/03 17:38:48 millert Exp $ */ +/* $OpenBSD: kern_ipc_35.c,v 1.2 2004/07/14 23:45:11 millert Exp $ */ /* * Copyright (c) 2004 Todd C. Miller <Todd.Miller@courtesan.com> @@ -20,6 +20,7 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/proc.h> +#include <sys/msg.h> #include <sys/sem.h> #include <sys/shm.h> @@ -77,3 +78,186 @@ compat_35_sys_semop(struct proc *p, void *v, register_t *retval) return (sys_semop(p, &semop_args, retval)); } #endif + +/* + * Convert between new and old struct {msq,sem,shm}id_ds (both ways) + */ +#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) +#define cvt_ds(to, from, type) do { \ + (to)->type##_perm.cuid = (from)->type##_perm.cuid; \ + (to)->type##_perm.cgid = (from)->type##_perm.cgid; \ + (to)->type##_perm.uid = (from)->type##_perm.uid; \ + (to)->type##_perm.gid = (from)->type##_perm.gid; \ + (to)->type##_perm.mode = (from)->type##_perm.mode & 0xffffU; \ + (to)->type##_perm.seq = (from)->type##_perm.seq; \ + (to)->type##_perm.key = (from)->type##_perm.key; \ + bcopy((caddr_t)(from) + sizeof((from)->type##_perm), \ + (caddr_t)(to) + sizeof((to)->type##_perm), \ + sizeof(*(to)) - sizeof((to)->type##_perm)); \ +} while (0) +#endif /* SYSVMSG || SYSVSEM || SYSVSHM */ + +#ifdef SYSVMSG +/* + * Copy a struct msqid_ds35 from userland and convert to struct msqid_ds + */ +static int +msqid_copyin(const void *uaddr, void *kaddr, size_t len) +{ + struct msqid_ds *msqbuf = kaddr; + struct msqid_ds35 omsqbuf; + int error; + + if (len != sizeof(struct msqid_ds)) + return (EFAULT); + if ((error = copyin(uaddr, &omsqbuf, sizeof(omsqbuf))) == 0) + cvt_ds(msqbuf, &omsqbuf, msg); + return (error); +} + +/* + * Convert a struct msqid_ds to struct msqid_ds35 and copy to userland + */ +static int +msqid_copyout(const void *kaddr, void *uaddr, size_t len) +{ + const struct msqid_ds *msqbuf = kaddr; + struct msqid_ds35 omsqbuf; + + if (len != sizeof(struct msqid_ds)) + return (EFAULT); + cvt_ds(&omsqbuf, msqbuf, msg); + return (copyout(&omsqbuf, uaddr, sizeof(omsqbuf))); +} + +/* + * OpenBSD 3.5 msgctl(2) with 16bit mode_t in struct ipcperm. + */ +int +compat_35_sys_msgctl(struct proc *p, void *v, register_t *retval) +{ + struct compat_35_sys_msgctl_args /* { + syscallarg(int) msqid; + syscallarg(int) cmd; + syscallarg(struct msqid_ds35 *) buf; + } */ *uap = v; + + return (msgctl1(p, SCARG(uap, msqid), SCARG(uap, cmd), + (caddr_t)SCARG(uap, buf), msqid_copyin, msqid_copyout)); +} +#endif /* SYSVMSG */ + +#ifdef SYSVSEM +/* + * Copy a struct semid_ds35 from userland and convert to struct semid_ds + */ +static int +semid_copyin(const void *uaddr, void *kaddr, size_t len) +{ + struct semid_ds *sembuf = kaddr; + struct semid_ds35 osembuf; + int error; + + if (len != sizeof(struct semid_ds)) + return (EFAULT); + if ((error = copyin(uaddr, &osembuf, sizeof(osembuf))) == 0) + cvt_ds(sembuf, &osembuf, sem); + return (error); +} + +/* + * Convert a struct semid_ds to struct semid_ds35 and copy to userland + */ +static int +semid_copyout(const void *kaddr, void *uaddr, size_t len) +{ + const struct semid_ds *sembuf = kaddr; + struct semid_ds35 osembuf; + + if (len != sizeof(struct semid_ds)) + return (EFAULT); + cvt_ds(&osembuf, sembuf, sem); + return (copyout(&osembuf, uaddr, sizeof(osembuf))); +} + +/* + * OpenBSD 3.5 semctl(2) with 16bit mode_t in struct ipcperm. + */ +int +compat_35_sys___semctl(struct proc *p, void *v, register_t *retval) +{ + struct compat_35_sys___semctl_args /* { + syscallarg(int) semid; + syscallarg(int) semnum; + syscallarg(int) cmd; + syscallarg(union semun *) arg; + } */ *uap = v; + union semun arg; + int error = 0, cmd = SCARG(uap, cmd); + + switch (cmd) { + case IPC_SET: + case IPC_STAT: + case GETALL: + case SETVAL: + case SETALL: + error = copyin(SCARG(uap, arg), &arg, sizeof(arg)); + break; + } + if (error == 0) { + error = semctl1(p, SCARG(uap, semid), SCARG(uap, semnum), + cmd, &arg, retval, semid_copyin, semid_copyout); + } + return (error); +} +#endif /* SYSVSEM */ + +#ifdef SYSVSHM +/* + * Copy a struct shmid_ds35 from userland and convert to struct shmid_ds + */ +static int +shmid_copyin(const void *uaddr, void *kaddr, size_t len) +{ + struct shmid_ds *shmbuf = kaddr; + struct shmid_ds35 oshmbuf; + int error; + + if (len != sizeof(struct shmid_ds)) + return (EFAULT); + if ((error = copyin(uaddr, &oshmbuf, sizeof(oshmbuf))) == 0) + cvt_ds(shmbuf, &oshmbuf, shm); + return (error); +} + +/* + * Convert a struct shmid_ds to struct shmid_ds35 and copy to userland + */ +static int +shmid_copyout(const void *kaddr, void *uaddr, size_t len) +{ + const struct shmid_ds *shmbuf = kaddr; + struct shmid_ds35 oshmbuf; + + if (len != sizeof(struct shmid_ds)) + return (EFAULT); + cvt_ds(&oshmbuf, shmbuf, shm); + return (copyout(&oshmbuf, uaddr, sizeof(oshmbuf))); +} + +/* + * OpenBSD 3.5 shmctl(2) with 16bit mode_t in struct ipcperm. + */ +int +compat_35_sys_shmctl(struct proc *p, void *v, register_t *retval) +{ + struct compat_35_sys_shmctl_args /* { + syscallarg(int) shmid; + syscallarg(int) cmd; + syscallarg(struct shmid_ds35 *) buf; + } */ *uap = v; + + return (shmctl1(p, SCARG(uap, shmid), SCARG(uap, cmd), + (caddr_t)SCARG(uap, buf), shmid_copyin, shmid_copyout)); +} +#endif /* SYSVSHM */ |