Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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