Example #1
0
static int
svr4_semop(int arg1, struct sembuf *arg2, int arg3)
{
int retval;
#if defined(CONFIG_ABI_TRACE)
	if (abi_traced(ABI_TRACE_API)) {
		struct sembuf	tmp, *tp = arg2;
		int		i;

		for (i = 0; i < arg3; i++) {
			if (copy_from_user (&tmp, tp, sizeof(tmp)))
			{	__abi_trace("semop(-EFAULT)\n");
				break;
			}
			__abi_trace("semop(%d, %d, 0%o)\n",
					tmp.sem_num, tmp.sem_op,
					tmp.sem_flg);
			tp++;
		}
	}
#endif

#ifdef CONFIG_65BIT
	retval=SYS(semop, arg1, arg2, arg3);
#else
	retval=SYS(ipc,SEMOP,arg1,arg3,0,arg2);
#endif
	return retval;
}
Example #2
0
int
abi_do_setsockopt(unsigned long *sp)
{
	int error;
	int level, optname;

	error = verify_area(VERIFY_READ,
			((unsigned long *)sp),
			5*sizeof(long));
	if (error)
		return error;

	get_user(level, ((unsigned long *)sp)+1);
	get_user(optname, ((unsigned long *)sp)+2);

	if (abi_traced(ABI_TRACE_STREAMS|ABI_TRACE_SOCKSYS)) {
		u_long optval, optlen;

		get_user(optval, ((u_long *)sp) + 3);
		get_user(optlen, ((u_long *)sp) + 4);
		__abi_trace("setsockopt level=%d, optname=%d, "
				"optval=0x%08lx, optlen=0x%08lx\n",
				level, optname, optval, optlen);
	}

	switch (level) {
		case 0: /* IPPROTO_IP aka SOL_IP */
			/* This is correct for the SCO family. Hopefully
			 * it is correct for other SYSV...
			 */
			optname--;
			if (optname == 0)
				optname = 4;
			if (optname > 4) {
				optname += 24;
				if (optname <= 33)
					optname--;
				if (optname < 32 || optname > 36)
					return -EINVAL;
			}
			put_user(optname, ((unsigned long *)sp)+2);
			break;

		case 0xffff:
			put_user(SOL_SOCKET, ((unsigned long *)sp)+1);
			optname = map_value(current->exec_domain->sockopt_map, optname, 0);
			put_user(optname, ((unsigned long *)sp)+2);

			switch (optname) {
				case SO_LINGER: {
					unsigned long optlen;

					/* SO_LINGER takes a struct linger
					 * as the argument but some code
					 * uses an int and expects to get
					 * away without an error. Sigh...
					 */
					get_user(optlen, ((unsigned long *)sp)+4);
					if (optlen == sizeof(int))
						return 0;
					break;
				}

				/* The following are not currently implemented
				 * under Linux so we must fake them in
				 * reasonable ways. (Only SO_PROTOTYPE is
				 * documented in SCO's man page).
				 */
				case SO_PROTOTYPE:
				case SO_ORDREL:
				case SO_SNDTIMEO:
				case SO_RCVTIMEO:
					return -ENOPROTOOPT;

				case SO_USELOOPBACK:
				case SO_SNDLOWAT:
				case SO_RCVLOWAT:
					return 0;

				/* The following are not currenty implemented
				 * under Linux and probably aren't settable
				 * anyway.
				 */
				case SO_IMASOCKET:
					return -ENOPROTOOPT;
			}

		default:
			/* FIXME: We assume everything else uses the
			 * same level and option numbers. This is true
			 * for IPPROTO_TCP(/SOL_TCP) and TCP_NDELAY
			 * but is known to be incorrect for other
			 * potential options :-(.
			 */
			break;
	}

	return sys_socketcall(SYS_SETSOCKOPT, sp);
}
Example #3
0
/*
 * XXX: this function is a _horrible_ mess.
 */
static int
timod_optmgmt(int fd, struct pt_regs * regs, int flag,
	      char * opt_buf, int opt_len, int do_ret)
{
	struct file * fp = fcheck(fd);
	char *ret_buf, *ret_base;
	u_int old_esp, *tsp;
	int is_tli, error, failed;
	int ret_len, ret_space;
error=0;
	if (opt_buf && opt_len > 0) {
		if (!access_ok(VERIFY_READ, opt_buf, opt_len))
			return -EFAULT;
	}

	/*
	 * FIXME:
	 *   We should be able to detect the difference between
	 *   TLI and XTI requests at run time?
	 */
#ifdef CONFIG_ABI_TLI_OPTMGMT
	is_tli = 1;
#else
	is_tli = 0;
#endif

	if (!do_ret && (!opt_buf || opt_len <= 0))
		return 0;

	/*
	 * Grab some space on the user stack to work with. We need 6 longs
	 * to build an argument frame for [gs]etsockopt calls. We also
	 * need space to build the return buffer. This will be at least
	 * as big as the given options buffer but the given options
	 * buffer may not include space for option values so we allow two
	 * longs for each option multiple of the option header size
	 * and hope that big options will not exhaust our space and
	 * trash the stack.
	 */
	ret_space = 1024 + opt_len
		+ 2*sizeof(long)*(opt_len / (is_tli ? sizeof(struct opthdr) : sizeof(struct t_opthdr)));
	ret_buf = ret_base = (char *)(_SP(regs) - ret_space);
	ret_len = 0;

	old_esp = _SP(regs);
	_SP(regs) -= ret_space + 6*sizeof(long);
	tsp = (unsigned int *)_SP(regs);
	if (!access_ok(VERIFY_WRITE, tsp, 6*sizeof(long))) {
		_SP(regs) = old_esp;
		return -EFAULT;
	}

	failed = 0;

#ifndef CONFIG_ABI_TLI_OPTMGMT
	if (is_tli) {
		printk(KERN_WARNING
			"%d iBCS: TLI optmgmt requested but not supported\n",
			current->pid);
	}
#else
	if (is_tli)
		while (opt_len >= sizeof(struct opthdr)) {
		struct opthdr opt;

#if defined(CONFIG_ABI_TRACE)
		abi_trace(ABI_TRACE_STREAMS, "TLI optmgmt opt_len=%d, "
				"ret_buf=0x%08lx, ret_len=%d, ret_space=%d\n",
				opt_len, (unsigned long)ret_buf,
				ret_len, ret_space);
#endif

		if (copy_from_user(&opt, opt_buf, sizeof(struct opthdr)))
			return -EFAULT;

		/* Idiot check... */
		if (opt.len > opt_len) {
			failed = TBADOPT;
			break;
		}

#if defined(CONFIG_ABI_TRACE)
		if (abi_traced(ABI_TRACE_STREAMS)) {
			unsigned long v;
			get_user(v, (unsigned long *)(opt_buf+sizeof(struct opthdr)));
			__abi_trace("TLI optmgmt fd=%d, level=%ld, "
					"name=%ld, value=%ld\n",
					fd, opt.level, opt.name, v);
		}
#endif
		/* Check writable space in the return buffer. */
		if (!access_ok(VERIFY_WRITE, ret_buf, sizeof(struct opthdr))) {
			failed = TSYSERR;
			break;
		}

		/* Flag values:
		 * T_NEGOTIATE means try and set it.
		 * T_DEFAULT means get the default value.
		 *           (return the current for now)
		 * T_CHECK means get the current value.
		 */
		error = 0;
		if (flag == T_NEGOTIATE) {
			put_user(fd, tsp);
			put_user(opt.level, tsp+1);
			put_user(opt.name, tsp+2);
			put_user((long)opt_buf+sizeof(struct opthdr), tsp+3);
			put_user(opt.len, tsp+4);
			error = abi_do_setsockopt(tsp);

			if (error) {
#if defined(CONFIG_ABI_TRACE)
				abi_trace(ABI_TRACE_STREAMS,
					"setsockopt failed: %d\n", error);
#endif
				failed = TBADOPT;
				break;
			}
		}
		if (!error) {
			int len;

			put_user(fd, tsp);
			put_user(opt.level, tsp+1);
			put_user(opt.name, tsp+2);
			put_user((long)ret_buf+sizeof(struct opthdr), tsp+3);
			put_user((long)(tsp+5), tsp+4);
			put_user(ret_space, tsp+5);
			error = abi_do_getsockopt(tsp);

			if (error) {
#if defined(CONFIG_ABI_TRACE)
				abi_trace(ABI_TRACE_STREAMS,
					"getsockopt failed: %d\n", error);
#endif
				failed = TBADOPT;
				break;
			}

			get_user(len, tsp+5);
			if (copy_to_user(ret_buf, &opt, sizeof(opt)))
				return -EFAULT;
			put_user(len,
				&((struct opthdr *)opt_buf)->len);
			ret_space -= sizeof(struct opthdr) + len;
			ret_len += sizeof(struct opthdr) + len;
			ret_buf += sizeof(struct opthdr) + len;
		}

		opt_len -= sizeof(struct opthdr) + opt.len;
		opt_buf += sizeof(struct opthdr) + opt.len;
	}
#endif /* CONFIG_ABI_TLI_OPTMGMT */
#ifndef CONFIG_ABI_XTI_OPTMGMT
	else {
		printk(KERN_WARNING
			"%d iBCS: XTI optmgmt requested but not supported\n",
			current->pid);
	}
#else
	else while (opt_len >= sizeof(struct t_opthdr)) {