root/net/atm/ioctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. register_atm_ioctl
  2. deregister_atm_ioctl
  3. do_vcc_ioctl
  4. vcc_ioctl
  5. do_atm_iobuf
  6. do_atmif_sioc
  7. do_atm_ioctl
  8. vcc_compat_ioctl

   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 
  31 static DEFINE_MUTEX(ioctl_mutex);
  32 static LIST_HEAD(ioctl_list);
  33 
  34 
  35 void 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 }
  41 EXPORT_SYMBOL(register_atm_ioctl);
  42 
  43 void deregister_atm_ioctl(struct atm_ioctl *ioctl)
  44 {
  45         mutex_lock(&ioctl_mutex);
  46         list_del(&ioctl->list);
  47         mutex_unlock(&ioctl_mutex);
  48 }
  49 EXPORT_SYMBOL(deregister_atm_ioctl);
  50 
  51 static 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 
 167 done:
 168         return error;
 169 }
 170 
 171 int 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 
 205 static 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 
 230 static 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 
 261 static 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 
 290 static 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 
 343 int 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

/* [<][>][^][v][top][bottom][index][help] */