diff options
author | kib <kib@FreeBSD.org> | 2010-03-19 11:04:42 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2010-03-19 11:04:42 +0000 |
commit | b27fa06f976447590802ac0521932dc2803b4854 (patch) | |
tree | c0f64553fae4afa41d4796848ab08f701505e447 /sys/kern/sysv_sem.c | |
parent | 610214ed4c4cf8e4c9ec77a65d3b4fee64af5657 (diff) | |
download | FreeBSD-src-b27fa06f976447590802ac0521932dc2803b4854.zip FreeBSD-src-b27fa06f976447590802ac0521932dc2803b4854.tar.gz |
Move SysV IPC freebsd32 compat shims from freebsd32_misc.c to corresponding
sysv_{msg,sem,shm}.c files.
Mark SysV IPC freebsd32 syscalls as NOSTD and add required
SYSCALL_INIT_HELPER/SYSCALL32_INIT_HELPERs to provide auto
register/unregister on module load.
This makes COMPAT_FREEBSD32 functional with SysV IPC compiled and loaded
as modules.
Reviewed by: jhb
MFC after: 2 weeks
Diffstat (limited to 'sys/kern/sysv_sem.c')
-rw-r--r-- | sys/kern/sysv_sem.c | 236 |
1 files changed, 223 insertions, 13 deletions
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 2f2b528..f6d781c7 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -70,7 +70,7 @@ static MALLOC_DEFINE(M_SEM, "sem", "SVID compatible semaphores"); #define DPRINTF(a) #endif -static void seminit(void); +static int seminit(void); static int sysvsem_modload(struct module *, int, void *); static int semunload(void); static void semexit_myhook(void *arg, struct proc *p); @@ -214,10 +214,43 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, semaem, CTLFLAG_RW, &seminfo.semaem, 0, SYSCTL_PROC(_kern_ipc, OID_AUTO, sema, CTLFLAG_RD, NULL, 0, sysctl_sema, "", ""); -static void +static struct syscall_helper_data sem_syscalls[] = { + SYSCALL_INIT_HELPER(__semctl), + SYSCALL_INIT_HELPER(semget), + SYSCALL_INIT_HELPER(semop), +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) + SYSCALL_INIT_HELPER(semsys), + SYSCALL_INIT_HELPER(freebsd7___semctl), +#endif + SYSCALL_INIT_LAST +}; + +#ifdef COMPAT_FREEBSD32 +#include <compat/freebsd32/freebsd32.h> +#include <compat/freebsd32/freebsd32_ipc.h> +#include <compat/freebsd32/freebsd32_proto.h> +#include <compat/freebsd32/freebsd32_signal.h> +#include <compat/freebsd32/freebsd32_syscall.h> +#include <compat/freebsd32/freebsd32_util.h> + +static struct syscall_helper_data sem32_syscalls[] = { + SYSCALL32_INIT_HELPER(freebsd32_semctl), + SYSCALL32_INIT_HELPER(semget), + SYSCALL32_INIT_HELPER(semop), + SYSCALL32_INIT_HELPER(freebsd32_semsys), +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) + SYSCALL32_INIT_HELPER(freebsd7_freebsd32_semctl), +#endif + SYSCALL_INIT_LAST +}; +#endif + +static int seminit(void) { - int i; + int i, error; TUNABLE_INT_FETCH("kern.ipc.semmap", &seminfo.semmap); TUNABLE_INT_FETCH("kern.ipc.semmni", &seminfo.semmni); @@ -258,6 +291,16 @@ seminit(void) mtx_init(&sem_undo_mtx, "semu", NULL, MTX_DEF); semexit_tag = EVENTHANDLER_REGISTER(process_exit, semexit_myhook, NULL, EVENTHANDLER_PRI_ANY); + + error = syscall_helper_register(sem_syscalls); + if (error != 0) + return (error); +#ifdef COMPAT_FREEBSD32 + error = syscall32_helper_register(sem32_syscalls); + if (error != 0) + return (error); +#endif + return (0); } static int @@ -269,6 +312,10 @@ semunload(void) if (semtot != 0) return (EBUSY); +#ifdef COMPAT_FREEBSD32 + syscall32_helper_unregister(sem32_syscalls); +#endif + syscall_helper_unregister(sem_syscalls); EVENTHANDLER_DEREGISTER(process_exit, semexit_tag); #ifdef MAC for (i = 0; i < seminfo.semmni; i++) @@ -292,7 +339,9 @@ sysvsem_modload(struct module *module, int cmd, void *arg) switch (cmd) { case MOD_LOAD: - seminit(); + error = seminit(); + if (error != 0) + semunload(); break; case MOD_UNLOAD: error = semunload(); @@ -312,10 +361,6 @@ static moduledata_t sysvsem_mod = { NULL }; -SYSCALL_MODULE_HELPER(__semctl); -SYSCALL_MODULE_HELPER(semget); -SYSCALL_MODULE_HELPER(semop); - DECLARE_MODULE(sysvsem, sysvsem_mod, SI_SUB_SYSV_SEM, SI_ORDER_FIRST); MODULE_VERSION(sysvsem, 1); @@ -1316,8 +1361,6 @@ 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[] = { @@ -1351,7 +1394,9 @@ semsys(td, uap) return (error); } +#ifndef CP #define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0) +#endif #ifndef _SYS_SYSPROTO_H_ struct freebsd7___semctl_args { @@ -1432,7 +1477,172 @@ freebsd7___semctl(struct thread *td, struct freebsd7___semctl_args *uap) return (error); } -#undef CP +#endif /* COMPAT_FREEBSD{4,5,6,7} */ + +#ifdef COMPAT_FREEBSD32 + +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 (freebsd7_freebsd32_semctl(td, + (struct freebsd7_freebsd32_semctl_args *)&uap->a2)); + 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) +{ + struct semid_ds32 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_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_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 /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 || - COMPAT_FREEBSD7 */ +#endif /* COMPAT_FREEBSD32 */ |