static int __abi4_semctl(int first, int second, int third, union semun *fourth) { struct abi4_semid_ds is, *isp; struct semid_ds ls; union semun lsemun; mm_segment_t fs; int err; err = get_user(isp, (struct abi4_semid_ds **)&fourth->buf); if (err) return (err); err = copy_from_user(&is, isp, sizeof(is)) ? -EFAULT : 0; if (err) return (err); isem_to_lsem_l(&is, &ls); lsemun.buf = &ls; fs = get_fs(); set_fs(get_ds()); #ifdef CONFIG_65BIT err = SYS(semctl, first, second, third, &lsemun,0); #else err = SYS(ipc,SEMCTL, first, second, third, &lsemun,0); #endif set_fs(fs); if (err < 0) return (err); lsem_to_isem_l(&ls, &is); return copy_to_user(isp, &is, sizeof(is)) ? -EFAULT : 0; }
int svr4_semsys(struct pt_regs *regs) { int command = get_syscall_parameter (regs, 0); int arg1, arg2, arg3; union semun *arg4; struct semid_ds ls; union semun lsemun; mm_segment_t old_fs; int retval; arg1 = get_syscall_parameter (regs, 1); arg2 = get_syscall_parameter (regs, 2); arg3 = get_syscall_parameter (regs, 3); switch (command) { case U_SEMCTL: /* XXX - The value for arg4 depends on how union * passing is implement on this architecture and * compiler. The following is *only* known to be * right for Intel (the default else case). */ #ifdef __sparc__ arg4 = (union semun *)get_syscall_parameter (regs, 4); #else arg4 = (union semun *)(((unsigned long *) regs->esp) + (5)); #endif #ifdef CONFIG_ABI_TRACE if ((ibcs_trace & TRACE_API) || ibcs_func_p->trace) printk(KERN_DEBUG "%d iBCS: ibcs_semctl: args: %d %d %d %lx\n", current->pid, arg1, arg2, arg3, (unsigned long)arg4); #endif switch (arg3) { case U_IPC_SET: { struct ibcs_semid_ds is, *is_p; retval = get_user(is_p, (struct ibcs_semid_ds **)&arg4->buf); if (!retval) retval = verify_area(VERIFY_WRITE, is_p, sizeof(is)); if (retval) return retval; copy_from_user(&is, (char *)is_p, sizeof(is)); isem_to_lsem(&is, &ls); lsemun.buf = &ls; old_fs = get_fs(); set_fs (get_ds()); retval = SYS (ipc) (SEMCTL, arg1, arg2, IPC_SET, &lsemun); set_fs(old_fs); lsem_to_isem(&ls, &is); copy_to_user((char *)is_p, &is, sizeof(is)); return retval; } case U_IPC_SET_L: { struct ibcs_semid_ds_l is, *is_p; retval = get_user(is_p, (struct ibcs_semid_ds_l **)&arg4->buf); if (!retval) retval = verify_area(VERIFY_WRITE, is_p, sizeof(is)); if (retval) return retval; copy_from_user(&is, (char *)is_p, sizeof(is)); isem_to_lsem_l(&is, &ls); lsemun.buf = &ls; old_fs = get_fs(); set_fs (get_ds()); retval = SYS (ipc) (SEMCTL, arg1, arg2, IPC_SET, &lsemun); set_fs(old_fs); lsem_to_isem_l(&ls, &is); copy_to_user((char *)is_p, &is, sizeof(is)); return retval; } case U_IPC_RMID: case U_IPC_RMID_L: case U_SETVAL: case U_GETVAL: case U_GETPID: case U_GETNCNT: case U_GETZCNT: { int cmd = ibcs_sem_trans(arg3); return SYS (ipc) (SEMCTL, arg1, arg2, cmd, arg4); } case U_SETALL: case U_GETALL: { int cmd = ibcs_sem_trans(arg3); return SYS (ipc) (SEMCTL, arg1, 0, cmd, arg4); } case U_IPC_STAT: { struct ibcs_semid_ds is, *is_p; retval = get_user(is_p, (struct ibcs_semid_ds **)&arg4->buf); if (!retval) retval = verify_area(VERIFY_WRITE, (char *)is_p, sizeof(is)); if (retval) return retval; lsemun.buf = &ls; old_fs = get_fs(); set_fs(get_ds()); retval = SYS (ipc) (SEMCTL, arg1, 0, IPC_STAT, &lsemun); set_fs(old_fs); if (retval < 0) return retval; lsem_to_isem(&ls, &is); copy_to_user((char *)is_p, &is, sizeof(is)); return retval; } case U_IPC_STAT_L: { struct ibcs_semid_ds_l is, *is_p; retval = get_user(is_p, (struct ibcs_semid_ds_l **)&arg4->buf); if (!retval) retval = verify_area(VERIFY_WRITE, (char *)is_p, sizeof(is)); if (retval) return retval; lsemun.buf = &ls; old_fs = get_fs(); set_fs(get_ds()); retval = SYS (ipc) (SEMCTL, arg1, 0, IPC_STAT, &lsemun); set_fs(old_fs); if (retval < 0) return retval; lsem_to_isem_l(&ls, &is); copy_to_user((char *)is_p, &is, sizeof(is)); return retval; } default: printk(KERN_ERR "%d ibcs_semctl: unsupported command %d\n", current->pid, arg3); return -EINVAL; } case U_SEMGET: #ifdef CONFIG_ABI_TRACE if ((ibcs_trace & TRACE_API) || ibcs_func_p->trace) printk(KERN_DEBUG "%d iBCS: ibcs_semget: args: %d %d %o \n", current->pid, arg1, arg2, arg3); #endif return SYS (ipc) (SEMGET, arg1, arg2, arg3, 0); case U_SEMOP: #ifdef CONFIG_ABI_TRACE if ((ibcs_trace & TRACE_API) || ibcs_func_p->trace) { int x; struct sembuf tmp; struct sembuf *tp = (struct sembuf *) arg2; printk(KERN_DEBUG "%d iBCS: ibcs_semop: args: %d 0x%08lx %d\n", current->pid, arg1, (unsigned long)arg2, arg3); for (x = 0; x < arg3; x++) { copy_from_user (&tmp, tp, sizeof (tmp)); printk(KERN_DEBUG "%d iBCS: ibcs_semop args: %d %d 0%o \n", current->pid, tmp.sem_num, tmp.sem_op, tmp.sem_flg); tp++; } } #endif return SYS (ipc) (SEMOP, arg1, arg3, 0, (struct sembuf *) arg2); } return -EINVAL; }