예제 #1
0
static int
__ibcs2_semctl(int first, int second, int third, union semun *fourth)
{
	struct ibcs2_semid_ds	is, *isp;
	struct semid_ds		ls;
	union semun		lsemun;
	mm_segment_t		fs;
	int			err;

	err = get_user(isp, (struct ibcs2_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(&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(&ls, &is);
	return copy_to_user(isp, &is, sizeof(is)) ? -EFAULT : 0;
}
예제 #2
0
파일: ipc.c 프로젝트: cpc26/abi_linux
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;
}