mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
[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: 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>
This commit is contained in:
parent
f0ac261441
commit
1b06e6ba25
124
net/x25/af_x25.c
124
net/x25/af_x25.c
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user