Skip to content

Commit

Permalink
[X25]: ioctl conversion 32 bit user to 64 bit kernel
Browse files Browse the repository at this point in the history
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: Shaun Pereira <spereira@tusc.com.au>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Shaun Pereira authored and David S. Miller committed Mar 22, 2006
1 parent f0ac261 commit 1b06e6b
Showing 1 changed file with 124 additions and 0 deletions.
124 changes: 124 additions & 0 deletions net/x25/af_x25.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down

0 comments on commit 1b06e6b

Please sign in to comment.