diff options
| author | Shaun Pereira <spereira@tusc.com.au> | 2006-03-22 03:00:12 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2006-03-22 03:00:12 -0500 |
| commit | 1b06e6ba25a37fe1c289049d0e0300d71ae39eff (patch) | |
| tree | e119b3bf47125cb1b5a32fab531815890202d334 | |
| parent | f0ac2614412e2b597e2d5bfbd3960b4f73718b41 (diff) | |
[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>
| -rw-r--r-- | net/x25/af_x25.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 72b6ff3299ba..a41cc0201760 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -54,7 +54,10 @@ | |||
| 54 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ | 54 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ |
| 55 | #include <linux/notifier.h> | 55 | #include <linux/notifier.h> |
| 56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
| 57 | #include <linux/compat.h> | ||
| 58 | |||
| 57 | #include <net/x25.h> | 59 | #include <net/x25.h> |
| 60 | #include <net/compat.h> | ||
| 58 | 61 | ||
| 59 | int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; | 62 | int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; |
| 60 | int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; | 63 | int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; |
| @@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops; | |||
| 69 | 72 | ||
| 70 | static struct x25_address null_x25_address = {" "}; | 73 | static struct x25_address null_x25_address = {" "}; |
| 71 | 74 | ||
| 75 | #ifdef CONFIG_COMPAT | ||
| 76 | struct compat_x25_subscrip_struct { | ||
| 77 | char device[200-sizeof(compat_ulong_t)]; | ||
| 78 | compat_ulong_t global_facil_mask; | ||
| 79 | compat_uint_t extended; | ||
| 80 | }; | ||
| 81 | #endif | ||
| 82 | |||
| 72 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, | 83 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, |
| 73 | struct x25_address *calling_addr) | 84 | struct x25_address *calling_addr) |
| 74 | { | 85 | { |
| @@ -1387,6 +1398,116 @@ static struct net_proto_family x25_family_ops = { | |||
| 1387 | .owner = THIS_MODULE, | 1398 | .owner = THIS_MODULE, |
| 1388 | }; | 1399 | }; |
| 1389 | 1400 | ||
| 1401 | #ifdef CONFIG_COMPAT | ||
| 1402 | static int compat_x25_subscr_ioctl(unsigned int cmd, | ||
| 1403 | struct compat_x25_subscrip_struct __user *x25_subscr32) | ||
| 1404 | { | ||
| 1405 | struct compat_x25_subscrip_struct x25_subscr; | ||
| 1406 | struct x25_neigh *nb; | ||
| 1407 | struct net_device *dev; | ||
| 1408 | int rc = -EINVAL; | ||
| 1409 | |||
| 1410 | rc = -EFAULT; | ||
| 1411 | if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32))) | ||
| 1412 | goto out; | ||
| 1413 | |||
| 1414 | rc = -EINVAL; | ||
| 1415 | dev = x25_dev_get(x25_subscr.device); | ||
| 1416 | if (dev == NULL) | ||
| 1417 | goto out; | ||
| 1418 | |||
| 1419 | nb = x25_get_neigh(dev); | ||
| 1420 | if (nb == NULL) | ||
| 1421 | goto out_dev_put; | ||
| 1422 | |||
| 1423 | dev_put(dev); | ||
| 1424 | |||
| 1425 | if (cmd == SIOCX25GSUBSCRIP) { | ||
| 1426 | x25_subscr.extended = nb->extended; | ||
| 1427 | x25_subscr.global_facil_mask = nb->global_facil_mask; | ||
| 1428 | rc = copy_to_user(x25_subscr32, &x25_subscr, | ||
| 1429 | sizeof(*x25_subscr32)) ? -EFAULT : 0; | ||
| 1430 | } else { | ||
| 1431 | rc = -EINVAL; | ||
| 1432 | if (x25_subscr.extended == 0 || x25_subscr.extended == 1) { | ||
| 1433 | rc = 0; | ||
| 1434 | nb->extended = x25_subscr.extended; | ||
| 1435 | nb->global_facil_mask = x25_subscr.global_facil_mask; | ||
| 1436 | } | ||
| 1437 | } | ||
| 1438 | x25_neigh_put(nb); | ||
| 1439 | out: | ||
| 1440 | return rc; | ||
| 1441 | out_dev_put: | ||
| 1442 | dev_put(dev); | ||
| 1443 | goto out; | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | ||
| 1447 | unsigned long arg) | ||
| 1448 | { | ||
| 1449 | void __user *argp = compat_ptr(arg); | ||
| 1450 | struct sock *sk = sock->sk; | ||
| 1451 | |||
| 1452 | int rc = -ENOIOCTLCMD; | ||
| 1453 | |||
| 1454 | switch(cmd) { | ||
| 1455 | case TIOCOUTQ: | ||
| 1456 | case TIOCINQ: | ||
| 1457 | rc = x25_ioctl(sock, cmd, (unsigned long)argp); | ||
| 1458 | break; | ||
| 1459 | case SIOCGSTAMP: | ||
| 1460 | rc = -EINVAL; | ||
| 1461 | if (sk) | ||
| 1462 | rc = compat_sock_get_timestamp(sk, | ||
| 1463 | (struct timeval __user*)argp); | ||
| 1464 | break; | ||
| 1465 | case SIOCGIFADDR: | ||
| 1466 | case SIOCSIFADDR: | ||
| 1467 | case SIOCGIFDSTADDR: | ||
| 1468 | case SIOCSIFDSTADDR: | ||
| 1469 | case SIOCGIFBRDADDR: | ||
| 1470 | case SIOCSIFBRDADDR: | ||
| 1471 | case SIOCGIFNETMASK: | ||
| 1472 | case SIOCSIFNETMASK: | ||
| 1473 | case SIOCGIFMETRIC: | ||
| 1474 | case SIOCSIFMETRIC: | ||
| 1475 | rc = -EINVAL; | ||
| 1476 | break; | ||
| 1477 | case SIOCADDRT: | ||
| 1478 | case SIOCDELRT: | ||
| 1479 | rc = -EPERM; | ||
| 1480 | if (!capable(CAP_NET_ADMIN)) | ||
| 1481 | break; | ||
| 1482 | rc = x25_route_ioctl(cmd, argp); | ||
| 1483 | break; | ||
| 1484 | case SIOCX25GSUBSCRIP: | ||
| 1485 | rc = compat_x25_subscr_ioctl(cmd, argp); | ||
| 1486 | break; | ||
| 1487 | case SIOCX25SSUBSCRIP: | ||
| 1488 | rc = -EPERM; | ||
| 1489 | if (!capable(CAP_NET_ADMIN)) | ||
| 1490 | break; | ||
| 1491 | rc = compat_x25_subscr_ioctl(cmd, argp); | ||
| 1492 | break; | ||
| 1493 | case SIOCX25GFACILITIES: | ||
| 1494 | case SIOCX25SFACILITIES: | ||
| 1495 | case SIOCX25GCALLUSERDATA: | ||
| 1496 | case SIOCX25SCALLUSERDATA: | ||
| 1497 | case SIOCX25GCAUSEDIAG: | ||
| 1498 | case SIOCX25SCUDMATCHLEN: | ||
| 1499 | case SIOCX25CALLACCPTAPPRV: | ||
| 1500 | case SIOCX25SENDCALLACCPT: | ||
| 1501 | rc = x25_ioctl(sock, cmd, (unsigned long)argp); | ||
| 1502 | break; | ||
| 1503 | default: | ||
| 1504 | rc = -ENOIOCTLCMD; | ||
| 1505 | break; | ||
| 1506 | } | ||
| 1507 | return rc; | ||
| 1508 | } | ||
| 1509 | #endif | ||
| 1510 | |||
| 1390 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | 1511 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { |
| 1391 | .family = AF_X25, | 1512 | .family = AF_X25, |
| 1392 | .owner = THIS_MODULE, | 1513 | .owner = THIS_MODULE, |
| @@ -1398,6 +1519,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
| 1398 | .getname = x25_getname, | 1519 | .getname = x25_getname, |
| 1399 | .poll = datagram_poll, | 1520 | .poll = datagram_poll, |
| 1400 | .ioctl = x25_ioctl, | 1521 | .ioctl = x25_ioctl, |
| 1522 | #ifdef CONFIG_COMPAT | ||
| 1523 | .compat_ioctl = compat_x25_ioctl, | ||
| 1524 | #endif | ||
| 1401 | .listen = x25_listen, | 1525 | .listen = x25_listen, |
| 1402 | .shutdown = sock_no_shutdown, | 1526 | .shutdown = sock_no_shutdown, |
| 1403 | .setsockopt = x25_setsockopt, | 1527 | .setsockopt = x25_setsockopt, |
