Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* ATM ioctl handling */
0003 
0004 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
0005 /* 2003 John Levon  <levon@movementarian.org> */
0006 
0007 #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
0008 
0009 #include <linux/module.h>
0010 #include <linux/kmod.h>
0011 #include <linux/net.h>      /* struct socket, struct proto_ops */
0012 #include <linux/atm.h>      /* ATM stuff */
0013 #include <linux/atmdev.h>
0014 #include <linux/atmclip.h>  /* CLIP_*ENCAP */
0015 #include <linux/atmarp.h>   /* manifest constants */
0016 #include <linux/capability.h>
0017 #include <linux/sonet.h>    /* for ioctls */
0018 #include <linux/atmsvc.h>
0019 #include <linux/atmmpc.h>
0020 #include <net/atmclip.h>
0021 #include <linux/atmlec.h>
0022 #include <linux/mutex.h>
0023 #include <asm/ioctls.h>
0024 #include <net/compat.h>
0025 
0026 #include "resources.h"
0027 #include "signaling.h"      /* for WAITING and sigd_attach */
0028 #include "common.h"
0029 
0030 
0031 static DEFINE_MUTEX(ioctl_mutex);
0032 static LIST_HEAD(ioctl_list);
0033 
0034 
0035 void register_atm_ioctl(struct atm_ioctl *ioctl)
0036 {
0037     mutex_lock(&ioctl_mutex);
0038     list_add_tail(&ioctl->list, &ioctl_list);
0039     mutex_unlock(&ioctl_mutex);
0040 }
0041 EXPORT_SYMBOL(register_atm_ioctl);
0042 
0043 void deregister_atm_ioctl(struct atm_ioctl *ioctl)
0044 {
0045     mutex_lock(&ioctl_mutex);
0046     list_del(&ioctl->list);
0047     mutex_unlock(&ioctl_mutex);
0048 }
0049 EXPORT_SYMBOL(deregister_atm_ioctl);
0050 
0051 static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
0052             unsigned long arg, int compat)
0053 {
0054     struct sock *sk = sock->sk;
0055     struct atm_vcc *vcc;
0056     int error;
0057     struct list_head *pos;
0058     void __user *argp = (void __user *)arg;
0059     void __user *buf;
0060     int __user *len;
0061 
0062     vcc = ATM_SD(sock);
0063     switch (cmd) {
0064     case SIOCOUTQ:
0065         if (sock->state != SS_CONNECTED ||
0066             !test_bit(ATM_VF_READY, &vcc->flags)) {
0067             error =  -EINVAL;
0068             goto done;
0069         }
0070         error = put_user(sk->sk_sndbuf - sk_wmem_alloc_get(sk),
0071                  (int __user *)argp) ? -EFAULT : 0;
0072         goto done;
0073     case SIOCINQ:
0074     {
0075         struct sk_buff *skb;
0076 
0077         if (sock->state != SS_CONNECTED) {
0078             error = -EINVAL;
0079             goto done;
0080         }
0081         skb = skb_peek(&sk->sk_receive_queue);
0082         error = put_user(skb ? skb->len : 0,
0083                  (int __user *)argp) ? -EFAULT : 0;
0084         goto done;
0085     }
0086     case ATM_SETSC:
0087         net_warn_ratelimited("ATM_SETSC is obsolete; used by %s:%d\n",
0088                      current->comm, task_pid_nr(current));
0089         error = 0;
0090         goto done;
0091     case ATMSIGD_CTRL:
0092         if (!capable(CAP_NET_ADMIN)) {
0093             error = -EPERM;
0094             goto done;
0095         }
0096         /*
0097          * The user/kernel protocol for exchanging signalling
0098          * info uses kernel pointers as opaque references,
0099          * so the holder of the file descriptor can scribble
0100          * on the kernel... so we should make sure that we
0101          * have the same privileges that /proc/kcore needs
0102          */
0103         if (!capable(CAP_SYS_RAWIO)) {
0104             error = -EPERM;
0105             goto done;
0106         }
0107 #ifdef CONFIG_COMPAT
0108         /* WTF? I don't even want to _think_ about making this
0109            work for 32-bit userspace. TBH I don't really want
0110            to think about it at all. dwmw2. */
0111         if (compat) {
0112             net_warn_ratelimited("32-bit task cannot be atmsigd\n");
0113             error = -EINVAL;
0114             goto done;
0115         }
0116 #endif
0117         error = sigd_attach(vcc);
0118         if (!error)
0119             sock->state = SS_CONNECTED;
0120         goto done;
0121     case ATM_SETBACKEND:
0122     case ATM_NEWBACKENDIF:
0123     {
0124         atm_backend_t backend;
0125         error = get_user(backend, (atm_backend_t __user *)argp);
0126         if (error)
0127             goto done;
0128         switch (backend) {
0129         case ATM_BACKEND_PPP:
0130             request_module("pppoatm");
0131             break;
0132         case ATM_BACKEND_BR2684:
0133             request_module("br2684");
0134             break;
0135         }
0136         break;
0137     }
0138     case ATMMPC_CTRL:
0139     case ATMMPC_DATA:
0140         request_module("mpoa");
0141         break;
0142     case ATMARPD_CTRL:
0143         request_module("clip");
0144         break;
0145     case ATMLEC_CTRL:
0146         request_module("lec");
0147         break;
0148     }
0149 
0150     error = -ENOIOCTLCMD;
0151 
0152     mutex_lock(&ioctl_mutex);
0153     list_for_each(pos, &ioctl_list) {
0154         struct atm_ioctl *ic = list_entry(pos, struct atm_ioctl, list);
0155         if (try_module_get(ic->owner)) {
0156             error = ic->ioctl(sock, cmd, arg);
0157             module_put(ic->owner);
0158             if (error != -ENOIOCTLCMD)
0159                 break;
0160         }
0161     }
0162     mutex_unlock(&ioctl_mutex);
0163 
0164     if (error != -ENOIOCTLCMD)
0165         goto done;
0166 
0167     if (cmd == ATM_GETNAMES) {
0168         if (IS_ENABLED(CONFIG_COMPAT) && compat) {
0169 #ifdef CONFIG_COMPAT
0170             struct compat_atm_iobuf __user *ciobuf = argp;
0171             compat_uptr_t cbuf;
0172             len = &ciobuf->length;
0173             if (get_user(cbuf, &ciobuf->buffer))
0174                 return -EFAULT;
0175             buf = compat_ptr(cbuf);
0176 #endif
0177         } else {
0178             struct atm_iobuf __user *iobuf = argp;
0179             len = &iobuf->length;
0180             if (get_user(buf, &iobuf->buffer))
0181                 return -EFAULT;
0182         }
0183         error = atm_getnames(buf, len);
0184     } else {
0185         int number;
0186 
0187         if (IS_ENABLED(CONFIG_COMPAT) && compat) {
0188 #ifdef CONFIG_COMPAT
0189             struct compat_atmif_sioc __user *csioc = argp;
0190             compat_uptr_t carg;
0191 
0192             len = &csioc->length;
0193             if (get_user(carg, &csioc->arg))
0194                 return -EFAULT;
0195             buf = compat_ptr(carg);
0196             if (get_user(number, &csioc->number))
0197                 return -EFAULT;
0198 #endif
0199         } else {
0200             struct atmif_sioc __user *sioc = argp;
0201 
0202             len = &sioc->length;
0203             if (get_user(buf, &sioc->arg))
0204                 return -EFAULT;
0205             if (get_user(number, &sioc->number))
0206                 return -EFAULT;
0207         }
0208         error = atm_dev_ioctl(cmd, buf, len, number, compat);
0209     }
0210 
0211 done:
0212     return error;
0213 }
0214 
0215 int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
0216 {
0217     return do_vcc_ioctl(sock, cmd, arg, 0);
0218 }
0219 
0220 #ifdef CONFIG_COMPAT
0221 /*
0222  * FIXME:
0223  * The compat_ioctl handling is duplicated, using both these conversion
0224  * routines and the compat argument to the actual handlers. Both
0225  * versions are somewhat incomplete and should be merged, e.g. by
0226  * moving the ioctl number translation into the actual handlers and
0227  * killing the conversion code.
0228  *
0229  * -arnd, November 2009
0230  */
0231 #define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct compat_atmif_sioc)
0232 #define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct compat_atm_iobuf)
0233 #define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct compat_atmif_sioc)
0234 #define ATM_GETESI32      _IOW('a', ATMIOC_ITF+5, struct compat_atmif_sioc)
0235 #define ATM_GETADDR32     _IOW('a', ATMIOC_ITF+6, struct compat_atmif_sioc)
0236 #define ATM_RSTADDR32     _IOW('a', ATMIOC_ITF+7, struct compat_atmif_sioc)
0237 #define ATM_ADDADDR32     _IOW('a', ATMIOC_ITF+8, struct compat_atmif_sioc)
0238 #define ATM_DELADDR32     _IOW('a', ATMIOC_ITF+9, struct compat_atmif_sioc)
0239 #define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct compat_atmif_sioc)
0240 #define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct compat_atmif_sioc)
0241 #define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct compat_atmif_sioc)
0242 #define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct compat_atmif_sioc)
0243 #define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct compat_atmif_sioc)
0244 #define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct compat_atmif_sioc)
0245 #define ATM_GETLOOP32     _IOW('a', ATMIOC_SARCOM+2, struct compat_atmif_sioc)
0246 #define ATM_SETLOOP32     _IOW('a', ATMIOC_SARCOM+3, struct compat_atmif_sioc)
0247 #define ATM_QUERYLOOP32   _IOW('a', ATMIOC_SARCOM+4, struct compat_atmif_sioc)
0248 
0249 static struct {
0250     unsigned int cmd32;
0251     unsigned int cmd;
0252 } atm_ioctl_map[] = {
0253     { ATM_GETLINKRATE32, ATM_GETLINKRATE },
0254     { ATM_GETNAMES32,    ATM_GETNAMES },
0255     { ATM_GETTYPE32,     ATM_GETTYPE },
0256     { ATM_GETESI32,      ATM_GETESI },
0257     { ATM_GETADDR32,     ATM_GETADDR },
0258     { ATM_RSTADDR32,     ATM_RSTADDR },
0259     { ATM_ADDADDR32,     ATM_ADDADDR },
0260     { ATM_DELADDR32,     ATM_DELADDR },
0261     { ATM_GETCIRANGE32,  ATM_GETCIRANGE },
0262     { ATM_SETCIRANGE32,  ATM_SETCIRANGE },
0263     { ATM_SETESI32,      ATM_SETESI },
0264     { ATM_SETESIF32,     ATM_SETESIF },
0265     { ATM_GETSTAT32,     ATM_GETSTAT },
0266     { ATM_GETSTATZ32,    ATM_GETSTATZ },
0267     { ATM_GETLOOP32,     ATM_GETLOOP },
0268     { ATM_SETLOOP32,     ATM_SETLOOP },
0269     { ATM_QUERYLOOP32,   ATM_QUERYLOOP },
0270 };
0271 
0272 #define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map)
0273 
0274 static int do_atm_iobuf(struct socket *sock, unsigned int cmd,
0275             unsigned long arg)
0276 {
0277     struct compat_atm_iobuf __user *iobuf32 = compat_ptr(arg);
0278     u32 data;
0279 
0280     if (get_user(data, &iobuf32->buffer))
0281         return -EFAULT;
0282 
0283     return atm_getnames(&iobuf32->length, compat_ptr(data));
0284 }
0285 
0286 static int do_atmif_sioc(struct socket *sock, unsigned int cmd,
0287              unsigned long arg)
0288 {
0289     struct compat_atmif_sioc __user *sioc32 = compat_ptr(arg);
0290     int number;
0291     u32 data;
0292 
0293     if (get_user(data, &sioc32->arg) || get_user(number, &sioc32->number))
0294         return -EFAULT;
0295     return atm_dev_ioctl(cmd, compat_ptr(data), &sioc32->length, number, 0);
0296 }
0297 
0298 static int do_atm_ioctl(struct socket *sock, unsigned int cmd32,
0299             unsigned long arg)
0300 {
0301     int i;
0302     unsigned int cmd = 0;
0303 
0304     switch (cmd32) {
0305     case SONET_GETSTAT:
0306     case SONET_GETSTATZ:
0307     case SONET_GETDIAG:
0308     case SONET_SETDIAG:
0309     case SONET_CLRDIAG:
0310     case SONET_SETFRAMING:
0311     case SONET_GETFRAMING:
0312     case SONET_GETFRSENSE:
0313         return do_atmif_sioc(sock, cmd32, arg);
0314     }
0315 
0316     for (i = 0; i < NR_ATM_IOCTL; i++) {
0317         if (cmd32 == atm_ioctl_map[i].cmd32) {
0318             cmd = atm_ioctl_map[i].cmd;
0319             break;
0320         }
0321     }
0322     if (i == NR_ATM_IOCTL)
0323         return -EINVAL;
0324 
0325     switch (cmd) {
0326     case ATM_GETNAMES:
0327         return do_atm_iobuf(sock, cmd, arg);
0328 
0329     case ATM_GETLINKRATE:
0330     case ATM_GETTYPE:
0331     case ATM_GETESI:
0332     case ATM_GETADDR:
0333     case ATM_RSTADDR:
0334     case ATM_ADDADDR:
0335     case ATM_DELADDR:
0336     case ATM_GETCIRANGE:
0337     case ATM_SETCIRANGE:
0338     case ATM_SETESI:
0339     case ATM_SETESIF:
0340     case ATM_GETSTAT:
0341     case ATM_GETSTATZ:
0342     case ATM_GETLOOP:
0343     case ATM_SETLOOP:
0344     case ATM_QUERYLOOP:
0345         return do_atmif_sioc(sock, cmd, arg);
0346     }
0347 
0348     return -EINVAL;
0349 }
0350 
0351 int vcc_compat_ioctl(struct socket *sock, unsigned int cmd,
0352              unsigned long arg)
0353 {
0354     int ret;
0355 
0356     ret = do_vcc_ioctl(sock, cmd, arg, 1);
0357     if (ret != -ENOIOCTLCMD)
0358         return ret;
0359 
0360     return do_atm_ioctl(sock, cmd, arg);
0361 }
0362 #endif