Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b06e6ba authored by Shaun Pereira's avatar Shaun Pereira Committed by David S. Miller
Browse files

[X25]: ioctl conversion 32 bit user to 64 bit kernel



To allow 32 bit x25 module structures to be passed to a 64 bit kernel via
ioctl using the new compat_sock_ioctl registration mechanism instead of the
obsolete 'register_ioctl32_conversion into hash table' mechanism

Signed-off-by: default avatarShaun Pereira <spereira@tusc.com.au>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f0ac2614
Loading
Loading
Loading
Loading
+124 −0
Original line number Diff line number Diff line
@@ -54,7 +54,10 @@
#include <linux/termios.h>	/* For TIOCINQ/OUTQ */
#include <linux/notifier.h>
#include <linux/init.h>
#include <linux/compat.h>

#include <net/x25.h>
#include <net/compat.h>

int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
int sysctl_x25_call_request_timeout    = X25_DEFAULT_T21;
@@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops;

static struct x25_address null_x25_address = {"               "};

#ifdef CONFIG_COMPAT
struct compat_x25_subscrip_struct {
	char device[200-sizeof(compat_ulong_t)];
	compat_ulong_t global_facil_mask;
	compat_uint_t extended;
};
#endif

int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
		  struct x25_address *calling_addr)
{
@@ -1387,6 +1398,116 @@ static struct net_proto_family x25_family_ops = {
	.owner	=	THIS_MODULE,
};

#ifdef CONFIG_COMPAT
static int compat_x25_subscr_ioctl(unsigned int cmd,
		struct compat_x25_subscrip_struct __user *x25_subscr32)
{
	struct compat_x25_subscrip_struct x25_subscr;
	struct x25_neigh *nb;
	struct net_device *dev;
	int rc = -EINVAL;

	rc = -EFAULT;
	if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32)))
		goto out;

	rc = -EINVAL;
	dev = x25_dev_get(x25_subscr.device);
	if (dev == NULL)
		goto out;

	nb = x25_get_neigh(dev);
	if (nb == NULL)
		goto out_dev_put;

	dev_put(dev);

	if (cmd == SIOCX25GSUBSCRIP) {
		x25_subscr.extended = nb->extended;
		x25_subscr.global_facil_mask = nb->global_facil_mask;
		rc = copy_to_user(x25_subscr32, &x25_subscr,
				sizeof(*x25_subscr32)) ? -EFAULT : 0;
	} else {
		rc = -EINVAL;
		if (x25_subscr.extended == 0 || x25_subscr.extended == 1) {
			rc = 0;
			nb->extended = x25_subscr.extended;
			nb->global_facil_mask = x25_subscr.global_facil_mask;
		}
	}
	x25_neigh_put(nb);
out:
	return rc;
out_dev_put:
	dev_put(dev);
	goto out;
}

static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
				unsigned long arg)
{
	void __user *argp = compat_ptr(arg);
	struct sock *sk = sock->sk;

	int rc = -ENOIOCTLCMD;

	switch(cmd) {
	case TIOCOUTQ:
	case TIOCINQ:
		rc = x25_ioctl(sock, cmd, (unsigned long)argp);
		break;
	case SIOCGSTAMP:
		rc = -EINVAL;
		if (sk)
			rc = compat_sock_get_timestamp(sk,
					(struct timeval __user*)argp);
		break;
	case SIOCGIFADDR:
	case SIOCSIFADDR:
	case SIOCGIFDSTADDR:
	case SIOCSIFDSTADDR:
	case SIOCGIFBRDADDR:
	case SIOCSIFBRDADDR:
	case SIOCGIFNETMASK:
	case SIOCSIFNETMASK:
	case SIOCGIFMETRIC:
	case SIOCSIFMETRIC:
		rc = -EINVAL;
		break;
	case SIOCADDRT:
	case SIOCDELRT:
		rc = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			break;
		rc = x25_route_ioctl(cmd, argp);
		break;
	case SIOCX25GSUBSCRIP:
		rc = compat_x25_subscr_ioctl(cmd, argp);
		break;
	case SIOCX25SSUBSCRIP:
		rc = -EPERM;
		if (!capable(CAP_NET_ADMIN))
			break;
		rc = compat_x25_subscr_ioctl(cmd, argp);
		break;
	case SIOCX25GFACILITIES:
	case SIOCX25SFACILITIES:
	case SIOCX25GCALLUSERDATA:
	case SIOCX25SCALLUSERDATA:
	case SIOCX25GCAUSEDIAG:
	case SIOCX25SCUDMATCHLEN:
	case SIOCX25CALLACCPTAPPRV:
	case SIOCX25SENDCALLACCPT:
		rc = x25_ioctl(sock, cmd, (unsigned long)argp);
		break;
	default:
		rc = -ENOIOCTLCMD;
		break;
	}
	return rc;
}
#endif

static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
	.family =	AF_X25,
	.owner =	THIS_MODULE,
@@ -1398,6 +1519,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
	.getname =	x25_getname,
	.poll =		datagram_poll,
	.ioctl =	x25_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl = compat_x25_ioctl,
#endif
	.listen =	x25_listen,
	.shutdown =	sock_no_shutdown,
	.setsockopt =	x25_setsockopt,