linux/net/atm/ioctl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* ATM ioctl handling */
   3
   4/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
   5/* 2003 John Levon  <levon@movementarian.org> */
   6
   7#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
   8
   9#include <linux/module.h>
  10#include <linux/kmod.h>
  11#include <linux/net.h>          /* struct socket, struct proto_ops */
  12#include <linux/atm.h>          /* ATM stuff */
  13#include <linux/atmdev.h>
  14#include <linux/atmclip.h>      /* CLIP_*ENCAP */
  15#include <linux/atmarp.h>       /* manifest constants */
  16#include <linux/capability.h>
  17#include <linux/sonet.h>        /* for ioctls */
  18#include <linux/atmsvc.h>
  19#include <linux/atmmpc.h>
  20#include <net/atmclip.h>
  21#include <linux/atmlec.h>
  22#include <linux/mutex.h>
  23#include <asm/ioctls.h>
  24#include <net/compat.h>
  25
  26#include "resources.h"
  27#include "signaling.h"          /* for WAITING and sigd_attach */
  28#include "common.h"
  29
  30
  31static DEFINE_MUTEX(ioctl_mutex);
  32static LIST_HEAD(ioctl_list);
  33
  34
  35void register_atm_ioctl(struct atm_ioctl *ioctl)
  36{
  37        mutex_lock(&ioctl_mutex);
  38        list_add_tail(&ioctl->list, &ioctl_list);
  39        mutex_unlock(&ioctl_mutex);
  40}
  41EXPORT_SYMBOL(register_atm_ioctl);
  42
  43void deregister_atm_ioctl(struct atm_ioctl *ioctl)
  44{
  45        mutex_lock(&ioctl_mutex);
  46        list_del(&ioctl->list);
  47        mutex_unlock(&ioctl_mutex);
  48}
  49EXPORT_SYMBOL(deregister_atm_ioctl);
  50
  51static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
  52                        unsigned long arg, int compat)
  53{
  54        struct sock *sk = sock->sk;
  55        struct atm_vcc *vcc;
  56        int error;
  57        struct list_head *pos;
  58        void __user *argp = (void __user *)arg;
  59
  60        vcc = ATM_SD(sock);
  61        switch (cmd) {
  62        case SIOCOUTQ:
  63                if (sock->state != SS_CONNECTED ||
  64                    !test_bit(ATM_VF_READY, &vcc->flags)) {
  65                        error =  -EINVAL;
  66                        goto done;
  67                }
  68                error = put_user(sk->sk_sndbuf - sk_wmem_alloc_get(sk),
  69                                 (int __user *)argp) ? -EFAULT : 0;
  70                goto done;
  71        case SIOCINQ:
  72        {
  73                struct sk_buff *skb;
  74
  75                if (sock->state != SS_CONNECTED) {
  76                        error = -EINVAL;
  77                        goto done;
  78                }
  79                skb = skb_peek(&sk->sk_receive_queue);
  80                error = put_user(skb ? skb->len : 0,
  81                                 (int __user *)argp) ? -EFAULT : 0;
  82                goto done;
  83        }
  84        case ATM_SETSC:
  85                net_warn_ratelimited("ATM_SETSC is obsolete; used by %s:%d\n",
  86                                     current->comm, task_pid_nr(current));
  87                error = 0;
  88                goto done;
  89        case ATMSIGD_CTRL:
  90                if (!capable(CAP_NET_ADMIN)) {
  91                        error = -EPERM;
  92                        goto done;
  93                }
  94                /*
  95                 * The user/kernel protocol for exchanging signalling
  96                 * info uses kernel pointers as opaque references,
  97                 * so the holder of the file descriptor can scribble
  98                 * on the kernel... so we should make sure that we
  99                 * have the same privileges that /proc/kcore needs
 100                 */
 101                if (!capable(CAP_SYS_RAWIO)) {
 102                        error = -EPERM;
 103                        goto done;
 104                }
 105#ifdef CONFIG_COMPAT
 106                /* WTF? I don't even want to _think_ about making this
 107                   work for 32-bit userspace. TBH I don't really want
 108                   to think about it at all. dwmw2. */
 109                if (compat) {
 110                        net_warn_ratelimited("32-bit task cannot be atmsigd\n");
 111                        error = -EINVAL;
 112                        goto done;
 113                }
 114#endif
 115                error = sigd_attach(vcc);
 116                if (!error)
 117                        sock->state = SS_CONNECTED;
 118                goto done;
 119        case ATM_SETBACKEND:
 120        case ATM_NEWBACKENDIF:
 121        {
 122                atm_backend_t backend;
 123                error = get_user(backend, (atm_backend_t __user *)argp);
 124                if (error)
 125                        goto done;
 126                switch (backend) {
 127                case ATM_BACKEND_PPP:
 128                        request_module("pppoatm");
 129                        break;
 130                case ATM_BACKEND_BR2684:
 131                        request_module("br2684");
 132                        break;
 133                }
 134                break;
 135        }
 136        case ATMMPC_CTRL:
 137        case ATMMPC_DATA:
 138                request_module("mpoa");
 139                break;
 140        case ATMARPD_CTRL:
 141                request_module("clip");
 142                break;
 143        case ATMLEC_CTRL:
 144                request_module("lec");
 145                break;
 146        }
 147
 148        error = -ENOIOCTLCMD;
 149
 150        mutex_lock(&ioctl_mutex);
 151        list_for_each(pos, &ioctl_list) {
 152                struct atm_ioctl *ic = list_entry(pos, struct atm_ioctl, list);
 153                if (try_module_get(ic->owner)) {
 154                        error = ic->ioctl(sock, cmd, arg);
 155                        module_put(ic->owner);
 156                        if (error != -ENOIOCTLCMD)
 157                                break;
 158                }
 159        }
 160        mutex_unlock(&ioctl_mutex);
 161
 162        if (error != -ENOIOCTLCMD)
 163                goto done;
 164
 165        error = atm_dev_ioctl(cmd, argp, compat);
 166
 167done:
 168        return error;
 169}
 170
 171int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 172{
 173        return do_vcc_ioctl(sock, cmd, arg, 0);
 174}
 175
 176#ifdef CONFIG_COMPAT
 177/*
 178 * FIXME:
 179 * The compat_ioctl handling is duplicated, using both these conversion
 180 * routines and the compat argument to the actual handlers. Both
 181 * versions are somewhat incomplete and should be merged, e.g. by
 182 * moving the ioctl number translation into the actual handlers and
 183 * killing the conversion code.
 184 *
 185 * -arnd, November 2009
 186 */
 187#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct compat_atmif_sioc)
 188#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct compat_atm_iobuf)
 189#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct compat_atmif_sioc)
 190#define ATM_GETESI32      _IOW('a', ATMIOC_ITF+5, struct compat_atmif_sioc)
 191#define ATM_GETADDR32     _IOW('a', ATMIOC_ITF+6, struct compat_atmif_sioc)
 192#define ATM_RSTADDR32     _IOW('a', ATMIOC_ITF+7, struct compat_atmif_sioc)
 193#define ATM_ADDADDR32     _IOW('a', ATMIOC_ITF+8, struct compat_atmif_sioc)
 194#define ATM_DELADDR32     _IOW('a', ATMIOC_ITF+9, struct compat_atmif_sioc)
 195#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct compat_atmif_sioc)
 196#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct compat_atmif_sioc)
 197#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct compat_atmif_sioc)
 198#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct compat_atmif_sioc)
 199#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct compat_atmif_sioc)
 200#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct compat_atmif_sioc)
 201#define ATM_GETLOOP32     _IOW('a', ATMIOC_SARCOM+2, struct compat_atmif_sioc)
 202#define ATM_SETLOOP32     _IOW('a', ATMIOC_SARCOM+3, struct compat_atmif_sioc)
 203#define ATM_QUERYLOOP32   _IOW('a', ATMIOC_SARCOM+4, struct compat_atmif_sioc)
 204
 205static struct {
 206        unsigned int cmd32;
 207        unsigned int cmd;
 208} atm_ioctl_map[] = {
 209        { ATM_GETLINKRATE32, ATM_GETLINKRATE },
 210        { ATM_GETNAMES32,    ATM_GETNAMES },
 211        { ATM_GETTYPE32,     ATM_GETTYPE },
 212        { ATM_GETESI32,      ATM_GETESI },
 213        { ATM_GETADDR32,     ATM_GETADDR },
 214        { ATM_RSTADDR32,     ATM_RSTADDR },
 215        { ATM_ADDADDR32,     ATM_ADDADDR },
 216        { ATM_DELADDR32,     ATM_DELADDR },
 217        { ATM_GETCIRANGE32,  ATM_GETCIRANGE },
 218        { ATM_SETCIRANGE32,  ATM_SETCIRANGE },
 219        { ATM_SETESI32,      ATM_SETESI },
 220        { ATM_SETESIF32,     ATM_SETESIF },
 221        { ATM_GETSTAT32,     ATM_GETSTAT },
 222        { ATM_GETSTATZ32,    ATM_GETSTATZ },
 223        { ATM_GETLOOP32,     ATM_GETLOOP },
 224        { ATM_SETLOOP32,     ATM_SETLOOP },
 225        { ATM_QUERYLOOP32,   ATM_QUERYLOOP },
 226};
 227
 228#define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map)
 229
 230static int do_atm_iobuf(struct socket *sock, unsigned int cmd,
 231                        unsigned long arg)
 232{
 233        struct atm_iobuf __user *iobuf;
 234        struct compat_atm_iobuf __user *iobuf32;
 235        u32 data;
 236        void __user *datap;
 237        int len, err;
 238
 239        iobuf = compat_alloc_user_space(sizeof(*iobuf));
 240        iobuf32 = compat_ptr(arg);
 241
 242        if (get_user(len, &iobuf32->length) ||
 243            get_user(data, &iobuf32->buffer))
 244                return -EFAULT;
 245        datap = compat_ptr(data);
 246        if (put_user(len, &iobuf->length) ||
 247            put_user(datap, &iobuf->buffer))
 248                return -EFAULT;
 249
 250        err = do_vcc_ioctl(sock, cmd, (unsigned long) iobuf, 0);
 251
 252        if (!err) {
 253                if (copy_in_user(&iobuf32->length, &iobuf->length,
 254                                 sizeof(int)))
 255                        err = -EFAULT;
 256        }
 257
 258        return err;
 259}
 260
 261static int do_atmif_sioc(struct socket *sock, unsigned int cmd,
 262                         unsigned long arg)
 263{
 264        struct atmif_sioc __user *sioc;
 265        struct compat_atmif_sioc __user *sioc32;
 266        u32 data;
 267        void __user *datap;
 268        int err;
 269
 270        sioc = compat_alloc_user_space(sizeof(*sioc));
 271        sioc32 = compat_ptr(arg);
 272
 273        if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
 274            get_user(data, &sioc32->arg))
 275                return -EFAULT;
 276        datap = compat_ptr(data);
 277        if (put_user(datap, &sioc->arg))
 278                return -EFAULT;
 279
 280        err = do_vcc_ioctl(sock, cmd, (unsigned long) sioc, 0);
 281
 282        if (!err) {
 283                if (copy_in_user(&sioc32->length, &sioc->length,
 284                                 sizeof(int)))
 285                        err = -EFAULT;
 286        }
 287        return err;
 288}
 289
 290static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
 291                        unsigned long arg)
 292{
 293        int i;
 294        unsigned int cmd = 0;
 295
 296        switch (cmd32) {
 297        case SONET_GETSTAT:
 298        case SONET_GETSTATZ:
 299        case SONET_GETDIAG:
 300        case SONET_SETDIAG:
 301        case SONET_CLRDIAG:
 302        case SONET_SETFRAMING:
 303        case SONET_GETFRAMING:
 304        case SONET_GETFRSENSE:
 305                return do_atmif_sioc(sock, cmd32, arg);
 306        }
 307
 308        for (i = 0; i < NR_ATM_IOCTL; i++) {
 309                if (cmd32 == atm_ioctl_map[i].cmd32) {
 310                        cmd = atm_ioctl_map[i].cmd;
 311                        break;
 312                }
 313        }
 314        if (i == NR_ATM_IOCTL)
 315                return -EINVAL;
 316
 317        switch (cmd) {
 318        case ATM_GETNAMES:
 319                return do_atm_iobuf(sock, cmd, arg);
 320
 321        case ATM_GETLINKRATE:
 322        case ATM_GETTYPE:
 323        case ATM_GETESI:
 324        case ATM_GETADDR:
 325        case ATM_RSTADDR:
 326        case ATM_ADDADDR:
 327        case ATM_DELADDR:
 328        case ATM_GETCIRANGE:
 329        case ATM_SETCIRANGE:
 330        case ATM_SETESI:
 331        case ATM_SETESIF:
 332        case ATM_GETSTAT:
 333        case ATM_GETSTATZ:
 334        case ATM_GETLOOP:
 335        case ATM_SETLOOP:
 336        case ATM_QUERYLOOP:
 337                return do_atmif_sioc(sock, cmd, arg);
 338        }
 339
 340        return -EINVAL;
 341}
 342
 343int vcc_compat_ioctl(struct socket *sock, unsigned int cmd,
 344                     unsigned long arg)
 345{
 346        int ret;
 347
 348        ret = do_vcc_ioctl(sock, cmd, arg, 1);
 349        if (ret != -ENOIOCTLCMD)
 350                return ret;
 351
 352        return do_atm_ioctl(sock, cmd, arg);
 353}
 354#endif
 355