1 // SPDX-License-Identifier: GPL-2.0 2 /* net/atm/resources.c - Statically allocated resources */ 3 4 /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ 5 6 /* Fixes 7 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 8 * 2002/01 - don't free the whole struct sock on sk->destruct time, 9 * use the default destruct function initialized by sock_init_data */ 10 11 #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ 12 13 #include <linux/ctype.h> 14 #include <linux/string.h> 15 #include <linux/atmdev.h> 16 #include <linux/sonet.h> 17 #include <linux/kernel.h> /* for barrier */ 18 #include <linux/module.h> 19 #include <linux/bitops.h> 20 #include <linux/capability.h> 21 #include <linux/delay.h> 22 #include <linux/mutex.h> 23 #include <linux/slab.h> 24 25 #include <net/sock.h> /* for struct sock */ 26 27 #include "common.h" 28 #include "resources.h" 29 #include "addr.h" 30 31 32 LIST_HEAD(atm_devs); 33 DEFINE_MUTEX(atm_dev_mutex); 34 35 static struct atm_dev *__alloc_atm_dev(const char *type) 36 { 37 struct atm_dev *dev; 38 39 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 40 if (!dev) 41 return NULL; 42 dev->type = type; 43 dev->signal = ATM_PHY_SIG_UNKNOWN; 44 dev->link_rate = ATM_OC3_PCR; 45 spin_lock_init(&dev->lock); 46 INIT_LIST_HEAD(&dev->local); 47 INIT_LIST_HEAD(&dev->lecs); 48 49 return dev; 50 } 51 52 static struct atm_dev *__atm_dev_lookup(int number) 53 { 54 struct atm_dev *dev; 55 56 list_for_each_entry(dev, &atm_devs, dev_list) { 57 if (dev->number == number) { 58 atm_dev_hold(dev); 59 return dev; 60 } 61 } 62 return NULL; 63 } 64 65 struct atm_dev *atm_dev_lookup(int number) 66 { 67 struct atm_dev *dev; 68 69 mutex_lock(&atm_dev_mutex); 70 dev = __atm_dev_lookup(number); 71 mutex_unlock(&atm_dev_mutex); 72 return dev; 73 } 74 EXPORT_SYMBOL(atm_dev_lookup); 75 76 struct atm_dev *atm_dev_register(const char *type, struct device *parent, 77 const struct atmdev_ops *ops, int number, 78 unsigned long *flags) 79 { 80 struct atm_dev *dev, *inuse; 81 82 dev = __alloc_atm_dev(type); 83 if (!dev) { 84 pr_err("no space for dev %s\n", type); 85 return NULL; 86 } 87 mutex_lock(&atm_dev_mutex); 88 if (number != -1) { 89 inuse = __atm_dev_lookup(number); 90 if (inuse) { 91 atm_dev_put(inuse); 92 mutex_unlock(&atm_dev_mutex); 93 kfree(dev); 94 return NULL; 95 } 96 dev->number = number; 97 } else { 98 dev->number = 0; 99 while ((inuse = __atm_dev_lookup(dev->number))) { 100 atm_dev_put(inuse); 101 dev->number++; 102 } 103 } 104 105 dev->ops = ops; 106 if (flags) 107 dev->flags = *flags; 108 else 109 memset(&dev->flags, 0, sizeof(dev->flags)); 110 memset(&dev->stats, 0, sizeof(dev->stats)); 111 refcount_set(&dev->refcnt, 1); 112 113 if (atm_proc_dev_register(dev) < 0) { 114 pr_err("atm_proc_dev_register failed for dev %s\n", type); 115 mutex_unlock(&atm_dev_mutex); 116 kfree(dev); 117 return NULL; 118 } 119 120 if (atm_register_sysfs(dev, parent) < 0) { 121 pr_err("atm_register_sysfs failed for dev %s\n", type); 122 atm_proc_dev_deregister(dev); 123 goto out_fail; 124 } 125 126 list_add_tail(&dev->dev_list, &atm_devs); 127 128 out: 129 mutex_unlock(&atm_dev_mutex); 130 return dev; 131 132 out_fail: 133 put_device(&dev->class_dev); 134 dev = NULL; 135 goto out; 136 } 137 EXPORT_SYMBOL(atm_dev_register); 138 139 void atm_dev_deregister(struct atm_dev *dev) 140 { 141 BUG_ON(test_bit(ATM_DF_REMOVED, &dev->flags)); 142 set_bit(ATM_DF_REMOVED, &dev->flags); 143 144 /* 145 * if we remove current device from atm_devs list, new device 146 * with same number can appear, such we need deregister proc, 147 * release async all vccs and remove them from vccs list too 148 */ 149 mutex_lock(&atm_dev_mutex); 150 list_del(&dev->dev_list); 151 atm_dev_release_vccs(dev); 152 atm_unregister_sysfs(dev); 153 atm_proc_dev_deregister(dev); 154 mutex_unlock(&atm_dev_mutex); 155 156 atm_dev_put(dev); 157 } 158 EXPORT_SYMBOL(atm_dev_deregister); 159 160 static void copy_aal_stats(struct k_atm_aal_stats *from, 161 struct atm_aal_stats *to) 162 { 163 #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i) 164 __AAL_STAT_ITEMS 165 #undef __HANDLE_ITEM 166 } 167 168 static void subtract_aal_stats(struct k_atm_aal_stats *from, 169 struct atm_aal_stats *to) 170 { 171 #define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i) 172 __AAL_STAT_ITEMS 173 #undef __HANDLE_ITEM 174 } 175 176 static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, 177 int zero) 178 { 179 struct atm_dev_stats tmp; 180 int error = 0; 181 182 copy_aal_stats(&dev->stats.aal0, &tmp.aal0); 183 copy_aal_stats(&dev->stats.aal34, &tmp.aal34); 184 copy_aal_stats(&dev->stats.aal5, &tmp.aal5); 185 if (arg) 186 error = copy_to_user(arg, &tmp, sizeof(tmp)); 187 if (zero && !error) { 188 subtract_aal_stats(&dev->stats.aal0, &tmp.aal0); 189 subtract_aal_stats(&dev->stats.aal34, &tmp.aal34); 190 subtract_aal_stats(&dev->stats.aal5, &tmp.aal5); 191 } 192 return error ? -EFAULT : 0; 193 } 194 195 int atm_getnames(void __user *buf, int __user *iobuf_len) 196 { 197 int error, len, size = 0; 198 struct atm_dev *dev; 199 struct list_head *p; 200 int *tmp_buf, *tmp_p; 201 202 if (get_user(len, iobuf_len)) 203 return -EFAULT; 204 mutex_lock(&atm_dev_mutex); 205 list_for_each(p, &atm_devs) 206 size += sizeof(int); 207 if (size > len) { 208 mutex_unlock(&atm_dev_mutex); 209 return -E2BIG; 210 } 211 tmp_buf = kmalloc(size, GFP_ATOMIC); 212 if (!tmp_buf) { 213 mutex_unlock(&atm_dev_mutex); 214 return -ENOMEM; 215 } 216 tmp_p = tmp_buf; 217 list_for_each_entry(dev, &atm_devs, dev_list) { 218 *tmp_p++ = dev->number; 219 } 220 mutex_unlock(&atm_dev_mutex); 221 error = ((copy_to_user(buf, tmp_buf, size)) || 222 put_user(size, iobuf_len)) 223 ? -EFAULT : 0; 224 kfree(tmp_buf); 225 return error; 226 } 227 228 int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, 229 int number, int compat) 230 { 231 int error, len, size = 0; 232 struct atm_dev *dev; 233 234 if (get_user(len, sioc_len)) 235 return -EFAULT; 236 237 dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d", 238 number); 239 if (!dev) 240 return -ENODEV; 241 242 switch (cmd) { 243 case ATM_GETTYPE: 244 size = strlen(dev->type) + 1; 245 if (copy_to_user(buf, dev->type, size)) { 246 error = -EFAULT; 247 goto done; 248 } 249 break; 250 case ATM_GETESI: 251 size = ESI_LEN; 252 if (copy_to_user(buf, dev->esi, size)) { 253 error = -EFAULT; 254 goto done; 255 } 256 break; 257 case ATM_SETESI: 258 { 259 int i; 260 261 for (i = 0; i < ESI_LEN; i++) 262 if (dev->esi[i]) { 263 error = -EEXIST; 264 goto done; 265 } 266 } 267 fallthrough; 268 case ATM_SETESIF: 269 { 270 unsigned char esi[ESI_LEN]; 271 272 if (!capable(CAP_NET_ADMIN)) { 273 error = -EPERM; 274 goto done; 275 } 276 if (copy_from_user(esi, buf, ESI_LEN)) { 277 error = -EFAULT; 278 goto done; 279 } 280 memcpy(dev->esi, esi, ESI_LEN); 281 error = ESI_LEN; 282 goto done; 283 } 284 case ATM_GETSTATZ: 285 if (!capable(CAP_NET_ADMIN)) { 286 error = -EPERM; 287 goto done; 288 } 289 fallthrough; 290 case ATM_GETSTAT: 291 size = sizeof(struct atm_dev_stats); 292 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ); 293 if (error) 294 goto done; 295 break; 296 case ATM_GETCIRANGE: 297 size = sizeof(struct atm_cirange); 298 if (copy_to_user(buf, &dev->ci_range, size)) { 299 error = -EFAULT; 300 goto done; 301 } 302 break; 303 case ATM_GETLINKRATE: 304 size = sizeof(int); 305 if (copy_to_user(buf, &dev->link_rate, size)) { 306 error = -EFAULT; 307 goto done; 308 } 309 break; 310 case ATM_RSTADDR: 311 if (!capable(CAP_NET_ADMIN)) { 312 error = -EPERM; 313 goto done; 314 } 315 atm_reset_addr(dev, ATM_ADDR_LOCAL); 316 break; 317 case ATM_ADDADDR: 318 case ATM_DELADDR: 319 case ATM_ADDLECSADDR: 320 case ATM_DELLECSADDR: 321 { 322 struct sockaddr_atmsvc addr; 323 324 if (!capable(CAP_NET_ADMIN)) { 325 error = -EPERM; 326 goto done; 327 } 328 329 if (copy_from_user(&addr, buf, sizeof(addr))) { 330 error = -EFAULT; 331 goto done; 332 } 333 if (cmd == ATM_ADDADDR || cmd == ATM_ADDLECSADDR) 334 error = atm_add_addr(dev, &addr, 335 (cmd == ATM_ADDADDR ? 336 ATM_ADDR_LOCAL : ATM_ADDR_LECS)); 337 else 338 error = atm_del_addr(dev, &addr, 339 (cmd == ATM_DELADDR ? 340 ATM_ADDR_LOCAL : ATM_ADDR_LECS)); 341 goto done; 342 } 343 case ATM_GETADDR: 344 case ATM_GETLECSADDR: 345 error = atm_get_addr(dev, buf, len, 346 (cmd == ATM_GETADDR ? 347 ATM_ADDR_LOCAL : ATM_ADDR_LECS)); 348 if (error < 0) 349 goto done; 350 size = error; 351 /* may return 0, but later on size == 0 means "don't 352 write the length" */ 353 error = put_user(size, sioc_len) ? -EFAULT : 0; 354 goto done; 355 case ATM_SETLOOP: 356 if (__ATM_LM_XTRMT((int) (unsigned long) buf) && 357 __ATM_LM_XTLOC((int) (unsigned long) buf) > 358 __ATM_LM_XTRMT((int) (unsigned long) buf)) { 359 error = -EINVAL; 360 goto done; 361 } 362 fallthrough; 363 case ATM_SETCIRANGE: 364 case SONET_GETSTATZ: 365 case SONET_SETDIAG: 366 case SONET_CLRDIAG: 367 case SONET_SETFRAMING: 368 if (!capable(CAP_NET_ADMIN)) { 369 error = -EPERM; 370 goto done; 371 } 372 fallthrough; 373 default: 374 if (IS_ENABLED(CONFIG_COMPAT) && compat) { 375 #ifdef CONFIG_COMPAT 376 if (!dev->ops->compat_ioctl) { 377 error = -EINVAL; 378 goto done; 379 } 380 size = dev->ops->compat_ioctl(dev, cmd, buf); 381 #endif 382 } else { 383 if (!dev->ops->ioctl) { 384 error = -EINVAL; 385 goto done; 386 } 387 size = dev->ops->ioctl(dev, cmd, buf); 388 } 389 if (size < 0) { 390 error = (size == -ENOIOCTLCMD ? -ENOTTY : size); 391 goto done; 392 } 393 } 394 395 if (size) 396 error = put_user(size, sioc_len) ? -EFAULT : 0; 397 else 398 error = 0; 399 done: 400 atm_dev_put(dev); 401 return error; 402 } 403 404 #ifdef CONFIG_PROC_FS 405 void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) 406 { 407 mutex_lock(&atm_dev_mutex); 408 return seq_list_start_head(&atm_devs, *pos); 409 } 410 411 void atm_dev_seq_stop(struct seq_file *seq, void *v) 412 { 413 mutex_unlock(&atm_dev_mutex); 414 } 415 416 void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 417 { 418 return seq_list_next(v, &atm_devs, pos); 419 } 420 #endif 421