diff options
author | jhb <jhb@FreeBSD.org> | 2009-06-24 21:10:52 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2009-06-24 21:10:52 +0000 |
commit | 6f52fe78fb1fc421bc6abb38286a4483aac9cdc0 (patch) | |
tree | 9bcf2215ae277f261cc7bf33f2dde8db38fe41c4 | |
parent | ce189363a0ec4e65f27076207a88142a8554bfbb (diff) | |
download | FreeBSD-src-6f52fe78fb1fc421bc6abb38286a4483aac9cdc0.zip FreeBSD-src-6f52fe78fb1fc421bc6abb38286a4483aac9cdc0.tar.gz |
Change the ABI of some of the structures used by the SYSV IPC API:
- The uid/cuid members of struct ipc_perm are now uid_t instead of unsigned
short.
- The gid/cgid members of struct ipc_perm are now gid_t instead of unsigned
short.
- The mode member of struct ipc_perm is now mode_t instead of unsigned short
(this is merely a style bug).
- The rather dubious padding fields for ABI compat with SV/I386 have been
removed from struct msqid_ds and struct semid_ds.
- The shm_segsz member of struct shmid_ds is now a size_t instead of an
int. This removes the need for the shm_bsegsz member in struct
shmid_kernel and should allow for complete support of SYSV SHM regions
>= 2GB.
- The shm_nattch member of struct shmid_ds is now an int instead of a
short.
- The shm_internal member of struct shmid_ds is now gone. The internal
VM object pointer for SHM regions has been moved into struct
shmid_kernel.
- The existing __semctl(), msgctl(), and shmctl() system call entries are
now marked COMPAT7 and new versions of those system calls which support
the new ABI are now present.
- The new system calls are assigned to the FBSD-1.1 version in libc. The
FBSD-1.0 symbols in libc now refer to the old COMPAT7 system calls.
- A simplistic framework for tagging system calls with compatibility
symbol versions has been added to libc. Version tags are added to
system calls by adding an appropriate __sym_compat() entry to
src/lib/libc/incldue/compat.h. [1]
PR: kern/16195 kern/113218 bin/129855
Reviewed by: arch@, rwatson
Discussed with: kan, kib [1]
-rw-r--r-- | lib/libc/gen/Symbol.map | 2 | ||||
-rw-r--r-- | lib/libc/gen/semctl.c | 30 | ||||
-rw-r--r-- | lib/libc/include/compat.h | 48 | ||||
-rw-r--r-- | lib/libc/sys/Makefile.inc | 6 | ||||
-rw-r--r-- | lib/libc/sys/Symbol.map | 6 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_ipc.h | 78 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_misc.c | 289 | ||||
-rw-r--r-- | sys/compat/freebsd32/syscalls.master | 16 | ||||
-rw-r--r-- | sys/compat/linux/linux_ipc.c | 24 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_ipc.c | 33 | ||||
-rw-r--r-- | sys/i386/ibcs2/ibcs2_ipc.c | 6 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 18 | ||||
-rw-r--r-- | sys/kern/sysv_ipc.c | 31 | ||||
-rw-r--r-- | sys/kern/sysv_msg.c | 63 | ||||
-rw-r--r-- | sys/kern/sysv_sem.c | 87 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 111 | ||||
-rw-r--r-- | sys/sys/ipc.h | 24 | ||||
-rw-r--r-- | sys/sys/msg.h | 25 | ||||
-rw-r--r-- | sys/sys/sem.h | 27 | ||||
-rw-r--r-- | sys/sys/shm.h | 21 | ||||
-rw-r--r-- | usr.bin/ipcs/ipcs.c | 2 |
21 files changed, 818 insertions, 129 deletions
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 2d23153..4f1efaf 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -247,7 +247,6 @@ FBSD_1.0 { sem_timedwait; sem_post; sem_getvalue; - semctl; setdomainname; sethostname; longjmperror; @@ -362,6 +361,7 @@ FBSD_1.1 { posix_spawnattr_setsigdefault; posix_spawnattr_setsigmask; posix_spawnp; + semctl; tcgetsid; tcsetsid; }; diff --git a/lib/libc/gen/semctl.c b/lib/libc/gen/semctl.c index 4b5283f..156d18c 100644 --- a/lib/libc/gen/semctl.c +++ b/lib/libc/gen/semctl.c @@ -29,15 +29,19 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#define _WANT_SEMUN_OLD + #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> #include <stdarg.h> #include <stdlib.h> -extern int __semctl(int semid, int semnum, int cmd, union semun *arg); +int __semctl(int semid, int semnum, int cmd, union semun *arg); +int freebsd7___semctl(int semid, int semnum, int cmd, union semun_old *arg); -int semctl(int semid, int semnum, int cmd, ...) +int +semctl(int semid, int semnum, int cmd, ...) { va_list ap; union semun semun; @@ -55,3 +59,25 @@ int semctl(int semid, int semnum, int cmd, ...) return (__semctl(semid, semnum, cmd, semun_ptr)); } + +int +freebsd7_semctl(int semid, int semnum, int cmd, ...) +{ + va_list ap; + union semun_old semun; + union semun_old *semun_ptr; + + va_start(ap, cmd); + if (cmd == IPC_SET || cmd == IPC_STAT || cmd == GETALL + || cmd == SETVAL || cmd == SETALL) { + semun = va_arg(ap, union semun_old); + semun_ptr = &semun; + } else { + semun_ptr = NULL; + } + va_end(ap); + + return (freebsd7___semctl(semid, semnum, cmd, semun_ptr)); +} + +__sym_compat(semctl, freebsd7_semctl, FBSD_1.0); diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h new file mode 100644 index 0000000..13c1d20 --- /dev/null +++ b/lib/libc/include/compat.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2009 Advanced Computing Technologies LLC + * Written by: John H. Baldwin <jhb@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * This file defines compatiblity symbol versions for old system calls. It + * is included in all generated system call files. + */ + +#ifndef __LIBC_COMPAT_H__ +#define __LIBC_COMPAT_H__ + +#define __sym_compat(sym,impl,verid) \ + .symver impl , sym @ verid + +__sym_compat(__semctl, freebsd7___semctl, FBSD_1.0); +__sym_compat(msgctl, freebsd7_msgctl, FBSD_1.0); +__sym_compat(shmctl, freebsd7_shmctl, FBSD_1.0); + +#undef __sym_compat + +#endif /* __LIBC_COMPAT_H__ */ + diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 7e65aa4..ad6b06e 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -53,11 +53,13 @@ SYM_MAPS+= ${.CURDIR}/sys/Symbol.map CLEANFILES+= ${SASM} ${SPSEUDO} ${SASM}: - printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' > ${.TARGET} + printf '#include "compat.h"\n' > ${.TARGET} + printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' >> ${.TARGET} ${SPSEUDO}: + printf '#include "compat.h"\n' > ${.TARGET} printf '#include "SYS.h"\nPSEUDO(${.PREFIX:S/_//})\n' \ - > ${.TARGET} + >> ${.TARGET} MAN+= abort2.2 accept.2 access.2 acct.2 adjtime.2 \ aio_cancel.2 aio_error.2 aio_read.2 aio_return.2 \ diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index d7da905..88bc779 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -31,7 +31,6 @@ FBSD_1.0 { __mac_set_file; __mac_set_link; __mac_set_proc; - __semctl; __setugid; __syscall; __sysctl; @@ -184,7 +183,6 @@ FBSD_1.0 { modstat; mount; mprotect; - msgctl; msgget; msgrcv; msgsnd; @@ -267,7 +265,6 @@ FBSD_1.0 { shm_open; shm_unlink; shmat; - shmctl; shmdt; shmget; shmsys; @@ -332,6 +329,7 @@ FBSD_1.0 { }; FBSD_1.1 { + __semctl; closefrom; cpuset; cpuset_getid; @@ -351,10 +349,12 @@ FBSD_1.1 { mkdirat; mkfifoat; mknodat; + msgctl; openat; readlinkat; renameat; setfib; + shmctl; symlinkat; unlinkat; }; diff --git a/sys/compat/freebsd32/freebsd32_ipc.h b/sys/compat/freebsd32/freebsd32_ipc.h index 93b5409..2b07494 100644 --- a/sys/compat/freebsd32/freebsd32_ipc.h +++ b/sys/compat/freebsd32/freebsd32_ipc.h @@ -30,11 +30,11 @@ #define _COMPAT_FREEBSD32_FREEBSD32_IPC_H_ struct ipc_perm32 { - uint16_t cuid; - uint16_t cgid; - uint16_t uid; - uint16_t gid; - uint16_t mode; + uid_t cuid; + gid_t cgid; + uid_t uid; + gid_t gid; + mode_t mode; uint16_t seq; uint32_t key; }; @@ -44,10 +44,7 @@ struct semid_ds32 { uint32_t sem_base; unsigned short sem_nsems; int32_t sem_otime; - int32_t sem_pad1; int32_t sem_ctime; - int32_t sem_pad2; - int32_t sem_pad3[4]; }; union semun32 { @@ -66,24 +63,19 @@ struct msqid_ds32 { pid_t msg_lspid; pid_t msg_lrpid; int32_t msg_stime; - int32_t msg_pad1; int32_t msg_rtime; - int32_t msg_pad2; int32_t msg_ctime; - int32_t msg_pad3; - int32_t msg_pad4[4]; }; struct shmid_ds32 { struct ipc_perm32 shm_perm; int32_t shm_segsz; - int32_t shm_lpid; - int32_t shm_cpid; - int16_t shm_nattch; + pid_t shm_lpid; + pid_t shm_cpid; + int shm_nattch; int32_t shm_atime; int32_t shm_dtime; int32_t shm_ctime; - uint32_t shm_internal; }; struct shm_info32 { @@ -103,4 +95,58 @@ struct shminfo32 { uint32_t shmall; }; +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +struct ipc_perm32_old { + uint16_t cuid; + uint16_t cgid; + uint16_t uid; + uint16_t gid; + uint16_t mode; + uint16_t seq; + uint32_t key; +}; + +struct semid_ds32_old { + struct ipc_perm32_old sem_perm; + uint32_t sem_base; + unsigned short sem_nsems; + int32_t sem_otime; + int32_t sem_pad1; + int32_t sem_ctime; + int32_t sem_pad2; + int32_t sem_pad3[4]; +}; + +struct msqid_ds32_old { + struct ipc_perm32_old msg_perm; + uint32_t msg_first; + uint32_t msg_last; + uint32_t msg_cbytes; + uint32_t msg_qnum; + uint32_t msg_qbytes; + pid_t msg_lspid; + pid_t msg_lrpid; + int32_t msg_stime; + int32_t msg_pad1; + int32_t msg_rtime; + int32_t msg_pad2; + int32_t msg_ctime; + int32_t msg_pad3; + int32_t msg_pad4[4]; +}; + +struct shmid_ds32_old { + struct ipc_perm32_old shm_perm; + int32_t shm_segsz; + pid_t shm_lpid; + pid_t shm_cpid; + int16_t shm_nattch; + int32_t shm_atime; + int32_t shm_dtime; + int32_t shm_ctime; + uint32_t shm_internal; +}; +#endif + #endif /* !_COMPAT_FREEBSD32_FREEBSD32_IPC_H_ */ diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 9301b8d..7509c45 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -1353,6 +1353,35 @@ freebsd4_freebsd32_fhstatfs(struct thread *td, struct freebsd4_freebsd32_fhstatf } #endif +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +static void +freebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, struct ipc_perm *ip) +{ + + CP(*ip32, *ip, cuid); + CP(*ip32, *ip, cgid); + CP(*ip32, *ip, uid); + CP(*ip32, *ip, gid); + CP(*ip32, *ip, mode); + CP(*ip32, *ip, seq); + CP(*ip32, *ip, key); +} + +static void +freebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm32_old *ip32) +{ + + CP(*ip, *ip32, cuid); + CP(*ip, *ip32, cgid); + CP(*ip, *ip32, uid); + CP(*ip, *ip32, gid); + CP(*ip, *ip32, mode); + CP(*ip, *ip32, seq); + CP(*ip, *ip32, key); +} +#endif + static void freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip) { @@ -1383,6 +1412,8 @@ int freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) { +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) switch (uap->which) { case 0: return (freebsd32_semctl(td, @@ -1390,7 +1421,85 @@ freebsd32_semsys(struct thread *td, struct freebsd32_semsys_args *uap) default: return (semsys(td, (struct semsys_args *)uap)); } +#else + return (nosys(td, NULL)); +#endif +} + +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +int +freebsd7_freebsd32_semctl(struct thread *td, + struct freebsd7_freebsd32_semctl_args *uap) +{ + struct semid_ds32_old dsbuf32; + struct semid_ds dsbuf; + union semun semun; + union semun32 arg; + register_t rval; + int error; + + switch (uap->cmd) { + case SEM_STAT: + case IPC_SET: + case IPC_STAT: + case GETALL: + case SETVAL: + case SETALL: + error = copyin(uap->arg, &arg, sizeof(arg)); + if (error) + return (error); + break; + } + + switch (uap->cmd) { + case SEM_STAT: + case IPC_STAT: + semun.buf = &dsbuf; + break; + case IPC_SET: + error = copyin(PTRIN(arg.buf), &dsbuf32, sizeof(dsbuf32)); + if (error) + return (error); + freebsd32_ipcperm_old_in(&dsbuf32.sem_perm, &dsbuf.sem_perm); + PTRIN_CP(dsbuf32, dsbuf, sem_base); + CP(dsbuf32, dsbuf, sem_nsems); + CP(dsbuf32, dsbuf, sem_otime); + CP(dsbuf32, dsbuf, sem_ctime); + semun.buf = &dsbuf; + break; + case GETALL: + case SETALL: + semun.array = PTRIN(arg.array); + break; + case SETVAL: + semun.val = arg.val; + break; + } + + error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun, + &rval); + if (error) + return (error); + + switch (uap->cmd) { + case SEM_STAT: + case IPC_STAT: + bzero(&dsbuf32, sizeof(dsbuf32)); + freebsd32_ipcperm_old_out(&dsbuf.sem_perm, &dsbuf32.sem_perm); + PTROUT_CP(dsbuf, dsbuf32, sem_base); + CP(dsbuf, dsbuf32, sem_nsems); + CP(dsbuf, dsbuf32, sem_otime); + CP(dsbuf, dsbuf32, sem_ctime); + error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32)); + break; + } + + if (error == 0) + td->td_retval[0] = rval; + return (error); } +#endif int freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap) @@ -1428,13 +1537,7 @@ freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap) PTRIN_CP(dsbuf32, dsbuf, sem_base); CP(dsbuf32, dsbuf, sem_nsems); CP(dsbuf32, dsbuf, sem_otime); - CP(dsbuf32, dsbuf, sem_pad1); CP(dsbuf32, dsbuf, sem_ctime); - CP(dsbuf32, dsbuf, sem_pad2); - CP(dsbuf32, dsbuf, sem_pad3[0]); - CP(dsbuf32, dsbuf, sem_pad3[1]); - CP(dsbuf32, dsbuf, sem_pad3[2]); - CP(dsbuf32, dsbuf, sem_pad3[3]); semun.buf = &dsbuf; break; case GETALL: @@ -1454,17 +1557,12 @@ freebsd32_semctl(struct thread *td, struct freebsd32_semctl_args *uap) switch (uap->cmd) { case SEM_STAT: case IPC_STAT: + bzero(&dsbuf32, sizeof(dsbuf32)); freebsd32_ipcperm_out(&dsbuf.sem_perm, &dsbuf32.sem_perm); PTROUT_CP(dsbuf, dsbuf32, sem_base); CP(dsbuf, dsbuf32, sem_nsems); CP(dsbuf, dsbuf32, sem_otime); - CP(dsbuf, dsbuf32, sem_pad1); CP(dsbuf, dsbuf32, sem_ctime); - CP(dsbuf, dsbuf32, sem_pad2); - CP(dsbuf, dsbuf32, sem_pad3[0]); - CP(dsbuf, dsbuf32, sem_pad3[1]); - CP(dsbuf, dsbuf32, sem_pad3[2]); - CP(dsbuf, dsbuf32, sem_pad3[3]); error = copyout(&dsbuf32, PTRIN(arg.buf), sizeof(dsbuf32)); break; } @@ -1478,6 +1576,8 @@ int freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) { +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) switch (uap->which) { case 0: return (freebsd32_msgctl(td, @@ -1491,8 +1591,59 @@ freebsd32_msgsys(struct thread *td, struct freebsd32_msgsys_args *uap) default: return (msgsys(td, (struct msgsys_args *)uap)); } +#else + return (nosys(td, NULL)); +#endif } +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +int +freebsd7_freebsd32_msgctl(struct thread *td, + struct freebsd7_freebsd32_msgctl_args *uap) +{ + struct msqid_ds msqbuf; + struct msqid_ds32_old msqbuf32; + int error; + + if (uap->cmd == IPC_SET) { + error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32)); + if (error) + return (error); + freebsd32_ipcperm_old_in(&msqbuf32.msg_perm, &msqbuf.msg_perm); + PTRIN_CP(msqbuf32, msqbuf, msg_first); + PTRIN_CP(msqbuf32, msqbuf, msg_last); + CP(msqbuf32, msqbuf, msg_cbytes); + CP(msqbuf32, msqbuf, msg_qnum); + CP(msqbuf32, msqbuf, msg_qbytes); + CP(msqbuf32, msqbuf, msg_lspid); + CP(msqbuf32, msqbuf, msg_lrpid); + CP(msqbuf32, msqbuf, msg_stime); + CP(msqbuf32, msqbuf, msg_rtime); + CP(msqbuf32, msqbuf, msg_ctime); + } + error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf); + if (error) + return (error); + if (uap->cmd == IPC_STAT) { + bzero(&msqbuf32, sizeof(msqbuf32)); + freebsd32_ipcperm_old_out(&msqbuf.msg_perm, &msqbuf32.msg_perm); + PTROUT_CP(msqbuf, msqbuf32, msg_first); + PTROUT_CP(msqbuf, msqbuf32, msg_last); + CP(msqbuf, msqbuf32, msg_cbytes); + CP(msqbuf, msqbuf32, msg_qnum); + CP(msqbuf, msqbuf32, msg_qbytes); + CP(msqbuf, msqbuf32, msg_lspid); + CP(msqbuf, msqbuf32, msg_lrpid); + CP(msqbuf, msqbuf32, msg_stime); + CP(msqbuf, msqbuf32, msg_rtime); + CP(msqbuf, msqbuf32, msg_ctime); + error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32)); + } + return (error); +} +#endif + int freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap) { @@ -1513,15 +1664,8 @@ freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap) CP(msqbuf32, msqbuf, msg_lspid); CP(msqbuf32, msqbuf, msg_lrpid); CP(msqbuf32, msqbuf, msg_stime); - CP(msqbuf32, msqbuf, msg_pad1); CP(msqbuf32, msqbuf, msg_rtime); - CP(msqbuf32, msqbuf, msg_pad2); CP(msqbuf32, msqbuf, msg_ctime); - CP(msqbuf32, msqbuf, msg_pad3); - CP(msqbuf32, msqbuf, msg_pad4[0]); - CP(msqbuf32, msqbuf, msg_pad4[1]); - CP(msqbuf32, msqbuf, msg_pad4[2]); - CP(msqbuf32, msqbuf, msg_pad4[3]); } error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf); if (error) @@ -1536,15 +1680,8 @@ freebsd32_msgctl(struct thread *td, struct freebsd32_msgctl_args *uap) CP(msqbuf, msqbuf32, msg_lspid); CP(msqbuf, msqbuf32, msg_lrpid); CP(msqbuf, msqbuf32, msg_stime); - CP(msqbuf, msqbuf32, msg_pad1); CP(msqbuf, msqbuf32, msg_rtime); - CP(msqbuf, msqbuf32, msg_pad2); CP(msqbuf, msqbuf32, msg_ctime); - CP(msqbuf, msqbuf32, msg_pad3); - CP(msqbuf, msqbuf32, msg_pad4[0]); - CP(msqbuf, msqbuf32, msg_pad4[1]); - CP(msqbuf, msqbuf32, msg_pad4[2]); - CP(msqbuf, msqbuf32, msg_pad4[3]); error = copyout(&msqbuf32, uap->buf, sizeof(struct msqid_ds32)); } return (error); @@ -1588,6 +1725,8 @@ int freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) { +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) switch (uap->which) { case 0: { /* shmat */ struct shmat_args ap; @@ -1623,8 +1762,99 @@ freebsd32_shmsys(struct thread *td, struct freebsd32_shmsys_args *uap) default: return (EINVAL); } +#else + return (nosys(td, NULL)); +#endif } +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +int +freebsd7_freebsd32_shmctl(struct thread *td, + struct freebsd7_freebsd32_shmctl_args *uap) +{ + int error = 0; + union { + struct shmid_ds shmid_ds; + struct shm_info shm_info; + struct shminfo shminfo; + } u; + union { + struct shmid_ds32_old shmid_ds32; + struct shm_info32 shm_info32; + struct shminfo32 shminfo32; + } u32; + size_t sz; + + if (uap->cmd == IPC_SET) { + if ((error = copyin(uap->buf, &u32.shmid_ds32, + sizeof(u32.shmid_ds32)))) + goto done; + freebsd32_ipcperm_old_in(&u32.shmid_ds32.shm_perm, + &u.shmid_ds.shm_perm); + CP(u32.shmid_ds32, u.shmid_ds, shm_segsz); + CP(u32.shmid_ds32, u.shmid_ds, shm_lpid); + CP(u32.shmid_ds32, u.shmid_ds, shm_cpid); + CP(u32.shmid_ds32, u.shmid_ds, shm_nattch); + CP(u32.shmid_ds32, u.shmid_ds, shm_atime); + CP(u32.shmid_ds32, u.shmid_ds, shm_dtime); + CP(u32.shmid_ds32, u.shmid_ds, shm_ctime); + } + + error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz); + if (error) + goto done; + + /* Cases in which we need to copyout */ + switch (uap->cmd) { + case IPC_INFO: + CP(u.shminfo, u32.shminfo32, shmmax); + CP(u.shminfo, u32.shminfo32, shmmin); + CP(u.shminfo, u32.shminfo32, shmmni); + CP(u.shminfo, u32.shminfo32, shmseg); + CP(u.shminfo, u32.shminfo32, shmall); + error = copyout(&u32.shminfo32, uap->buf, + sizeof(u32.shminfo32)); + break; + case SHM_INFO: + CP(u.shm_info, u32.shm_info32, used_ids); + CP(u.shm_info, u32.shm_info32, shm_rss); + CP(u.shm_info, u32.shm_info32, shm_tot); + CP(u.shm_info, u32.shm_info32, shm_swp); + CP(u.shm_info, u32.shm_info32, swap_attempts); + CP(u.shm_info, u32.shm_info32, swap_successes); + error = copyout(&u32.shm_info32, uap->buf, + sizeof(u32.shm_info32)); + break; + case SHM_STAT: + case IPC_STAT: + freebsd32_ipcperm_old_out(&u.shmid_ds.shm_perm, + &u32.shmid_ds32.shm_perm); + if (u.shmid_ds.shm_segsz > INT32_MAX) + u32.shmid_ds32.shm_segsz = INT32_MAX; + else + CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); + CP(u.shmid_ds, u32.shmid_ds32, shm_lpid); + CP(u.shmid_ds, u32.shmid_ds32, shm_cpid); + CP(u.shmid_ds, u32.shmid_ds32, shm_nattch); + CP(u.shmid_ds, u32.shmid_ds32, shm_atime); + CP(u.shmid_ds, u32.shmid_ds32, shm_dtime); + CP(u.shmid_ds, u32.shmid_ds32, shm_ctime); + u32.shmid_ds32.shm_internal = 0; + error = copyout(&u32.shmid_ds32, uap->buf, + sizeof(u32.shmid_ds32)); + break; + } + +done: + if (error) { + /* Invalidate the return value */ + td->td_retval[0] = -1; + } + return (error); +} +#endif + int freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap) { @@ -1654,7 +1884,6 @@ freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap) CP(u32.shmid_ds32, u.shmid_ds, shm_atime); CP(u32.shmid_ds32, u.shmid_ds, shm_dtime); CP(u32.shmid_ds32, u.shmid_ds, shm_ctime); - PTRIN_CP(u32.shmid_ds32, u.shmid_ds, shm_internal); } error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&u, &sz); @@ -1686,14 +1915,16 @@ freebsd32_shmctl(struct thread *td, struct freebsd32_shmctl_args *uap) case IPC_STAT: freebsd32_ipcperm_out(&u.shmid_ds.shm_perm, &u32.shmid_ds32.shm_perm); - CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); + if (u.shmid_ds.shm_segsz > INT32_MAX) + u32.shmid_ds32.shm_segsz = INT32_MAX; + else + CP(u.shmid_ds, u32.shmid_ds32, shm_segsz); CP(u.shmid_ds, u32.shmid_ds32, shm_lpid); CP(u.shmid_ds, u32.shmid_ds32, shm_cpid); CP(u.shmid_ds, u32.shmid_ds32, shm_nattch); CP(u.shmid_ds, u32.shmid_ds32, shm_atime); CP(u.shmid_ds, u32.shmid_ds32, shm_dtime); CP(u.shmid_ds, u32.shmid_ds32, shm_ctime); - PTROUT_CP(u.shmid_ds, u32.shmid_ds32, shm_internal); error = copyout(&u32.shmid_ds32, uap->buf, sizeof(u32.shmid_ds32)); break; diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 5b3fd9f..6e0f886 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -405,15 +405,15 @@ ; The following were introduced with NetBSD/4.4Lite-2 ; They are initialized by thier respective modules/sysinits ; XXX PROBLEM!! -220 AUE_SEMCTL STD { int freebsd32_semctl(int semid, int semnum, \ +220 AUE_SEMCTL COMPAT7 { int freebsd32_semctl(int semid, int semnum, \ int cmd, union semun32 *arg); } 221 AUE_SEMGET NOPROTO { int semget(key_t key, int nsems, \ int semflg); } 222 AUE_SEMOP NOPROTO { int semop(int semid, struct sembuf *sops, \ u_int nsops); } 223 AUE_NULL UNIMPL semconfig -224 AUE_MSGCTL STD { int freebsd32_msgctl(int msqid, int cmd, \ - struct msqid_ds32 *buf); } +224 AUE_MSGCTL COMPAT7 { int freebsd32_msgctl(int msqid, int cmd, \ + struct msqid_ds32_old *buf); } 225 AUE_MSGGET NOPROTO { int msgget(key_t key, int msgflg); } 226 AUE_MSGSND STD { int freebsd32_msgsnd(int msqid, void *msgp, \ size_t msgsz, int msgflg); } @@ -421,8 +421,8 @@ size_t msgsz, long msgtyp, int msgflg); } 228 AUE_SHMAT NOPROTO { int shmat(int shmid, void *shmaddr, \ int shmflg); } -229 AUE_SHMCTL STD { int freebsd32_shmctl(int shmid, int cmd, \ - struct shmid_ds *buf); } +229 AUE_SHMCTL COMPAT7 { int freebsd32_shmctl(int shmid, int cmd, \ + struct shmid_ds32_old *buf); } 230 AUE_SHMDT NOPROTO { int shmdt(void *shmaddr); } 231 AUE_SHMGET NOPROTO { int shmget(key_t key, int size, \ int shmflg); } @@ -894,3 +894,9 @@ unsigned int iovcnt, int flags); } 508 AUE_NULL NOPROTO { int jail_remove(int jid); } 509 AUE_CLOSEFROM NOPROTO { int closefrom(int lowfd); } +510 AUE_SEMCTL STD { int freebsd32_semctl(int semid, int semnum, \ + int cmd, union semun32 *arg); } +511 AUE_MSGCTL STD { int freebsd32_msgctl(int msqid, int cmd, \ + struct msqid_ds32 *buf); } +512 AUE_SHMCTL STD { int freebsd32_shmctl(int shmid, int cmd, \ + struct shmid_ds32 *buf); } diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c index 273c2f7..0a46a05 100644 --- a/sys/compat/linux/linux_ipc.c +++ b/sys/compat/linux/linux_ipc.c @@ -230,23 +230,26 @@ linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp) bsp->shm_atime = lsp->shm_atime; bsp->shm_dtime = lsp->shm_dtime; bsp->shm_ctime = lsp->shm_ctime; - /* this goes (yet) SOS */ - bsp->shm_internal = PTRIN(lsp->private3); } static void bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp) { bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); - lsp->shm_segsz = bsp->shm_segsz; + if (bsp->shm_segsz > INT_MAX) + lsp->shm_segsz = INT_MAX; + else + lsp->shm_segsz = bsp->shm_segsz; lsp->shm_lpid = bsp->shm_lpid; lsp->shm_cpid = bsp->shm_cpid; - lsp->shm_nattch = bsp->shm_nattch; + if (bsp->shm_nattch > SHRT_MAX) + lsp->shm_nattch = SHRT_MAX; + else + lsp->shm_nattch = bsp->shm_nattch; lsp->shm_atime = bsp->shm_atime; lsp->shm_dtime = bsp->shm_dtime; lsp->shm_ctime = bsp->shm_ctime; - /* this goes (yet) SOS */ - lsp->private3 = PTROUT(bsp->shm_internal); + lsp->private3 = 0; } static void @@ -424,6 +427,15 @@ linux_shmid_pushdown(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) { struct l_shmid64_ds linux_shmid64; + /* + * XXX: This is backwards and loses information in shm_nattch + * and shm_segsz. We should probably either expose the BSD + * shmid structure directly and convert it to either the + * non-64 or 64 variant directly or the code should always + * convert to the 64 variant and then truncate values into the + * non-64 variant if needed since the 64 variant has more + * precision. + */ if (ver == LINUX_IPC_64) { bzero(&linux_shmid64, sizeof(linux_shmid64)); diff --git a/sys/compat/svr4/svr4_ipc.c b/sys/compat/svr4/svr4_ipc.c index 317239c..658c6d6 100644 --- a/sys/compat/svr4/svr4_ipc.c +++ b/sys/compat/svr4/svr4_ipc.c @@ -169,13 +169,12 @@ bsd_to_svr4_semid_ds(bds, sds) const struct semid_ds *bds; struct svr4_semid_ds *sds; { + bzero(sds, sizeof(*sds)); bsd_to_svr4_ipc_perm(&bds->sem_perm, &sds->sem_perm); sds->sem_base = (struct svr4_sem *) bds->sem_base; sds->sem_nsems = bds->sem_nsems; sds->sem_otime = bds->sem_otime; - sds->sem_pad1 = bds->sem_pad1; sds->sem_ctime = bds->sem_ctime; - sds->sem_pad2 = bds->sem_pad2; } static void @@ -187,9 +186,7 @@ svr4_to_bsd_semid_ds(sds, bds) bds->sem_base = (struct sem *) bds->sem_base; bds->sem_nsems = sds->sem_nsems; bds->sem_otime = sds->sem_otime; - bds->sem_pad1 = sds->sem_pad1; bds->sem_ctime = sds->sem_ctime; - bds->sem_pad2 = sds->sem_pad2; } struct svr4_sys_semctl_args { @@ -350,6 +347,7 @@ bsd_to_svr4_msqid_ds(bds, sds) const struct msqid_ds *bds; struct svr4_msqid_ds *sds; { + bzero(sds, sizeof(*sds)); bsd_to_svr4_ipc_perm(&bds->msg_perm, &sds->msg_perm); sds->msg_first = (struct svr4_msg *) bds->msg_first; sds->msg_last = (struct svr4_msg *) bds->msg_last; @@ -359,18 +357,8 @@ bsd_to_svr4_msqid_ds(bds, sds) sds->msg_lspid = bds->msg_lspid; sds->msg_lrpid = bds->msg_lrpid; sds->msg_stime = bds->msg_stime; - sds->msg_pad1 = bds->msg_pad1; sds->msg_rtime = bds->msg_rtime; - sds->msg_pad2 = bds->msg_pad2; sds->msg_ctime = bds->msg_ctime; - sds->msg_pad3 = bds->msg_pad3; - - /* use the padding for the rest of the fields */ - { - const short *pad = (const short *) bds->msg_pad4; - sds->msg_cv = pad[0]; - sds->msg_qnum_cv = pad[1]; - } } static void @@ -387,18 +375,8 @@ svr4_to_bsd_msqid_ds(sds, bds) bds->msg_lspid = sds->msg_lspid; bds->msg_lrpid = sds->msg_lrpid; bds->msg_stime = sds->msg_stime; - bds->msg_pad1 = sds->msg_pad1; bds->msg_rtime = sds->msg_rtime; - bds->msg_pad2 = sds->msg_pad2; bds->msg_ctime = sds->msg_ctime; - bds->msg_pad3 = sds->msg_pad3; - - /* use the padding for the rest of the fields */ - { - short *pad = (short *) bds->msg_pad4; - pad[0] = sds->msg_cv; - pad[1] = sds->msg_qnum_cv; - } } struct svr4_sys_msgsnd_args { @@ -543,20 +521,18 @@ bsd_to_svr4_shmid_ds(bds, sds) const struct shmid_ds *bds; struct svr4_shmid_ds *sds; { + bzero(sds, sizeof(*sds)); bsd_to_svr4_ipc_perm(&bds->shm_perm, &sds->shm_perm); sds->shm_segsz = bds->shm_segsz; sds->shm_lkcnt = 0; sds->shm_lpid = bds->shm_lpid; sds->shm_cpid = bds->shm_cpid; - sds->shm_amp = bds->shm_internal; + sds->shm_amp = 0; sds->shm_nattch = bds->shm_nattch; sds->shm_cnattch = 0; sds->shm_atime = bds->shm_atime; - sds->shm_pad1 = 0; sds->shm_dtime = bds->shm_dtime; - sds->shm_pad2 = 0; sds->shm_ctime = bds->shm_ctime; - sds->shm_pad3 = 0; } static void @@ -568,7 +544,6 @@ svr4_to_bsd_shmid_ds(sds, bds) bds->shm_segsz = sds->shm_segsz; bds->shm_lpid = sds->shm_lpid; bds->shm_cpid = sds->shm_cpid; - bds->shm_internal = sds->shm_amp; bds->shm_nattch = sds->shm_nattch; bds->shm_atime = sds->shm_atime; bds->shm_dtime = sds->shm_dtime; diff --git a/sys/i386/ibcs2/ibcs2_ipc.c b/sys/i386/ibcs2/ibcs2_ipc.c index 5b6342a..f606c1b 100644 --- a/sys/i386/ibcs2/ibcs2_ipc.c +++ b/sys/i386/ibcs2/ibcs2_ipc.c @@ -415,7 +415,10 @@ struct ibcs2_shmid_ds *ibp; ibp->shm_segsz = bp->shm_segsz; ibp->shm_lpid = bp->shm_lpid; ibp->shm_cpid = bp->shm_cpid; - ibp->shm_nattch = bp->shm_nattch; + if (bp->shm_nattch > SHRT_MAX) + ibp->shm_nattch = SHRT_MAX; + else + ibp->shm_nattch = bp->shm_nattch; ibp->shm_cnattch = 0; /* ignored anyway */ ibp->shm_atime = bp->shm_atime; ibp->shm_dtime = bp->shm_dtime; @@ -436,7 +439,6 @@ struct shmid_ds *bp; bp->shm_atime = ibp->shm_atime; bp->shm_dtime = ibp->shm_dtime; bp->shm_ctime = ibp->shm_ctime; - bp->shm_internal = (void *)0; /* ignored anyway */ return; } diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 204e7da..940f13d 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -417,15 +417,15 @@ ; ; The following were introduced with NetBSD/4.4Lite-2 -220 AUE_SEMCTL NOSTD { int __semctl(int semid, int semnum, \ - int cmd, union semun *arg); } +220 AUE_SEMCTL COMPAT7|NOSTD { int __semctl(int semid, int semnum, \ + int cmd, union semun_old *arg); } 221 AUE_SEMGET NOSTD { int semget(key_t key, int nsems, \ int semflg); } 222 AUE_SEMOP NOSTD { int semop(int semid, struct sembuf *sops, \ size_t nsops); } 223 AUE_NULL UNIMPL semconfig -224 AUE_MSGCTL NOSTD { int msgctl(int msqid, int cmd, \ - struct msqid_ds *buf); } +224 AUE_MSGCTL COMPAT7|NOSTD { int msgctl(int msqid, int cmd, \ + struct msqid_ds_old *buf); } 225 AUE_MSGGET NOSTD { int msgget(key_t key, int msgflg); } 226 AUE_MSGSND NOSTD { int msgsnd(int msqid, const void *msgp, \ size_t msgsz, int msgflg); } @@ -433,8 +433,8 @@ size_t msgsz, long msgtyp, int msgflg); } 228 AUE_SHMAT NOSTD { int shmat(int shmid, const void *shmaddr, \ int shmflg); } -229 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \ - struct shmid_ds *buf); } +229 AUE_SHMCTL COMPAT7|NOSTD { int shmctl(int shmid, int cmd, \ + struct shmid_ds_old *buf); } 230 AUE_SHMDT NOSTD { int shmdt(const void *shmaddr); } 231 AUE_SHMGET NOSTD { int shmget(key_t key, size_t size, \ int shmflg); } @@ -904,5 +904,11 @@ unsigned int iovcnt, int flags); } 508 AUE_NULL STD { int jail_remove(int jid); } 509 AUE_CLOSEFROM STD { int closefrom(int lowfd); } +510 AUE_SEMCTL NOSTD { int __semctl(int semid, int semnum, \ + int cmd, union semun *arg); } +511 AUE_MSGCTL NOSTD { int msgctl(int msqid, int cmd, \ + struct msqid_ds *buf); } +512 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \ + struct shmid_ds *buf); } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c index 0cbb4bb..d33fdb0 100644 --- a/sys/kern/sysv_ipc.c +++ b/sys/kern/sysv_ipc.c @@ -36,6 +36,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_compat.h" #include "opt_sysvipc.h" #include <sys/param.h> @@ -147,3 +148,33 @@ ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode) else return (EACCES); } + +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +void +ipcperm_old2new(struct ipc_perm_old *old, struct ipc_perm *new) +{ + + new->cuid = old->cuid; + new->cgid = old->cgid; + new->uid = old->uid; + new->gid = old->gid; + new->mode = old->mode; + new->seq = old->seq; + new->key = old->key; +} + +void +ipcperm_new2old(struct ipc_perm *new, struct ipc_perm_old *old) +{ + + /* XXX: How to handle ID's > USHORT_MAX? */ + old->cuid = new->cuid; + old->cgid = new->cgid; + old->uid = new->uid; + old->gid = new->gid; + old->mode = new->mode; + old->seq = new->seq; + old->key = new->key; +} +#endif diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c index e2f0c5d..c7c67d4 100644 --- a/sys/kern/sysv_msg.c +++ b/sys/kern/sysv_msg.c @@ -1260,10 +1260,11 @@ SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLFLAG_RD, #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) SYSCALL_MODULE_HELPER(msgsys); +SYSCALL_MODULE_HELPER(freebsd7_msgctl); /* XXX casting to (sy_call_t *) is bogus, as usual. */ static sy_call_t *msgcalls[] = { - (sy_call_t *)msgctl, (sy_call_t *)msgget, + (sy_call_t *)freebsd7_msgctl, (sy_call_t *)msgget, (sy_call_t *)msgsnd, (sy_call_t *)msgrcv }; @@ -1293,5 +1294,65 @@ msgsys(td, uap) error = (*msgcalls[uap->which])(td, &uap->a2); return (error); } + +#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0) + +#ifndef _SYS_SYSPROTO_H_ +struct freebsd7_msgctl_args { + int msqid; + int cmd; + struct msqid_ds_old *buf; +}; +#endif +int +freebsd7_msgctl(td, uap) + struct thread *td; + struct freebsd7_msgctl_args *uap; +{ + struct msqid_ds_old msqold; + struct msqid_ds msqbuf; + int error; + + DPRINTF(("call to freebsd7_msgctl(%d, %d, %p)\n", uap->msqid, uap->cmd, + uap->buf)); + if (uap->cmd == IPC_SET) { + error = copyin(uap->buf, &msqold, sizeof(msqold)); + if (error) + return (error); + ipcperm_old2new(&msqold.msg_perm, &msqbuf.msg_perm); + CP(msqold, msqbuf, msg_first); + CP(msqold, msqbuf, msg_last); + CP(msqold, msqbuf, msg_cbytes); + CP(msqold, msqbuf, msg_qnum); + CP(msqold, msqbuf, msg_qbytes); + CP(msqold, msqbuf, msg_lspid); + CP(msqold, msqbuf, msg_lrpid); + CP(msqold, msqbuf, msg_stime); + CP(msqold, msqbuf, msg_rtime); + CP(msqold, msqbuf, msg_ctime); + } + error = kern_msgctl(td, uap->msqid, uap->cmd, &msqbuf); + if (error) + return (error); + if (uap->cmd == IPC_STAT) { + bzero(&msqold, sizeof(msqold)); + ipcperm_new2old(&msqbuf.msg_perm, &msqold.msg_perm); + CP(msqbuf, msqold, msg_first); + CP(msqbuf, msqold, msg_last); + CP(msqbuf, msqold, msg_cbytes); + CP(msqbuf, msqold, msg_qnum); + CP(msqbuf, msqold, msg_qbytes); + CP(msqbuf, msqold, msg_lspid); + CP(msqbuf, msqold, msg_lrpid); + CP(msqbuf, msqold, msg_stime); + CP(msqbuf, msqold, msg_rtime); + CP(msqbuf, msqold, msg_ctime); + error = copyout(&msqold, uap->buf, sizeof(struct msqid_ds_old)); + } + return (error); +} + +#undef CP + #endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 || COMPAT_FREEBSD7 */ diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 719295d..2f2b528 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -1317,10 +1317,11 @@ sysctl_sema(SYSCTL_HANDLER_ARGS) #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) SYSCALL_MODULE_HELPER(semsys); +SYSCALL_MODULE_HELPER(freebsd7___semctl); /* XXX casting to (sy_call_t *) is bogus, as usual. */ static sy_call_t *semcalls[] = { - (sy_call_t *)__semctl, (sy_call_t *)semget, + (sy_call_t *)freebsd7___semctl, (sy_call_t *)semget, (sy_call_t *)semop }; @@ -1349,5 +1350,89 @@ semsys(td, uap) error = (*semcalls[uap->which])(td, &uap->a2); return (error); } + +#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0) + +#ifndef _SYS_SYSPROTO_H_ +struct freebsd7___semctl_args { + int semid; + int semnum; + int cmd; + union semun_old *arg; +}; +#endif +int +freebsd7___semctl(struct thread *td, struct freebsd7___semctl_args *uap) +{ + struct semid_ds_old dsold; + struct semid_ds dsbuf; + union semun_old arg; + union semun semun; + register_t rval; + int error; + + switch (uap->cmd) { + case SEM_STAT: + case IPC_SET: + case IPC_STAT: + case GETALL: + case SETVAL: + case SETALL: + error = copyin(uap->arg, &arg, sizeof(arg)); + if (error) + return (error); + break; + } + + switch (uap->cmd) { + case SEM_STAT: + case IPC_STAT: + semun.buf = &dsbuf; + break; + case IPC_SET: + error = copyin(arg.buf, &dsold, sizeof(dsold)); + if (error) + return (error); + ipcperm_old2new(&dsold.sem_perm, &dsbuf.sem_perm); + CP(dsold, dsbuf, sem_base); + CP(dsold, dsbuf, sem_nsems); + CP(dsold, dsbuf, sem_otime); + CP(dsold, dsbuf, sem_ctime); + semun.buf = &dsbuf; + break; + case GETALL: + case SETALL: + semun.array = arg.array; + break; + case SETVAL: + semun.val = arg.val; + break; + } + + error = kern_semctl(td, uap->semid, uap->semnum, uap->cmd, &semun, + &rval); + if (error) + return (error); + + switch (uap->cmd) { + case SEM_STAT: + case IPC_STAT: + bzero(&dsold, sizeof(dsold)); + ipcperm_new2old(&dsbuf.sem_perm, &dsold.sem_perm); + CP(dsbuf, dsold, sem_base); + CP(dsbuf, dsold, sem_nsems); + CP(dsbuf, dsold, sem_otime); + CP(dsbuf, dsold, sem_ctime); + error = copyout(&dsold, arg.buf, sizeof(dsold)); + break; + } + + if (error == 0) + td->td_retval[0] = rval; + return (error); +} + +#undef CP + #endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 || COMPAT_FREEBSD7 */ diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 2ea9830..bfcbebf 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/limits.h> #include <sys/lock.h> #include <sys/sysctl.h> #include <sys/shm.h> @@ -234,9 +235,9 @@ shm_deallocate_segment(shmseg) GIANT_REQUIRED; - vm_object_deallocate(shmseg->u.shm_internal); - shmseg->u.shm_internal = NULL; - size = round_page(shmseg->shm_bsegsz); + vm_object_deallocate(shmseg->object); + shmseg->object = NULL; + size = round_page(shmseg->u.shm_segsz); shm_committed -= btoc(size); shm_nused--; shmseg->u.shm_perm.mode = SHMSEG_FREE; @@ -256,7 +257,7 @@ shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s) segnum = IPCID_TO_IX(shmmap_s->shmid); shmseg = &shmsegs[segnum]; - size = round_page(shmseg->shm_bsegsz); + size = round_page(shmseg->u.shm_segsz); result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size); if (result != KERN_SUCCESS) return (EINVAL); @@ -376,7 +377,7 @@ kern_shmat(td, shmid, shmaddr, shmflg) error = EMFILE; goto done2; } - size = round_page(shmseg->shm_bsegsz); + size = round_page(shmseg->u.shm_segsz); prot = VM_PROT_READ; if ((shmflg & SHM_RDONLY) == 0) prot |= VM_PROT_WRITE; @@ -402,12 +403,12 @@ kern_shmat(td, shmid, shmaddr, shmflg) PROC_UNLOCK(p); } - vm_object_reference(shmseg->u.shm_internal); - rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->u.shm_internal, + vm_object_reference(shmseg->object); + rv = vm_map_find(&p->p_vmspace->vm_map, shmseg->object, 0, &attach_va, size, (flags & MAP_FIXED) ? VMFS_NO_SPACE : VMFS_ANY_SPACE, prot, prot, 0); if (rv != KERN_SUCCESS) { - vm_object_deallocate(shmseg->u.shm_internal); + vm_object_deallocate(shmseg->object); error = ENOMEM; goto done2; } @@ -624,7 +625,7 @@ shmget_existing(td, uap, mode, segnum) if (error != 0) return (error); #endif - if (uap->size != 0 && uap->size > shmseg->shm_bsegsz) + if (uap->size != 0 && uap->size > shmseg->u.shm_segsz) return (EINVAL); td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm); return (0); @@ -686,13 +687,12 @@ shmget_allocate_segment(td, uap, mode) vm_object_set_flag(shm_object, OBJ_NOSPLIT); VM_OBJECT_UNLOCK(shm_object); - shmseg->u.shm_internal = shm_object; + shmseg->object = shm_object; shmseg->u.shm_perm.cuid = shmseg->u.shm_perm.uid = cred->cr_uid; shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid; shmseg->u.shm_perm.mode = (shmseg->u.shm_perm.mode & SHMSEG_WANTED) | (mode & ACCESSPERMS) | SHMSEG_ALLOCATED; shmseg->u.shm_segsz = uap->size; - shmseg->shm_bsegsz = uap->size; shmseg->u.shm_cpid = td->td_proc->p_pid; shmseg->u.shm_lpid = shmseg->u.shm_nattch = 0; shmseg->u.shm_atime = shmseg->u.shm_dtime = 0; @@ -953,7 +953,7 @@ done2: static sy_call_t *shmcalls[] = { (sy_call_t *)shmat, (sy_call_t *)oshmctl, (sy_call_t *)shmdt, (sy_call_t *)shmget, - (sy_call_t *)shmctl + (sy_call_t *)freebsd7_shmctl }; int @@ -983,6 +983,93 @@ shmsys(td, uap) SYSCALL_MODULE_HELPER(shmsys); #endif /* i386 && (COMPAT_FREEBSD4 || COMPAT_43) */ +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) + +#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0) + + +#ifndef _SYS_SYSPROTO_H_ +struct freebsd7_shmctl_args { + int shmid; + int cmd; + struct shmid_ds_old *buf; +}; +#endif +int +freebsd7_shmctl(td, uap) + struct thread *td; + struct freebsd7_shmctl_args *uap; +{ + int error = 0; + struct shmid_ds_old old; + struct shmid_ds buf; + size_t bufsz; + + /* + * The only reason IPC_INFO, SHM_INFO, SHM_STAT exists is to support + * Linux binaries. If we see the call come through the FreeBSD ABI, + * return an error back to the user since we do not to support this. + */ + if (uap->cmd == IPC_INFO || uap->cmd == SHM_INFO || + uap->cmd == SHM_STAT) + return (EINVAL); + + /* IPC_SET needs to copyin the buffer before calling kern_shmctl */ + if (uap->cmd == IPC_SET) { + if ((error = copyin(uap->buf, &old, sizeof(old)))) + goto done; + ipcperm_old2new(&old.shm_perm, &buf.shm_perm); + CP(old, buf, shm_segsz); + CP(old, buf, shm_lpid); + CP(old, buf, shm_cpid); + CP(old, buf, shm_nattch); + CP(old, buf, shm_atime); + CP(old, buf, shm_dtime); + CP(old, buf, shm_ctime); + } + + error = kern_shmctl(td, uap->shmid, uap->cmd, (void *)&buf, &bufsz); + if (error) + goto done; + + /* Cases in which we need to copyout */ + switch (uap->cmd) { + case IPC_STAT: + ipcperm_new2old(&buf.shm_perm, &old.shm_perm); + if (buf.shm_segsz > INT_MAX) + old.shm_segsz = INT_MAX; + else + CP(buf, old, shm_segsz); + CP(buf, old, shm_lpid); + CP(buf, old, shm_cpid); + if (buf.shm_nattch > SHRT_MAX) + old.shm_nattch = SHRT_MAX; + else + CP(buf, old, shm_nattch); + CP(buf, old, shm_atime); + CP(buf, old, shm_dtime); + CP(buf, old, shm_ctime); + old.shm_internal = NULL; + error = copyout(&old, uap->buf, sizeof(old)); + break; + } + +done: + if (error) { + /* Invalidate the return value */ + td->td_retval[0] = -1; + } + return (error); +} + +SYSCALL_MODULE_HELPER(freebsd7_shmctl); + +#undef CP + +#endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 || + COMPAT_FREEBSD7 */ + static int sysvshm_modload(struct module *module, int cmd, void *arg) { diff --git a/sys/sys/ipc.h b/sys/sys/ipc.h index 139b103..c72d913 100644 --- a/sys/sys/ipc.h +++ b/sys/sys/ipc.h @@ -69,10 +69,9 @@ typedef __uid_t uid_t; #define _UID_T_DECLARED #endif -/* - * XXX almost all members have wrong types. - */ -struct ipc_perm { +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +struct ipc_perm_old { unsigned short cuid; /* creator user id */ unsigned short cgid; /* creator group id */ unsigned short uid; /* user id */ @@ -81,6 +80,17 @@ struct ipc_perm { unsigned short seq; /* sequence # (to generate unique ipcid) */ key_t key; /* user specified msg/sem/shm key */ }; +#endif + +struct ipc_perm { + uid_t cuid; /* creator user id */ + gid_t cgid; /* creator group id */ + uid_t uid; /* user id */ + gid_t gid; /* group id */ + mode_t mode; /* r/w permission */ + unsigned short seq; /* sequence # (to generate unique ipcid) */ + key_t key; /* user specified msg/sem/shm key */ +}; #if __BSD_VISIBLE /* common mode bits */ @@ -116,6 +126,12 @@ struct thread; struct proc; struct vmspace; +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +void ipcperm_old2new(struct ipc_perm_old *, struct ipc_perm *); +void ipcperm_new2old(struct ipc_perm *, struct ipc_perm_old *); +#endif + int ipcperm(struct thread *, struct ipc_perm *, int); extern void (*shmfork_hook)(struct proc *, struct proc *); extern void (*shmexit_hook)(struct vmspace *); diff --git a/sys/sys/msg.h b/sys/sys/msg.h index 325df93..e4edd09 100644 --- a/sys/sys/msg.h +++ b/sys/sys/msg.h @@ -57,6 +57,27 @@ typedef __time_t time_t; #define _TIME_T_DECLARED #endif +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +struct msqid_ds_old { + struct ipc_perm_old msg_perm; /* msg queue permission bits */ + struct msg *msg_first; /* first message in the queue */ + struct msg *msg_last; /* last message in the queue */ + msglen_t msg_cbytes; /* number of bytes in use on the queue */ + msgqnum_t msg_qnum; /* number of msgs in the queue */ + msglen_t msg_qbytes; /* max # of bytes on the queue */ + pid_t msg_lspid; /* pid of last msgsnd() */ + pid_t msg_lrpid; /* pid of last msgrcv() */ + time_t msg_stime; /* time of last msgsnd() */ + long msg_pad1; + time_t msg_rtime; /* time of last msgrcv() */ + long msg_pad2; + time_t msg_ctime; /* time of last msgctl() */ + long msg_pad3; + long msg_pad4[4]; +}; +#endif + /* * XXX there seems to be no prefix reserved for this header, so the name * "msg" in "struct msg" and the names of all of the nonstandard members @@ -73,12 +94,8 @@ struct msqid_ds { pid_t msg_lspid; /* pid of last msgsnd() */ pid_t msg_lrpid; /* pid of last msgrcv() */ time_t msg_stime; /* time of last msgsnd() */ - long msg_pad1; time_t msg_rtime; /* time of last msgrcv() */ - long msg_pad2; time_t msg_ctime; /* time of last msgctl() */ - long msg_pad3; - long msg_pad4[4]; }; #if __BSD_VISIBLE diff --git a/sys/sys/sem.h b/sys/sys/sem.h index d8d6e92..458ffb9 100644 --- a/sys/sys/sem.h +++ b/sys/sys/sem.h @@ -27,8 +27,10 @@ typedef __time_t time_t; #define _TIME_T_DECLARED #endif -struct semid_ds { - struct ipc_perm sem_perm; /* operation permission struct */ +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +struct semid_ds_old { + struct ipc_perm_old sem_perm; /* operation permission struct */ struct sem *sem_base; /* pointer to first semaphore in set */ unsigned short sem_nsems; /* number of sems in set */ time_t sem_otime; /* last operation time */ @@ -39,6 +41,17 @@ struct semid_ds { long sem_pad2; /* SVABI/386 says I need this here */ long sem_pad3[4]; /* SVABI/386 says I need this here */ }; +#endif + +struct semid_ds { + struct ipc_perm sem_perm; /* operation permission struct */ + struct sem *sem_base; /* pointer to first semaphore in set */ + unsigned short sem_nsems; /* number of sems in set */ + time_t sem_otime; /* last operation time */ + time_t sem_ctime; /* last change time */ + /* Times measured in secs since */ + /* 00:00:00 GMT, Jan. 1, 1970 */ +}; /* * semop's sops parameter structure @@ -50,6 +63,16 @@ struct sembuf { }; #define SEM_UNDO 010000 +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) || \ + defined(_WANT_SEMUN_OLD) +union semun_old { + int val; /* value for SETVAL */ + struct semid_ds_old *buf; /* buffer for IPC_STAT & IPC_SET */ + unsigned short *array; /* array for GETALL & SETALL */ +}; +#endif + /* * semctl's arg parameter structure */ diff --git a/sys/sys/shm.h b/sys/sys/shm.h index e6f2f76..7fe3dae 100644 --- a/sys/sys/shm.h +++ b/sys/sys/shm.h @@ -75,8 +75,10 @@ typedef __size_t size_t; #define _SIZE_T_DECLARED #endif -struct shmid_ds { - struct ipc_perm shm_perm; /* operation permission structure */ +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +struct shmid_ds_old { + struct ipc_perm_old shm_perm; /* operation permission structure */ int shm_segsz; /* size of segment in bytes */ pid_t shm_lpid; /* process ID of last shared memory op */ pid_t shm_cpid; /* process ID of creator */ @@ -86,8 +88,21 @@ struct shmid_ds { time_t shm_ctime; /* time of last change by shmctl() */ void *shm_internal; /* sysv stupidity */ }; +#endif + +struct shmid_ds { + struct ipc_perm shm_perm; /* operation permission structure */ + size_t shm_segsz; /* size of segment in bytes */ + pid_t shm_lpid; /* process ID of last shared memory op */ + pid_t shm_cpid; /* process ID of creator */ + int shm_nattch; /* number of current attaches */ + time_t shm_atime; /* time of last shmat() */ + time_t shm_dtime; /* time of last shmdt() */ + time_t shm_ctime; /* time of last change by shmctl() */ +}; #ifdef _KERNEL +#include <vm/vm.h> /* * System 5 style catch-all structure for shared memory constants that @@ -107,8 +122,8 @@ struct shminfo { */ struct shmid_kernel { struct shmid_ds u; + vm_object_t object; struct label *label; /* MAC label */ - size_t shm_bsegsz; }; extern struct shminfo shminfo; diff --git a/usr.bin/ipcs/ipcs.c b/usr.bin/ipcs/ipcs.c index 1fd943a..3ddfa25 100644 --- a/usr.bin/ipcs/ipcs.c +++ b/usr.bin/ipcs/ipcs.c @@ -453,7 +453,7 @@ print_kshmptr(int i, int option, struct shmid_kernel *kshmptr) if (option & BIGGEST) printf(" %12zu", - kshmptr->shm_bsegsz); + kshmptr->u.shm_segsz); if (option & PID) printf(" %12d %12d", |