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/capability.h> 15 #include <linux/mutex.h> 16 #include <asm/ioctls.h> 17 #include <net/compat.h> 18 19 #include "resources.h" 20 #include "common.h" 21 22 23 static DEFINE_MUTEX(ioctl_mutex); 24 static LIST_HEAD(ioctl_list); 25 26 27 void register_atm_ioctl(struct atm_ioctl *ioctl) 28 { 29 mutex_lock(&ioctl_mutex); 30 list_add_tail(&ioctl->list, &ioctl_list); 31 mutex_unlock(&ioctl_mutex); 32 } 33 EXPORT_SYMBOL(register_atm_ioctl); 34 35 void deregister_atm_ioctl(struct atm_ioctl *ioctl) 36 { 37 mutex_lock(&ioctl_mutex); 38 list_del(&ioctl->list); 39 mutex_unlock(&ioctl_mutex); 40 } 41 EXPORT_SYMBOL(deregister_atm_ioctl); 42 43 static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, 44 unsigned long arg, int compat) 45 { 46 struct sock *sk = sock->sk; 47 struct atm_vcc *vcc; 48 int error; 49 struct list_head *pos; 50 void __user *argp = (void __user *)arg; 51 void __user *buf; 52 int __user *len; 53 54 vcc = ATM_SD(sock); 55 switch (cmd) { 56 case SIOCOUTQ: 57 if (sock->state != SS_CONNECTED || 58 !test_bit(ATM_VF_READY, &vcc->flags)) { 59 error = -EINVAL; 60 goto done; 61 } 62 error = put_user(sk->sk_sndbuf - sk_wmem_alloc_get(sk), 63 (int __user *)argp); 64 goto done; 65 case SIOCINQ: 66 { 67 struct sk_buff *skb; 68 int amount; 69 70 if (sock->state != SS_CONNECTED) { 71 error = -EINVAL; 72 goto done; 73 } 74 spin_lock_irq(&sk->sk_receive_queue.lock); 75 skb = skb_peek(&sk->sk_receive_queue); 76 amount = skb ? skb->len : 0; 77 spin_unlock_irq(&sk->sk_receive_queue.lock); 78 error = put_user(amount, (int __user *)argp); 79 goto done; 80 } 81 case ATM_SETSC: 82 net_warn_ratelimited("ATM_SETSC is obsolete; used by %s:%d\n", 83 current->comm, task_pid_nr(current)); 84 error = 0; 85 goto done; 86 case ATM_SETBACKEND: 87 case ATM_NEWBACKENDIF: 88 { 89 atm_backend_t backend; 90 error = get_user(backend, (atm_backend_t __user *)argp); 91 if (error) 92 goto done; 93 switch (backend) { 94 case ATM_BACKEND_PPP: 95 request_module("pppoatm"); 96 break; 97 case ATM_BACKEND_BR2684: 98 request_module("br2684"); 99 break; 100 } 101 break; 102 } 103 } 104 105 error = -ENOIOCTLCMD; 106 107 mutex_lock(&ioctl_mutex); 108 list_for_each(pos, &ioctl_list) { 109 struct atm_ioctl *ic = list_entry(pos, struct atm_ioctl, list); 110 if (try_module_get(ic->owner)) { 111 error = ic->ioctl(sock, cmd, arg); 112 module_put(ic->owner); 113 if (error != -ENOIOCTLCMD) 114 break; 115 } 116 } 117 mutex_unlock(&ioctl_mutex); 118 119 if (error != -ENOIOCTLCMD) 120 goto done; 121 122 if (cmd == ATM_GETNAMES) { 123 if (IS_ENABLED(CONFIG_COMPAT) && compat) { 124 #ifdef CONFIG_COMPAT 125 struct compat_atm_iobuf __user *ciobuf = argp; 126 compat_uptr_t cbuf; 127 len = &ciobuf->length; 128 if (get_user(cbuf, &ciobuf->buffer)) 129 return -EFAULT; 130 buf = compat_ptr(cbuf); 131 #endif 132 } else { 133 struct atm_iobuf __user *iobuf = argp; 134 len = &iobuf->length; 135 if (get_user(buf, &iobuf->buffer)) 136 return -EFAULT; 137 } 138 error = atm_getnames(buf, len); 139 } else { 140 int number; 141 142 if (IS_ENABLED(CONFIG_COMPAT) && compat) { 143 #ifdef CONFIG_COMPAT 144 struct compat_atmif_sioc __user *csioc = argp; 145 compat_uptr_t carg; 146 147 len = &csioc->length; 148 if (get_user(carg, &csioc->arg)) 149 return -EFAULT; 150 buf = compat_ptr(carg); 151 if (get_user(number, &csioc->number)) 152 return -EFAULT; 153 #endif 154 } else { 155 struct atmif_sioc __user *sioc = argp; 156 157 len = &sioc->length; 158 if (get_user(buf, &sioc->arg)) 159 return -EFAULT; 160 if (get_user(number, &sioc->number)) 161 return -EFAULT; 162 } 163 error = atm_dev_ioctl(cmd, buf, len, number, compat); 164 } 165 166 done: 167 return error; 168 } 169 170 int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 171 { 172 return do_vcc_ioctl(sock, cmd, arg, 0); 173 } 174 175 #ifdef CONFIG_COMPAT 176 /* 177 * FIXME: 178 * The compat_ioctl handling is duplicated, using both these conversion 179 * routines and the compat argument to the actual handlers. Both 180 * versions are somewhat incomplete and should be merged, e.g. by 181 * moving the ioctl number translation into the actual handlers and 182 * killing the conversion code. 183 * 184 * -arnd, November 2009 185 */ 186 #define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct compat_atmif_sioc) 187 #define ATM_GETNAMES32 _IOW('a', ATMIOC_ITF+3, struct compat_atm_iobuf) 188 #define ATM_GETTYPE32 _IOW('a', ATMIOC_ITF+4, struct compat_atmif_sioc) 189 #define ATM_GETESI32 _IOW('a', ATMIOC_ITF+5, struct compat_atmif_sioc) 190 #define ATM_GETCIRANGE32 _IOW('a', ATMIOC_ITF+10, struct compat_atmif_sioc) 191 #define ATM_SETCIRANGE32 _IOW('a', ATMIOC_ITF+11, struct compat_atmif_sioc) 192 #define ATM_SETESI32 _IOW('a', ATMIOC_ITF+12, struct compat_atmif_sioc) 193 #define ATM_SETESIF32 _IOW('a', ATMIOC_ITF+13, struct compat_atmif_sioc) 194 #define ATM_GETSTAT32 _IOW('a', ATMIOC_SARCOM+0, struct compat_atmif_sioc) 195 #define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct compat_atmif_sioc) 196 #define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct compat_atmif_sioc) 197 #define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct compat_atmif_sioc) 198 #define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct compat_atmif_sioc) 199 200 static struct { 201 unsigned int cmd32; 202 unsigned int cmd; 203 } atm_ioctl_map[] = { 204 { ATM_GETLINKRATE32, ATM_GETLINKRATE }, 205 { ATM_GETNAMES32, ATM_GETNAMES }, 206 { ATM_GETTYPE32, ATM_GETTYPE }, 207 { ATM_GETESI32, ATM_GETESI }, 208 { ATM_GETCIRANGE32, ATM_GETCIRANGE }, 209 { ATM_SETCIRANGE32, ATM_SETCIRANGE }, 210 { ATM_SETESI32, ATM_SETESI }, 211 { ATM_SETESIF32, ATM_SETESIF }, 212 { ATM_GETSTAT32, ATM_GETSTAT }, 213 { ATM_GETSTATZ32, ATM_GETSTATZ }, 214 { ATM_GETLOOP32, ATM_GETLOOP }, 215 { ATM_SETLOOP32, ATM_SETLOOP }, 216 { ATM_QUERYLOOP32, ATM_QUERYLOOP }, 217 }; 218 219 #define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map) 220 221 static int do_atm_iobuf(struct socket *sock, unsigned int cmd, 222 unsigned long arg) 223 { 224 struct compat_atm_iobuf __user *iobuf32 = compat_ptr(arg); 225 u32 data; 226 227 if (get_user(data, &iobuf32->buffer)) 228 return -EFAULT; 229 230 return atm_getnames(&iobuf32->length, compat_ptr(data)); 231 } 232 233 static int do_atmif_sioc(struct socket *sock, unsigned int cmd, 234 unsigned long arg) 235 { 236 struct compat_atmif_sioc __user *sioc32 = compat_ptr(arg); 237 int number; 238 u32 data; 239 240 if (get_user(data, &sioc32->arg) || get_user(number, &sioc32->number)) 241 return -EFAULT; 242 return atm_dev_ioctl(cmd, compat_ptr(data), &sioc32->length, number, 0); 243 } 244 245 static int do_atm_ioctl(struct socket *sock, unsigned int cmd32, 246 unsigned long arg) 247 { 248 int i; 249 unsigned int cmd = 0; 250 251 for (i = 0; i < NR_ATM_IOCTL; i++) { 252 if (cmd32 == atm_ioctl_map[i].cmd32) { 253 cmd = atm_ioctl_map[i].cmd; 254 break; 255 } 256 } 257 if (i == NR_ATM_IOCTL) 258 return -EINVAL; 259 260 switch (cmd) { 261 case ATM_GETNAMES: 262 return do_atm_iobuf(sock, cmd, arg); 263 264 case ATM_GETLINKRATE: 265 case ATM_GETTYPE: 266 case ATM_GETESI: 267 case ATM_GETCIRANGE: 268 case ATM_SETCIRANGE: 269 case ATM_SETESI: 270 case ATM_SETESIF: 271 case ATM_GETSTAT: 272 case ATM_GETSTATZ: 273 case ATM_GETLOOP: 274 case ATM_SETLOOP: 275 case ATM_QUERYLOOP: 276 return do_atmif_sioc(sock, cmd, arg); 277 } 278 279 return -EINVAL; 280 } 281 282 int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, 283 unsigned long arg) 284 { 285 int ret; 286 287 ret = do_vcc_ioctl(sock, cmd, arg, 1); 288 if (ret != -ENOIOCTLCMD) 289 return ret; 290 291 return do_atm_ioctl(sock, cmd, arg); 292 } 293 #endif 294