diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h index 058ac72..b68f8fb 100644 --- a/sys/compat/freebsd32/freebsd32.h +++ b/sys/compat/freebsd32/freebsd32.h @@ -221,4 +221,12 @@ struct prpsinfo32 { char pr_psargs[PRARGSZ+1]; }; +struct mq_attr32 { + int mq_flags; + int mq_maxmsg; + int mq_msgsize; + int mq_curmsgs; + int __reserved[4]; +}; + #endif /* !_COMPAT_FREEBSD32_FREEBSD32_H_ */ diff --git a/sys/compat/freebsd32/freebsd32_ipc.h b/sys/compat/freebsd32/freebsd32_ipc.h index 2b07494..320a63f 100644 --- a/sys/compat/freebsd32/freebsd32_ipc.h +++ b/sys/compat/freebsd32/freebsd32_ipc.h @@ -147,6 +147,14 @@ struct shmid_ds32_old { int32_t shm_ctime; uint32_t shm_internal; }; + +void freebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, + struct ipc_perm *ip); +void freebsd32_ipcperm_old_out(struct ipc_perm *ip, + struct ipc_perm32_old *ip32); #endif +void freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip); +void freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32); + #endif /* !_COMPAT_FREEBSD32_FREEBSD32_IPC_H_ */ diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index c20e5fb..1284e38 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -873,7 +873,7 @@ freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap) return (error); } -static int +int freebsd32_copyiniov(struct iovec32 *iovp32, u_int iovcnt, struct iovec **iovp, int error) { @@ -1400,591 +1400,6 @@ 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) -{ - - 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_out(struct ipc_perm *ip, struct ipc_perm32 *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); -} - -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); -} - -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 (freebsd7_freebsd32_msgctl(td, - (struct freebsd7_freebsd32_msgctl_args *)&uap->a2)); - case 2: - return (freebsd32_msgsnd(td, - (struct freebsd32_msgsnd_args *)&uap->a2)); - case 3: - return (freebsd32_msgrcv(td, - (struct freebsd32_msgrcv_args *)&uap->a2)); - 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) -{ - struct msqid_ds msqbuf; - struct msqid_ds32 msqbuf32; - int error; - - if (uap->cmd == IPC_SET) { - error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32)); - if (error) - return (error); - freebsd32_ipcperm_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) { - freebsd32_ipcperm_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); -} - -int -freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap) -{ - const void *msgp; - long mtype; - int32_t mtype32; - int error; - - msgp = PTRIN(uap->msgp); - if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0) - return (error); - mtype = mtype32; - return (kern_msgsnd(td, uap->msqid, - (const char *)msgp + sizeof(mtype32), - uap->msgsz, uap->msgflg, mtype)); -} - -int -freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap) -{ - void *msgp; - long mtype; - int32_t mtype32; - int error; - - msgp = PTRIN(uap->msgp); - if ((error = kern_msgrcv(td, uap->msqid, - (char *)msgp + sizeof(mtype32), uap->msgsz, - uap->msgtyp, uap->msgflg, &mtype)) != 0) - return (error); - mtype32 = (int32_t)mtype; - return (copyout(&mtype32, msgp, sizeof(mtype32))); -} - -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; - - ap.shmid = uap->a2; - ap.shmaddr = PTRIN(uap->a3); - ap.shmflg = uap->a4; - return (sysent[SYS_shmat].sy_call(td, &ap)); - } - case 2: { /* shmdt */ - struct shmdt_args ap; - - ap.shmaddr = PTRIN(uap->a2); - return (sysent[SYS_shmdt].sy_call(td, &ap)); - } - case 3: { /* shmget */ - struct shmget_args ap; - - ap.key = uap->a2; - ap.size = uap->a3; - ap.shmflg = uap->a4; - return (sysent[SYS_shmget].sy_call(td, &ap)); - } - case 4: { /* shmctl */ - struct freebsd7_freebsd32_shmctl_args ap; - - ap.shmid = uap->a2; - ap.cmd = uap->a3; - ap.buf = PTRIN(uap->a4); - return (freebsd7_freebsd32_shmctl(td, &ap)); - } - case 1: /* oshmctl */ - 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) -{ - int error = 0; - union { - struct shmid_ds shmid_ds; - struct shm_info shm_info; - struct shminfo shminfo; - } u; - union { - struct shmid_ds32 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_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_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); - 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); -} - int freebsd32_pread(struct thread *td, struct freebsd32_pread_args *uap) { @@ -3084,6 +2499,36 @@ syscall32_module_handler(struct module *mod, int what, void *arg) } } +int +syscall32_helper_register(struct syscall_helper_data *sd) +{ + struct syscall_helper_data *sd1; + int error; + + for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) { + error = syscall32_register(&sd1->syscall_no, &sd1->new_sysent, + &sd1->old_sysent); + if (error != 0) { + syscall32_helper_unregister(sd); + return (error); + } + sd1->registered = 1; + } + return (0); +} + +int +syscall32_helper_unregister(struct syscall_helper_data *sd) +{ + struct syscall_helper_data *sd1; + + for (sd1 = sd; sd1->registered != 0; sd1++) { + syscall32_deregister(&sd1->syscall_no, &sd1->old_sysent); + sd1->registered = 0; + } + return (0); +} + register_t * freebsd32_copyout_strings(struct image_params *imgp) { diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h index 5e5942b..f5ccbf1 100644 --- a/sys/compat/freebsd32/freebsd32_util.h +++ b/sys/compat/freebsd32/freebsd32_util.h @@ -61,7 +61,7 @@ static struct syscall_module_data name##_syscall32_mod = { \ }; \ \ static moduledata_t name##32_mod = { \ - #name, \ + "sys32/" #name, \ syscall32_module_handler, \ &name##_syscall32_mod \ }; \ @@ -78,11 +78,25 @@ SYSCALL32_MODULE(syscallname, \ & syscallname##_syscall32, & syscallname##_sysent32,\ NULL, NULL); +#define SYSCALL32_INIT_HELPER(syscallname) { \ + .new_sysent = { \ + .sy_narg = (sizeof(struct syscallname ## _args ) \ + / sizeof(register_t)), \ + .sy_call = (sy_call_t *)& syscallname, \ + }, \ + .syscall_no = FREEBSD32_SYS_##syscallname \ +} + int syscall32_register(int *offset, struct sysent *new_sysent, struct sysent *old_sysent); int syscall32_deregister(int *offset, struct sysent *old_sysent); int syscall32_module_handler(struct module *mod, int what, void *arg); +int syscall32_helper_register(struct syscall_helper_data *sd); +int syscall32_helper_unregister(struct syscall_helper_data *sd); register_t *freebsd32_copyout_strings(struct image_params *imgp); +struct iovec32; +int freebsd32_copyiniov(struct iovec32 *iovp, u_int iovcnt, + struct iovec **iov, int error); #endif /* !_COMPAT_FREEBSD32_FREEBSD32_UTIL_H_ */ diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 4817f7b..1afe586 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -309,11 +309,11 @@ struct rtprio *rtp); } 167 AUE_NULL UNIMPL nosys 168 AUE_NULL UNIMPL nosys -169 AUE_SEMSYS STD { int freebsd32_semsys(int which, int a2, \ +169 AUE_SEMSYS NOSTD { int freebsd32_semsys(int which, int a2, \ int a3, int a4, int a5); } -170 AUE_MSGSYS STD { int freebsd32_msgsys(int which, int a2, \ +170 AUE_MSGSYS NOSTD { int freebsd32_msgsys(int which, int a2, \ int a3, int a4, int a5, int a6); } -171 AUE_SHMSYS STD { int freebsd32_shmsys(uint32_t which, uint32_t a2, \ +171 AUE_SHMSYS NOSTD { int freebsd32_shmsys(uint32_t which, uint32_t a2, \ uint32_t a3, uint32_t a4); } 172 AUE_NULL UNIMPL nosys 173 AUE_PREAD COMPAT6 { ssize_t freebsd32_pread(int fd, void *buf, \ @@ -401,26 +401,29 @@ ; The following were introduced with NetBSD/4.4Lite-2 ; They are initialized by their respective modules/sysinits ; XXX PROBLEM!! -220 AUE_SEMCTL COMPAT7 { int freebsd32_semctl(int semid, int semnum, \ +220 AUE_SEMCTL COMPAT7|NOSTD { int freebsd32_semctl( \ + int semid, int semnum, \ int cmd, union semun32 *arg); } -221 AUE_SEMGET NOPROTO { int semget(key_t key, int nsems, \ +221 AUE_SEMGET NOSTD|NOPROTO { int semget(key_t key, int nsems, \ int semflg); } -222 AUE_SEMOP NOPROTO { int semop(int semid, struct sembuf *sops, \ - u_int nsops); } +222 AUE_SEMOP NOSTD|NOPROTO { int semop(int semid, \ + struct sembuf *sops, u_int nsops); } 223 AUE_NULL UNIMPL semconfig -224 AUE_MSGCTL COMPAT7 { int freebsd32_msgctl(int msqid, int cmd, \ +224 AUE_MSGCTL COMPAT7|NOSTD { 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, \ +225 AUE_MSGGET NOSTD|NOPROTO { int msgget(key_t key, int msgflg); } +226 AUE_MSGSND NOSTD { int freebsd32_msgsnd(int msqid, void *msgp, \ size_t msgsz, int msgflg); } -227 AUE_MSGRCV STD { int freebsd32_msgrcv(int msqid, void *msgp, \ +227 AUE_MSGRCV NOSTD { int freebsd32_msgrcv(int msqid, void *msgp, \ size_t msgsz, long msgtyp, int msgflg); } -228 AUE_SHMAT NOPROTO { int shmat(int shmid, void *shmaddr, \ +228 AUE_SHMAT NOSTD|NOPROTO { int shmat(int shmid, void *shmaddr, \ int shmflg); } -229 AUE_SHMCTL COMPAT7 { int freebsd32_shmctl(int shmid, int cmd, \ +229 AUE_SHMCTL COMPAT7|NOSTD { 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, \ +230 AUE_SHMDT NOSTD|NOPROTO { int shmdt(void *shmaddr); } +231 AUE_SHMGET NOSTD|NOPROTO { int shmget(key_t key, int size, \ int shmflg); } ; 232 AUE_NULL STD { int freebsd32_clock_gettime(clockid_t clock_id, \ @@ -694,16 +697,19 @@ 398 AUE_FHSTATFS NOPROTO { int fhstatfs(const struct fhandle *u_fhp, \ struct statfs *buf); } 399 AUE_NULL UNIMPL nosys -; XXX implement these? -400 AUE_NULL UNIMPL ksem_close -401 AUE_NULL UNIMPL ksem_post -402 AUE_NULL UNIMPL ksem_wait -403 AUE_NULL UNIMPL ksem_trywait -404 AUE_NULL UNIMPL ksem_init -405 AUE_NULL UNIMPL ksem_open -406 AUE_NULL UNIMPL ksem_unlink -407 AUE_NULL UNIMPL ksem_getvalue -408 AUE_NULL UNIMPL ksem_destroy +400 AUE_NULL NOSTD|NOPROTO { int ksem_close(semid_t id); } +401 AUE_NULL NOSTD|NOPROTO { int ksem_post(semid_t id); } +402 AUE_NULL NOSTD|NOPROTO { int ksem_wait(semid_t id); } +403 AUE_NULL NOSTD|NOPROTO { int ksem_trywait(semid_t id); } +404 AUE_NULL NOSTD { int freebsd32_ksem_init(semid_t *idp, \ + unsigned int value); } +405 AUE_NULL NOSTD { int freebsd32_ksem_open(semid_t *idp, \ + const char *name, int oflag, \ + mode_t mode, unsigned int value); } +406 AUE_NULL NOSTD|NOPROTO { int ksem_unlink(const char *name); } +407 AUE_NULL NOSTD|NOPROTO { int ksem_getvalue(semid_t id, \ + int *val); } +408 AUE_NULL NOSTD|NOPROTO { int ksem_destroy(semid_t id); } 409 AUE_NULL UNIMPL __mac_get_pid 410 AUE_NULL UNIMPL __mac_get_link 411 AUE_NULL UNIMPL __mac_set_link @@ -762,7 +768,8 @@ const char *path, int attrnamespace, \ void *data, size_t nbytes); } 440 AUE_NULL UNIMPL kse_switchin -441 AUE_NULL UNIMPL ksem_timedwait +441 AUE_NULL NOSTD { int freebsd32_ksem_timedwait(semid_t id, \ + const struct timespec32 *abstime); } 442 AUE_NULL STD { int freebsd32_thr_suspend( \ const struct timespec32 *timeout); } 443 AUE_NULL NOPROTO { int thr_wake(long id); } @@ -790,12 +797,23 @@ int param_size); } 456 AUE_NULL NOPROTO { int sigqueue(pid_t pid, int signum, \ void *value); } -457 AUE_NULL UNIMPL kmq_open -458 AUE_NULL UNIMPL kmq_setattr -459 AUE_NULL UNIMPL kmq_timedreceive -460 AUE_NULL UNIMPL kmq_timedsend -461 AUE_NULL UNIMPL kmq_notify -462 AUE_NULL UNIMPL kmq_unlink +457 AUE_NULL NOSTD { int freebsd32_kmq_open( \ + const char *path, int flags, mode_t mode, \ + const struct mq_attr32 *attr); } +458 AUE_NULL NOSTD { int freebsd32_kmq_setattr(int mqd, \ + const struct mq_attr32 *attr, \ + struct mq_attr32 *oattr); } +459 AUE_NULL NOSTD { int freebsd32_kmq_timedreceive(int mqd, \ + char *msg_ptr, size_t msg_len, \ + unsigned *msg_prio, \ + const struct timespec32 *abs_timeout); } +460 AUE_NULL NOSTD { int freebsd32_kmq_timedsend(int mqd, \ + const char *msg_ptr, size_t msg_len,\ + unsigned msg_prio, \ + const struct timespec32 *abs_timeout);} +461 AUE_NULL NOPROTO|NOSTD { int kmq_notify(int mqd, \ + const struct sigevent *sigev); } +462 AUE_NULL NOPROTO|NOSTD { int kmq_unlink(const char *path); } 463 AUE_NULL NOPROTO { int abort2(const char *why, int nargs, void **args); } 464 AUE_NULL NOPROTO { int thr_set_name(long id, const char *name); } 465 AUE_NULL NOSTD { int freebsd32_aio_fsync(int op, \ @@ -925,11 +943,11 @@ 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, \ +510 AUE_SEMCTL NOSTD { int freebsd32_semctl(int semid, int semnum, \ int cmd, union semun32 *arg); } -511 AUE_MSGCTL STD { int freebsd32_msgctl(int msqid, int cmd, \ +511 AUE_MSGCTL NOSTD { int freebsd32_msgctl(int msqid, int cmd, \ struct msqid_ds32 *buf); } -512 AUE_SHMCTL STD { int freebsd32_shmctl(int shmid, int cmd, \ +512 AUE_SHMCTL NOSTD { int freebsd32_shmctl(int shmid, int cmd, \ struct shmid_ds32 *buf); } 513 AUE_LPATHCONF NOPROTO { int lpathconf(char *path, int name); } 514 AUE_CAP_NEW UNIMPL cap_new diff --git a/sys/kern/kern_syscalls.c b/sys/kern/kern_syscalls.c index 077aedc..9cb7b68 100644 --- a/sys/kern/kern_syscalls.c +++ b/sys/kern/kern_syscalls.c @@ -135,3 +135,33 @@ syscall_module_handler(struct module *mod, int what, void *arg) else return (0); } + +int +syscall_helper_register(struct syscall_helper_data *sd) +{ + struct syscall_helper_data *sd1; + int error; + + for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) { + error = syscall_register(&sd1->syscall_no, &sd1->new_sysent, + &sd1->old_sysent); + if (error != 0) { + syscall_helper_unregister(sd); + return (error); + } + sd1->registered = 1; + } + return (0); +} + +int +syscall_helper_unregister(struct syscall_helper_data *sd) +{ + struct syscall_helper_data *sd1; + + for (sd1 = sd; sd1->registered != 0; sd1++) { + syscall_deregister(&sd1->syscall_no, &sd1->old_sysent); + sd1->registered = 0; + } + return (0); +} diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c index d33fdb0..e402cb5 100644 --- a/sys/kern/sysv_ipc.c +++ b/sys/kern/sysv_ipc.c @@ -178,3 +178,69 @@ ipcperm_new2old(struct ipc_perm *new, struct ipc_perm_old *old) old->key = new->key; } #endif + +#ifdef COMPAT_FREEBSD32 +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) +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); +} + +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 + +void +freebsd32_ipcperm_in(struct ipc_perm32 *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); +} + +void +freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *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 diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c index c7c67d4..01d7f79 100644 --- a/sys/kern/sysv_msg.c +++ b/sys/kern/sysv_msg.c @@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$"); static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues"); -static void msginit(void); +static int msginit(void); static int msgunload(void); static int sysvmsg_modload(struct module *, int, void *); @@ -152,10 +152,45 @@ static struct msg *msghdrs; /* MSGTQL msg headers */ static struct msqid_kernel *msqids; /* MSGMNI msqid_kernel struct's */ static struct mtx msq_mtx; /* global mutex for message queues. */ -static void +static struct syscall_helper_data msg_syscalls[] = { + SYSCALL_INIT_HELPER(msgctl), + SYSCALL_INIT_HELPER(msgget), + SYSCALL_INIT_HELPER(msgsnd), + SYSCALL_INIT_HELPER(msgrcv), +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) + SYSCALL_INIT_HELPER(msgsys), + SYSCALL_INIT_HELPER(freebsd7_msgctl), +#endif + SYSCALL_INIT_LAST +}; + +#ifdef COMPAT_FREEBSD32 +#include +#include +#include +#include +#include +#include + +static struct syscall_helper_data msg32_syscalls[] = { + SYSCALL32_INIT_HELPER(freebsd32_msgctl), + SYSCALL32_INIT_HELPER(freebsd32_msgsnd), + SYSCALL32_INIT_HELPER(freebsd32_msgrcv), + SYSCALL32_INIT_HELPER(msgget), + SYSCALL32_INIT_HELPER(freebsd32_msgsys), +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) + SYSCALL32_INIT_HELPER(freebsd7_freebsd32_msgctl), +#endif + SYSCALL_INIT_LAST +}; +#endif + +static int msginit() { - register int i; + int i, error; TUNABLE_INT_FETCH("kern.ipc.msgseg", &msginfo.msgseg); TUNABLE_INT_FETCH("kern.ipc.msgssz", &msginfo.msgssz); @@ -235,6 +270,16 @@ msginit() #endif } mtx_init(&msq_mtx, "msq", NULL, MTX_DEF); + + error = syscall_helper_register(msg_syscalls); + if (error != 0) + return (error); +#ifdef COMPAT_FREEBSD32 + error = syscall32_helper_register(msg32_syscalls); + if (error != 0) + return (error); +#endif + return (0); } static int @@ -246,6 +291,11 @@ msgunload() int i; #endif + syscall_helper_unregister(msg_syscalls); +#ifdef COMPAT_FREEBSD32 + syscall32_helper_unregister(msg32_syscalls); +#endif + for (msqid = 0; msqid < msginfo.msgmni; msqid++) { /* * Look for an unallocated and unlocked msqid_ds. @@ -283,7 +333,9 @@ sysvmsg_modload(struct module *module, int cmd, void *arg) switch (cmd) { case MOD_LOAD: - msginit(); + error = msginit(); + if (error != 0) + msgunload(); break; case MOD_UNLOAD: error = msgunload(); @@ -303,11 +355,6 @@ static moduledata_t sysvmsg_mod = { NULL }; -SYSCALL_MODULE_HELPER(msgctl); -SYSCALL_MODULE_HELPER(msgget); -SYSCALL_MODULE_HELPER(msgsnd); -SYSCALL_MODULE_HELPER(msgrcv); - DECLARE_MODULE(sysvmsg, sysvmsg_mod, SI_SUB_SYSV_MSG, SI_ORDER_FIRST); MODULE_VERSION(sysvmsg, 1); @@ -1257,10 +1304,159 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, msgseg, CTLFLAG_RDTUN, &msginfo.msgseg, 0, SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLFLAG_RD, NULL, 0, sysctl_msqids, "", "Message queue IDs"); +#ifdef COMPAT_FREEBSD32 +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 (freebsd7_freebsd32_msgctl(td, + (struct freebsd7_freebsd32_msgctl_args *)&uap->a2)); + case 2: + return (freebsd32_msgsnd(td, + (struct freebsd32_msgsnd_args *)&uap->a2)); + case 3: + return (freebsd32_msgrcv(td, + (struct freebsd32_msgrcv_args *)&uap->a2)); + 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) +{ + struct msqid_ds msqbuf; + struct msqid_ds32 msqbuf32; + int error; + + if (uap->cmd == IPC_SET) { + error = copyin(uap->buf, &msqbuf32, sizeof(msqbuf32)); + if (error) + return (error); + freebsd32_ipcperm_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) { + freebsd32_ipcperm_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); +} + +int +freebsd32_msgsnd(struct thread *td, struct freebsd32_msgsnd_args *uap) +{ + const void *msgp; + long mtype; + int32_t mtype32; + int error; + + msgp = PTRIN(uap->msgp); + if ((error = copyin(msgp, &mtype32, sizeof(mtype32))) != 0) + return (error); + mtype = mtype32; + return (kern_msgsnd(td, uap->msqid, + (const char *)msgp + sizeof(mtype32), + uap->msgsz, uap->msgflg, mtype)); +} + +int +freebsd32_msgrcv(struct thread *td, struct freebsd32_msgrcv_args *uap) +{ + void *msgp; + long mtype; + int32_t mtype32; + int error; + + msgp = PTRIN(uap->msgp); + if ((error = kern_msgrcv(td, uap->msqid, + (char *)msgp + sizeof(mtype32), uap->msgsz, + uap->msgtyp, uap->msgflg, &mtype)) != 0) + return (error); + mtype32 = (int32_t)mtype; + return (copyout(&mtype32, msgp, sizeof(mtype32))); +} +#endif + #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[] = { @@ -1295,7 +1491,9 @@ msgsys(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_msgctl_args { diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 2f2b528..f6d781c 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 +#include +#include +#include +#include +#include + +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 */ diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index a16c8af..ddf4ce1 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -122,7 +122,7 @@ static struct shmid_kernel *shm_find_segment_by_shmid(int); static struct shmid_kernel *shm_find_segment_by_shmidx(int); static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *); static void shmrealloc(void); -static void shminit(void); +static int shminit(void); static int sysvshm_modload(struct module *, int, void *); static int shmunload(void); static void shmexit_myhook(struct vmspace *vm); @@ -816,10 +816,47 @@ shmrealloc(void) shmalloced = shminfo.shmmni; } -static void +static struct syscall_helper_data shm_syscalls[] = { + SYSCALL_INIT_HELPER(shmat), + SYSCALL_INIT_HELPER(shmctl), + SYSCALL_INIT_HELPER(shmdt), + SYSCALL_INIT_HELPER(shmget), +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) + SYSCALL_INIT_HELPER(freebsd7_shmctl), +#endif +#if defined(__i386__) && (defined(COMPAT_FREEBSD4) || defined(COMPAT_43)) + SYSCALL_INIT_HELPER(shmsys), +#endif + SYSCALL_INIT_LAST +}; + +#ifdef COMPAT_FREEBSD32 +#include +#include +#include +#include +#include +#include + +static struct syscall_helper_data shm32_syscalls[] = { + SYSCALL32_INIT_HELPER(shmat), + SYSCALL32_INIT_HELPER(shmdt), + SYSCALL32_INIT_HELPER(shmget), + SYSCALL32_INIT_HELPER(freebsd32_shmsys), + SYSCALL32_INIT_HELPER(freebsd32_shmctl), +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) + SYSCALL32_INIT_HELPER(freebsd7_freebsd32_shmctl), +#endif + SYSCALL_INIT_LAST +}; +#endif + +static int shminit() { - int i; + int i, error; #ifndef BURN_BRIDGES if (TUNABLE_ULONG_FETCH("kern.ipc.shmmaxpgs", &shminfo.shmall) != 0) @@ -855,6 +892,16 @@ shminit() shm_committed = 0; shmexit_hook = &shmexit_myhook; shmfork_hook = &shmfork_myhook; + + error = syscall_helper_register(shm_syscalls); + if (error != 0) + return (error); +#ifdef COMPAT_FREEBSD32 + error = syscall32_helper_register(shm32_syscalls); + if (error != 0) + return (error); +#endif + return (0); } static int @@ -867,6 +914,11 @@ shmunload() if (shm_nused > 0) return (EBUSY); +#ifdef COMPAT_FREEBSD32 + syscall32_helper_unregister(shm32_syscalls); +#endif + syscall_helper_unregister(shm_syscalls); + #ifdef MAC for (i = 0; i < shmalloced; i++) mac_sysvshm_destroy(&shmsegs[i]); @@ -985,14 +1037,234 @@ shmsys(td, uap) return (error); } -SYSCALL_MODULE_HELPER(shmsys); #endif /* i386 && (COMPAT_FREEBSD4 || COMPAT_43) */ +#ifdef COMPAT_FREEBSD32 + +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; + + ap.shmid = uap->a2; + ap.shmaddr = PTRIN(uap->a3); + ap.shmflg = uap->a4; + return (sysent[SYS_shmat].sy_call(td, &ap)); + } + case 2: { /* shmdt */ + struct shmdt_args ap; -#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0) + ap.shmaddr = PTRIN(uap->a2); + return (sysent[SYS_shmdt].sy_call(td, &ap)); + } + case 3: { /* shmget */ + struct shmget_args ap; + ap.key = uap->a2; + ap.size = uap->a3; + ap.shmflg = uap->a4; + return (sysent[SYS_shmget].sy_call(td, &ap)); + } + case 4: { /* shmctl */ + struct freebsd7_freebsd32_shmctl_args ap; + + ap.shmid = uap->a2; + ap.cmd = uap->a3; + ap.buf = PTRIN(uap->a4); + return (freebsd7_freebsd32_shmctl(td, &ap)); + } + case 1: /* oshmctl */ + 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) +{ + int error = 0; + union { + struct shmid_ds shmid_ds; + struct shm_info shm_info; + struct shminfo shminfo; + } u; + union { + struct shmid_ds32 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_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_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); + 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 + +#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ + defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) + +#ifndef CP +#define CP(src, dst, fld) do { (dst).fld = (src).fld; } while (0) +#endif #ifndef _SYS_SYSPROTO_H_ struct freebsd7_shmctl_args { @@ -1068,10 +1340,6 @@ done: return (error); } -SYSCALL_MODULE_HELPER(freebsd7_shmctl); - -#undef CP - #endif /* COMPAT_FREEBSD4 || COMPAT_FREEBSD5 || COMPAT_FREEBSD6 || COMPAT_FREEBSD7 */ @@ -1082,7 +1350,9 @@ sysvshm_modload(struct module *module, int cmd, void *arg) switch (cmd) { case MOD_LOAD: - shminit(); + error = shminit(); + if (error != 0) + shmunload(); break; case MOD_UNLOAD: error = shmunload(); @@ -1102,10 +1372,5 @@ static moduledata_t sysvshm_mod = { NULL }; -SYSCALL_MODULE_HELPER(shmat); -SYSCALL_MODULE_HELPER(shmctl); -SYSCALL_MODULE_HELPER(shmdt); -SYSCALL_MODULE_HELPER(shmget); - DECLARE_MODULE(sysvshm, sysvshm_mod, SI_SUB_SYSV_SHM, SI_ORDER_FIRST); MODULE_VERSION(sysvshm, 1); diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index c44ab5a..a34c228 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -45,6 +45,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" + #include #include #include @@ -1622,7 +1624,7 @@ mqueue_send(struct mqueue *mq, const char *msg_ptr, const struct timespec *abs_timeout) { struct mqueue_msg *msg; - struct timespec ets, ts, ts2; + struct timespec ts, ts2; struct timeval tv; int error; @@ -1658,15 +1660,12 @@ mqueue_send(struct mqueue *mq, const char *msg_ptr, if (error != EAGAIN) goto bad; - error = copyin(abs_timeout, &ets, sizeof(ets)); - if (error != 0) - goto bad; - if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) { + if (abs_timeout->tv_nsec >= 1000000000 || abs_timeout->tv_nsec < 0) { error = EINVAL; goto bad; } for (;;) { - ts2 = ets; + ts2 = *abs_timeout; getnanotime(&ts); timespecsub(&ts2, &ts); if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) { @@ -1773,7 +1772,7 @@ mqueue_receive(struct mqueue *mq, char *msg_ptr, const struct timespec *abs_timeout) { struct mqueue_msg *msg; - struct timespec ets, ts, ts2; + struct timespec ts, ts2; struct timeval tv; int error; @@ -1804,16 +1803,13 @@ mqueue_receive(struct mqueue *mq, char *msg_ptr, if (error != EAGAIN) return (error); - error = copyin(abs_timeout, &ets, sizeof(ets)); - if (error != 0) - return (error); - if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) { + if (abs_timeout->tv_nsec >= 1000000000 || abs_timeout->tv_nsec < 0) { error = EINVAL; return (error); } for (;;) { - ts2 = ets; + ts2 = *abs_timeout; getnanotime(&ts); timespecsub(&ts2, &ts); if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) { @@ -1934,40 +1930,28 @@ notifier_remove(struct proc *p, struct mqueue *mq, int fd) PROC_UNLOCK(p); } -/* - * Syscall to open a message queue. - */ -int -kmq_open(struct thread *td, struct kmq_open_args *uap) +static int +kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode, + const struct mq_attr *attr) { char path[MQFS_NAMELEN + 1]; - struct mq_attr attr, *pattr; struct mqfs_node *pn; struct filedesc *fdp; struct file *fp; struct mqueue *mq; - int fd, error, len, flags, cmode; - - if ((uap->flags & O_ACCMODE) == O_ACCMODE) - return (EINVAL); + int fd, error, len, cmode; fdp = td->td_proc->p_fd; - flags = FFLAGS(uap->flags); - cmode = (((uap->mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT); + cmode = (((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT); mq = NULL; - if ((flags & O_CREAT) && (uap->attr != NULL)) { - error = copyin(uap->attr, &attr, sizeof(attr)); - if (error) - return (error); - if (attr.mq_maxmsg <= 0 || attr.mq_maxmsg > maxmsg) + if ((flags & O_CREAT) != 0 && attr != NULL) { + if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > maxmsg) return (EINVAL); - if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize) + if (attr->mq_msgsize <= 0 || attr->mq_msgsize > maxmsgsize) return (EINVAL); - pattr = &attr; - } else - pattr = NULL; + } - error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL); + error = copyinstr(upath, path, MQFS_NAMELEN + 1, NULL); if (error) return (error); @@ -1990,7 +1974,7 @@ kmq_open(struct thread *td, struct kmq_open_args *uap) if (!(flags & O_CREAT)) { error = ENOENT; } else { - mq = mqueue_alloc(pattr); + mq = mqueue_alloc(attr); if (mq == NULL) { error = ENFILE; } else { @@ -2045,6 +2029,27 @@ kmq_open(struct thread *td, struct kmq_open_args *uap) } /* + * Syscall to open a message queue. + */ +int +kmq_open(struct thread *td, struct kmq_open_args *uap) +{ + struct mq_attr attr; + int flags, error; + + if ((uap->flags & O_ACCMODE) == O_ACCMODE) + return (EINVAL); + flags = FFLAGS(uap->flags); + if ((flags & O_CREAT) != 0 && uap->attr != NULL) { + error = copyin(uap->attr, &attr, sizeof(attr)); + if (error) + return (error); + } + return (kern_kmq_open(td, uap->path, flags, uap->mode, + uap->attr != NULL ? &attr : NULL)); +} + +/* * Syscall to unlink a message queue. */ int @@ -2120,39 +2125,52 @@ getmq_write(struct thread *td, int fd, struct file **fpp, return _getmq(td, fd, fget_write, fpp, ppn, pmq); } -int -kmq_setattr(struct thread *td, struct kmq_setattr_args *uap) +static int +kern_kmq_setattr(struct thread *td, int mqd, const struct mq_attr *attr, + struct mq_attr *oattr) { struct mqueue *mq; struct file *fp; - struct mq_attr attr, oattr; u_int oflag, flag; int error; - if (uap->attr) { - error = copyin(uap->attr, &attr, sizeof(attr)); - if (error) - return (error); - if (attr.mq_flags & ~O_NONBLOCK) - return (EINVAL); - } - error = getmq(td, uap->mqd, &fp, NULL, &mq); + if (attr != NULL && (attr->mq_flags & ~O_NONBLOCK) != 0) + return (EINVAL); + error = getmq(td, mqd, &fp, NULL, &mq); if (error) return (error); - oattr.mq_maxmsg = mq->mq_maxmsg; - oattr.mq_msgsize = mq->mq_msgsize; - oattr.mq_curmsgs = mq->mq_curmsgs; - if (uap->attr) { + oattr->mq_maxmsg = mq->mq_maxmsg; + oattr->mq_msgsize = mq->mq_msgsize; + oattr->mq_curmsgs = mq->mq_curmsgs; + if (attr != NULL) { do { oflag = flag = fp->f_flag; flag &= ~O_NONBLOCK; - flag |= (attr.mq_flags & O_NONBLOCK); + flag |= (attr->mq_flags & O_NONBLOCK); } while (atomic_cmpset_int(&fp->f_flag, oflag, flag) == 0); } else oflag = fp->f_flag; - oattr.mq_flags = (O_NONBLOCK & oflag); + oattr->mq_flags = (O_NONBLOCK & oflag); fdrop(fp, td); - if (uap->oattr) + return (error); +} + +int +kmq_setattr(struct thread *td, struct kmq_setattr_args *uap) +{ + struct mq_attr attr, oattr; + int error; + + if (uap->attr != NULL) { + error = copyin(uap->attr, &attr, sizeof(attr)); + if (error != 0) + return (error); + } + error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL, + &oattr); + if (error != 0) + return (error); + if (uap->oattr != NULL) error = copyout(&oattr, uap->oattr, sizeof(oattr)); return (error); } @@ -2162,15 +2180,23 @@ kmq_timedreceive(struct thread *td, struct kmq_timedreceive_args *uap) { struct mqueue *mq; struct file *fp; + struct timespec *abs_timeout, ets; int error; int waitok; error = getmq_read(td, uap->mqd, &fp, NULL, &mq); if (error) return (error); + if (uap->abs_timeout != NULL) { + error = copyin(uap->abs_timeout, &ets, sizeof(ets)); + if (error != 0) + return (error); + abs_timeout = &ets; + } else + abs_timeout = NULL; waitok = !(fp->f_flag & O_NONBLOCK); error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len, - uap->msg_prio, waitok, uap->abs_timeout); + uap->msg_prio, waitok, abs_timeout); fdrop(fp, td); return (error); } @@ -2180,14 +2206,22 @@ kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap) { struct mqueue *mq; struct file *fp; + struct timespec *abs_timeout, ets; int error, waitok; error = getmq_write(td, uap->mqd, &fp, NULL, &mq); if (error) return (error); + if (uap->abs_timeout != NULL) { + error = copyin(uap->abs_timeout, &ets, sizeof(ets)); + if (error != 0) + return (error); + abs_timeout = &ets; + } else + abs_timeout = NULL; waitok = !(fp->f_flag & O_NONBLOCK); error = mqueue_send(mq, uap->msg_ptr, uap->msg_len, - uap->msg_prio, waitok, uap->abs_timeout); + uap->msg_prio, waitok, abs_timeout); fdrop(fp, td); return (error); } @@ -2511,12 +2545,219 @@ static struct vfsops mqfs_vfsops = { .vfs_statfs = mqfs_statfs, }; -SYSCALL_MODULE_HELPER(kmq_open); -SYSCALL_MODULE_HELPER(kmq_setattr); -SYSCALL_MODULE_HELPER(kmq_timedsend); -SYSCALL_MODULE_HELPER(kmq_timedreceive); -SYSCALL_MODULE_HELPER(kmq_notify); -SYSCALL_MODULE_HELPER(kmq_unlink); +static struct vfsconf mqueuefs_vfsconf = { + .vfc_version = VFS_VERSION, + .vfc_name = "mqueuefs", + .vfc_vfsops = &mqfs_vfsops, + .vfc_typenum = -1, + .vfc_flags = VFCF_SYNTHETIC +}; + +static struct syscall_helper_data mq_syscalls[] = { + SYSCALL_INIT_HELPER(kmq_open), + SYSCALL_INIT_HELPER(kmq_setattr), + SYSCALL_INIT_HELPER(kmq_timedsend), + SYSCALL_INIT_HELPER(kmq_timedreceive), + SYSCALL_INIT_HELPER(kmq_notify), + SYSCALL_INIT_HELPER(kmq_unlink), + SYSCALL_INIT_LAST +}; + +#ifdef COMPAT_FREEBSD32 +#include +#include +#include +#include + +static void +mq_attr_from32(const struct mq_attr32 *from, struct mq_attr *to) +{ + + to->mq_flags = from->mq_flags; + to->mq_maxmsg = from->mq_maxmsg; + to->mq_msgsize = from->mq_msgsize; + to->mq_curmsgs = from->mq_curmsgs; +} + +static void +mq_attr_to32(const struct mq_attr *from, struct mq_attr32 *to) +{ + + to->mq_flags = from->mq_flags; + to->mq_maxmsg = from->mq_maxmsg; + to->mq_msgsize = from->mq_msgsize; + to->mq_curmsgs = from->mq_curmsgs; +} + +int +freebsd32_kmq_open(struct thread *td, struct freebsd32_kmq_open_args *uap) +{ + struct mq_attr attr; + struct mq_attr32 attr32; + int flags, error; + + if ((uap->flags & O_ACCMODE) == O_ACCMODE) + return (EINVAL); + flags = FFLAGS(uap->flags); + if ((flags & O_CREAT) != 0 && uap->attr != NULL) { + error = copyin(uap->attr, &attr32, sizeof(attr32)); + if (error) + return (error); + mq_attr_from32(&attr32, &attr); + } + return (kern_kmq_open(td, uap->path, flags, uap->mode, + uap->attr != NULL ? &attr : NULL)); +} + +int +freebsd32_kmq_setattr(struct thread *td, struct freebsd32_kmq_setattr_args *uap) +{ + struct mq_attr attr, oattr; + struct mq_attr32 attr32, oattr32; + int error; + + if (uap->attr != NULL) { + error = copyin(uap->attr, &attr32, sizeof(attr32)); + if (error != 0) + return (error); + mq_attr_from32(&attr32, &attr); + } + error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL, + &oattr); + if (error != 0) + return (error); + if (uap->oattr != NULL) { + mq_attr_to32(&oattr, &oattr32); + error = copyout(&oattr32, uap->oattr, sizeof(oattr32)); + } + return (error); +} + +int +freebsd32_kmq_timedsend(struct thread *td, + struct freebsd32_kmq_timedsend_args *uap) +{ + struct mqueue *mq; + struct file *fp; + struct timespec32 ets32; + struct timespec *abs_timeout, ets; + int error; + int waitok; + + error = getmq_read(td, uap->mqd, &fp, NULL, &mq); + if (error) + return (error); + if (uap->abs_timeout != NULL) { + error = copyin(uap->abs_timeout, &ets32, sizeof(ets32)); + if (error != 0) + return (error); + CP(ets32, ets, tv_sec); + CP(ets32, ets, tv_nsec); + abs_timeout = &ets; + } else + abs_timeout = NULL; + waitok = !(fp->f_flag & O_NONBLOCK); + error = mqueue_send(mq, uap->msg_ptr, uap->msg_len, + uap->msg_prio, waitok, abs_timeout); + fdrop(fp, td); + return (error); +} + +int +freebsd32_kmq_timedreceive(struct thread *td, + struct freebsd32_kmq_timedreceive_args *uap) +{ + struct mqueue *mq; + struct file *fp; + struct timespec32 ets32; + struct timespec *abs_timeout, ets; + int error, waitok; + + error = getmq_write(td, uap->mqd, &fp, NULL, &mq); + if (error) + return (error); + if (uap->abs_timeout != NULL) { + error = copyin(uap->abs_timeout, &ets32, sizeof(ets32)); + if (error != 0) + return (error); + CP(ets32, ets, tv_sec); + CP(ets32, ets, tv_nsec); + abs_timeout = &ets; + } else + abs_timeout = NULL; + waitok = !(fp->f_flag & O_NONBLOCK); + error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len, + uap->msg_prio, waitok, abs_timeout); + fdrop(fp, td); + return (error); +} + +static struct syscall_helper_data mq32_syscalls[] = { + SYSCALL32_INIT_HELPER(freebsd32_kmq_open), + SYSCALL32_INIT_HELPER(freebsd32_kmq_setattr), + SYSCALL32_INIT_HELPER(freebsd32_kmq_timedsend), + SYSCALL32_INIT_HELPER(freebsd32_kmq_timedreceive), + SYSCALL32_INIT_HELPER(kmq_notify), + SYSCALL32_INIT_HELPER(kmq_unlink), + SYSCALL_INIT_LAST +}; +#endif + +static int +mqinit(void) +{ + int error; + + error = syscall_helper_register(mq_syscalls); + if (error != 0) + return (error); +#ifdef COMPAT_FREEBSD32 + error = syscall32_helper_register(mq32_syscalls); + if (error != 0) + return (error); +#endif + return (0); +} + +static int +mqunload(void) +{ + +#ifdef COMPAT_FREEBSD32 + syscall32_helper_unregister(mq32_syscalls); +#endif + syscall_helper_unregister(mq_syscalls); + return (0); +} + +static int +mq_modload(struct module *module, int cmd, void *arg) +{ + int error = 0; + + error = vfs_modevent(module, cmd, arg); + if (error != 0) + return (error); -VFS_SET(mqfs_vfsops, mqueuefs, VFCF_SYNTHETIC); + switch (cmd) { + case MOD_LOAD: + error = mqinit(); + if (error != 0) + mqunload(); + break; + case MOD_UNLOAD: + error = mqunload(); + break; + default: + break; + } + return (error); +} + +static moduledata_t mqueuefs_mod = { + "mqueuefs", + mq_modload, + &mqueuefs_vfsconf +}; +DECLARE_MODULE(mqueuefs, mqueuefs_mod, SI_SUB_VFS, SI_ORDER_MIDDLE); MODULE_VERSION(mqueuefs, 1); diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index f41b49c..a6b2f75 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -34,6 +34,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" #include "opt_posix.h" #include @@ -112,7 +113,7 @@ static struct ksem *ksem_alloc(struct ucred *ucred, mode_t mode, unsigned int value); static int ksem_create(struct thread *td, const char *path, semid_t *semidp, mode_t mode, unsigned int value, - int flags); + int flags, int compat32); static void ksem_drop(struct ksem *ks); static int ksem_get(struct thread *td, semid_t id, struct file **fpp); static struct ksem *ksem_hold(struct ksem *ks); @@ -374,16 +375,44 @@ ksem_remove(char *path, Fnv32_t fnv, struct ucred *ucred) return (ENOENT); } +static int +ksem_create_copyout_semid(struct thread *td, semid_t *semidp, int fd, + int compat32) +{ + semid_t semid; +#ifdef COMPAT_FREEBSD32 + int32_t semid32; +#endif + void *ptr; + size_t ptrs; + +#ifdef COMPAT_FREEBSD32 + if (compat32) { + semid32 = fd; + ptr = &semid32; + ptrs = sizeof(semid32); + } else { +#endif + semid = fd; + ptr = &semid; + ptrs = sizeof(semid); + compat32 = 0; /* silence gcc */ +#ifdef COMPAT_FREEBSD32 + } +#endif + + return (copyout(ptr, semidp, ptrs)); +} + /* Other helper routines. */ static int ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, - unsigned int value, int flags) + unsigned int value, int flags, int compat32) { struct filedesc *fdp; struct ksem *ks; struct file *fp; char *path; - semid_t semid; Fnv32_t fnv; int error, fd; @@ -404,8 +433,7 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, * premature, but it is a lot easier to handle errors as opposed * to later when we've possibly created a new semaphore, etc. */ - semid = fd; - error = copyout(&semid, semidp, sizeof(semid)); + error = ksem_create_copyout_semid(td, semidp, fd, compat32); if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); @@ -530,7 +558,7 @@ ksem_init(struct thread *td, struct ksem_init_args *uap) { return (ksem_create(td, NULL, uap->idp, S_IRWXU | S_IRWXG, uap->value, - 0)); + 0, 0)); } #ifndef _SYS_SYSPROTO_H_ @@ -551,7 +579,7 @@ ksem_open(struct thread *td, struct ksem_open_args *uap) if ((uap->oflag & ~(O_CREAT | O_EXCL)) != 0) return (EINVAL); return (ksem_create(td, uap->name, uap->idp, uap->mode, uap->value, - uap->oflag)); + uap->oflag, 0)); } #ifndef _SYS_SYSPROTO_H_ @@ -832,38 +860,85 @@ err: return (error); } -#define SYSCALL_DATA(syscallname) \ -static int syscallname##_syscall = SYS_##syscallname; \ -static int syscallname##_registered; \ -static struct sysent syscallname##_old_sysent; \ -MAKE_SYSENT(syscallname); - -#define SYSCALL_REGISTER(syscallname) do { \ - error = syscall_register(& syscallname##_syscall, \ - & syscallname##_sysent, & syscallname##_old_sysent); \ - if (error) \ - return (error); \ - syscallname##_registered = 1; \ -} while(0) - -#define SYSCALL_DEREGISTER(syscallname) do { \ - if (syscallname##_registered) { \ - syscallname##_registered = 0; \ - syscall_deregister(& syscallname##_syscall, \ - & syscallname##_old_sysent); \ - } \ -} while(0) - -SYSCALL_DATA(ksem_init); -SYSCALL_DATA(ksem_open); -SYSCALL_DATA(ksem_unlink); -SYSCALL_DATA(ksem_close); -SYSCALL_DATA(ksem_post); -SYSCALL_DATA(ksem_wait); -SYSCALL_DATA(ksem_timedwait); -SYSCALL_DATA(ksem_trywait); -SYSCALL_DATA(ksem_getvalue); -SYSCALL_DATA(ksem_destroy); +static struct syscall_helper_data ksem_syscalls[] = { + SYSCALL_INIT_HELPER(ksem_init), + SYSCALL_INIT_HELPER(ksem_open), + SYSCALL_INIT_HELPER(ksem_unlink), + SYSCALL_INIT_HELPER(ksem_close), + SYSCALL_INIT_HELPER(ksem_post), + SYSCALL_INIT_HELPER(ksem_wait), + SYSCALL_INIT_HELPER(ksem_timedwait), + SYSCALL_INIT_HELPER(ksem_trywait), + SYSCALL_INIT_HELPER(ksem_getvalue), + SYSCALL_INIT_HELPER(ksem_destroy), + SYSCALL_INIT_LAST +}; + +#ifdef COMPAT_FREEBSD32 +#include +#include +#include +#include +#include + +int +freebsd32_ksem_init(struct thread *td, struct freebsd32_ksem_init_args *uap) +{ + + return (ksem_create(td, NULL, uap->idp, S_IRWXU | S_IRWXG, uap->value, + 0, 1)); +} + +int +freebsd32_ksem_open(struct thread *td, struct freebsd32_ksem_open_args *uap) +{ + + if ((uap->oflag & ~(O_CREAT | O_EXCL)) != 0) + return (EINVAL); + return (ksem_create(td, uap->name, uap->idp, uap->mode, uap->value, + uap->oflag, 1)); +} + +int +freebsd32_ksem_timedwait(struct thread *td, + struct freebsd32_ksem_timedwait_args *uap) +{ + struct timespec32 abstime32; + struct timespec *ts, abstime; + int error; + + /* + * We allow a null timespec (wait forever). + */ + if (uap->abstime == NULL) + ts = NULL; + else { + error = copyin(uap->abstime, &abstime32, sizeof(abstime32)); + if (error != 0) + return (error); + CP(abstime32, abstime, tv_sec); + CP(abstime32, abstime, tv_nsec); + if (abstime.tv_nsec >= 1000000000 || abstime.tv_nsec < 0) + return (EINVAL); + ts = &abstime; + } + return (kern_sem_wait(td, uap->id, 0, ts)); +} + +static struct syscall_helper_data ksem32_syscalls[] = { + SYSCALL32_INIT_HELPER(freebsd32_ksem_init), + SYSCALL32_INIT_HELPER(freebsd32_ksem_open), + SYSCALL32_INIT_HELPER(ksem_unlink), + SYSCALL32_INIT_HELPER(ksem_close), + SYSCALL32_INIT_HELPER(ksem_post), + SYSCALL32_INIT_HELPER(ksem_wait), + SYSCALL32_INIT_HELPER(freebsd32_ksem_timedwait), + SYSCALL32_INIT_HELPER(ksem_trywait), + SYSCALL32_INIT_HELPER(ksem_getvalue), + SYSCALL32_INIT_HELPER(ksem_destroy), + SYSCALL_INIT_LAST +}; +#endif static int ksem_module_init(void) @@ -877,16 +952,14 @@ ksem_module_init(void) p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX); p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX); - SYSCALL_REGISTER(ksem_init); - SYSCALL_REGISTER(ksem_open); - SYSCALL_REGISTER(ksem_unlink); - SYSCALL_REGISTER(ksem_close); - SYSCALL_REGISTER(ksem_post); - SYSCALL_REGISTER(ksem_wait); - SYSCALL_REGISTER(ksem_timedwait); - SYSCALL_REGISTER(ksem_trywait); - SYSCALL_REGISTER(ksem_getvalue); - SYSCALL_REGISTER(ksem_destroy); + error = syscall_helper_register(ksem_syscalls); + if (error) + return (error); +#ifdef COMPAT_FREEBSD32 + error = syscall32_helper_register(ksem32_syscalls); + if (error) + return (error); +#endif return (0); } @@ -894,16 +967,10 @@ static void ksem_module_destroy(void) { - SYSCALL_DEREGISTER(ksem_init); - SYSCALL_DEREGISTER(ksem_open); - SYSCALL_DEREGISTER(ksem_unlink); - SYSCALL_DEREGISTER(ksem_close); - SYSCALL_DEREGISTER(ksem_post); - SYSCALL_DEREGISTER(ksem_wait); - SYSCALL_DEREGISTER(ksem_timedwait); - SYSCALL_DEREGISTER(ksem_trywait); - SYSCALL_DEREGISTER(ksem_getvalue); - SYSCALL_DEREGISTER(ksem_destroy); +#ifdef COMPAT_FREEBSD32 + syscall32_helper_unregister(ksem32_syscalls); +#endif + syscall_helper_unregister(ksem_syscalls); hashdestroy(ksem_dictionary, M_KSEM, ksem_hash); sx_destroy(&ksem_dict_lock); diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index c3e755b..a14be72 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -69,6 +70,9 @@ __FBSDID("$FreeBSD$"); #ifdef KTRACE #include #endif +#ifdef COMPAT_FREEBSD32 +#include +#endif #include @@ -2513,7 +2517,13 @@ sctp_generic_sendmsg_iov(td, uap) if (error) goto sctp_bad1; - error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE); +#ifdef COMPAT_FREEBSD32 + if (SV_CURPROC_FLAG(SV_ILP32)) + error = freebsd32_copyiniov((struct iovec32 *)uap->iov, + uap->iovlen, &iov, EMSGSIZE); + else +#endif + error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE); if (error) goto sctp_bad1; #ifdef KTRACE @@ -2528,7 +2538,7 @@ sctp_generic_sendmsg_iov(td, uap) goto sctp_bad; #endif /* MAC */ - auio.uio_iov = iov; + auio.uio_iov = iov; auio.uio_iovcnt = uap->iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_WRITE; @@ -2615,17 +2625,21 @@ sctp_generic_recvmsg(td, uap) if (error) { return (error); } - error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE); - if (error) { +#ifdef COMPAT_FREEBSD32 + if (SV_CURPROC_FLAG(SV_ILP32)) + error = freebsd32_copyiniov((struct iovec32 *)uap->iov, + uap->iovlen, &iov, EMSGSIZE); + else +#endif + error = copyiniov(uap->iov, uap->iovlen, &iov, EMSGSIZE); + if (error) goto out1; - } so = fp->f_data; #ifdef MAC error = mac_socket_check_receive(td->td_ucred, so); if (error) { goto out; - return (error); } #endif /* MAC */ @@ -2638,7 +2652,7 @@ sctp_generic_recvmsg(td, uap) } else { fromlen = 0; } - if(uap->msg_flags) { + if (uap->msg_flags) { error = copyin(uap->msg_flags, &msg_flags, sizeof (int)); if (error) { goto out; diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index 25328d6..e05106a 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -334,7 +334,7 @@ static TAILQ_HEAD(,aiocblist) aio_jobs; /* (c) Async job list */ static struct unrhdr *aiod_unr; void aio_init_aioinfo(struct proc *p); -static void aio_onceonly(void); +static int aio_onceonly(void); static int aio_free_entry(struct aiocblist *aiocbe); static void aio_process(struct aiocblist *aiocbe); static int aio_newproc(int *); @@ -419,18 +419,47 @@ static moduledata_t aio_mod = { NULL }; -SYSCALL_MODULE_HELPER(aio_cancel); -SYSCALL_MODULE_HELPER(aio_error); -SYSCALL_MODULE_HELPER(aio_fsync); -SYSCALL_MODULE_HELPER(aio_read); -SYSCALL_MODULE_HELPER(aio_return); -SYSCALL_MODULE_HELPER(aio_suspend); -SYSCALL_MODULE_HELPER(aio_waitcomplete); -SYSCALL_MODULE_HELPER(aio_write); -SYSCALL_MODULE_HELPER(lio_listio); -SYSCALL_MODULE_HELPER(oaio_read); -SYSCALL_MODULE_HELPER(oaio_write); -SYSCALL_MODULE_HELPER(olio_listio); +static struct syscall_helper_data aio_syscalls[] = { + SYSCALL_INIT_HELPER(aio_cancel), + SYSCALL_INIT_HELPER(aio_error), + SYSCALL_INIT_HELPER(aio_fsync), + SYSCALL_INIT_HELPER(aio_read), + SYSCALL_INIT_HELPER(aio_return), + SYSCALL_INIT_HELPER(aio_suspend), + SYSCALL_INIT_HELPER(aio_waitcomplete), + SYSCALL_INIT_HELPER(aio_write), + SYSCALL_INIT_HELPER(lio_listio), + SYSCALL_INIT_HELPER(oaio_read), + SYSCALL_INIT_HELPER(oaio_write), + SYSCALL_INIT_HELPER(olio_listio), + SYSCALL_INIT_LAST +}; + +#ifdef COMPAT_FREEBSD32 +#include +#include +#include +#include +#include +#include +#include + +static struct syscall_helper_data aio32_syscalls[] = { + SYSCALL32_INIT_HELPER(freebsd32_aio_return), + SYSCALL32_INIT_HELPER(freebsd32_aio_suspend), + SYSCALL32_INIT_HELPER(freebsd32_aio_cancel), + SYSCALL32_INIT_HELPER(freebsd32_aio_error), + SYSCALL32_INIT_HELPER(freebsd32_aio_fsync), + SYSCALL32_INIT_HELPER(freebsd32_aio_read), + SYSCALL32_INIT_HELPER(freebsd32_aio_write), + SYSCALL32_INIT_HELPER(freebsd32_aio_waitcomplete), + SYSCALL32_INIT_HELPER(freebsd32_lio_listio), + SYSCALL32_INIT_HELPER(freebsd32_oaio_read), + SYSCALL32_INIT_HELPER(freebsd32_oaio_write), + SYSCALL32_INIT_HELPER(freebsd32_olio_listio), + SYSCALL_INIT_LAST +}; +#endif DECLARE_MODULE(aio, aio_mod, SI_SUB_VFS, SI_ORDER_ANY); @@ -439,9 +468,10 @@ MODULE_VERSION(aio, 1); /* * Startup initialization */ -static void +static int aio_onceonly(void) { + int error; /* XXX: should probably just use so->callback */ aio_swake = &aio_swake_cb; @@ -474,6 +504,16 @@ aio_onceonly(void) p31b_setcfg(CTL_P1003_1B_AIO_LISTIO_MAX, AIO_LISTIO_MAX); p31b_setcfg(CTL_P1003_1B_AIO_MAX, MAX_AIO_QUEUE); p31b_setcfg(CTL_P1003_1B_AIO_PRIO_DELTA_MAX, 0); + + error = syscall_helper_register(aio_syscalls); + if (error) + return (error); +#ifdef COMPAT_FREEBSD32 + error = syscall32_helper_register(aio32_syscalls); + if (error) + return (error); +#endif + return (0); } /* @@ -495,6 +535,11 @@ aio_unload(void) if (!unloadable) return (EOPNOTSUPP); +#ifdef COMPAT_FREEBSD32 + syscall32_helper_unregister(aio32_syscalls); +#endif + syscall_helper_unregister(aio_syscalls); + error = kqueue_del_filteropts(EVFILT_AIO); if (error) return error; @@ -2533,13 +2578,6 @@ filt_lio(struct knote *kn, long hint) } #ifdef COMPAT_FREEBSD32 -#include -#include -#include -#include -#include -#include -#include struct __aiocb_private32 { int32_t status; @@ -2948,16 +2986,4 @@ freebsd32_lio_listio(struct thread *td, struct freebsd32_lio_listio_args *uap) return (error); } -SYSCALL32_MODULE_HELPER(freebsd32_aio_return); -SYSCALL32_MODULE_HELPER(freebsd32_aio_suspend); -SYSCALL32_MODULE_HELPER(freebsd32_aio_cancel); -SYSCALL32_MODULE_HELPER(freebsd32_aio_error); -SYSCALL32_MODULE_HELPER(freebsd32_aio_fsync); -SYSCALL32_MODULE_HELPER(freebsd32_aio_read); -SYSCALL32_MODULE_HELPER(freebsd32_aio_write); -SYSCALL32_MODULE_HELPER(freebsd32_aio_waitcomplete); -SYSCALL32_MODULE_HELPER(freebsd32_lio_listio); -SYSCALL32_MODULE_HELPER(freebsd32_oaio_read); -SYSCALL32_MODULE_HELPER(freebsd32_oaio_write); -SYSCALL32_MODULE_HELPER(freebsd32_olio_listio); #endif diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index a7a2907..707c00b 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -149,7 +149,7 @@ static struct syscall_module_data name##_syscall_mod = { \ }; \ \ static moduledata_t name##_mod = { \ - #name, \ + "sys/" #name, \ syscall_module_handler, \ &name##_syscall_mod \ }; \ @@ -166,10 +166,34 @@ SYSCALL_MODULE(syscallname, \ (sysent[SYS_##syscallname].sy_call != (sy_call_t *)lkmnosys && \ sysent[SYS_##syscallname].sy_call != (sy_call_t *)lkmressys) +/* + * Syscall registration helpers with resource allocation handling. + */ +struct syscall_helper_data { + struct sysent new_sysent; + struct sysent old_sysent; + int syscall_no; + int registered; +}; +#define SYSCALL_INIT_HELPER(syscallname) { \ + .new_sysent = { \ + .sy_narg = (sizeof(struct syscallname ## _args ) \ + / sizeof(register_t)), \ + .sy_call = (sy_call_t *)& syscallname, \ + .sy_auevent = SYS_AUE_##syscallname \ + }, \ + .syscall_no = SYS_##syscallname \ +} +#define SYSCALL_INIT_LAST { \ + .syscall_no = NO_SYSCALL \ +} + int syscall_register(int *offset, struct sysent *new_sysent, struct sysent *old_sysent); int syscall_deregister(int *offset, struct sysent *old_sysent); int syscall_module_handler(struct module *mod, int what, void *arg); +int syscall_helper_register(struct syscall_helper_data *sd); +int syscall_helper_unregister(struct syscall_helper_data *sd); /* Special purpose system call functions. */ struct nosys_args;