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/kernel.h> /* for barrier */ 17 #include <linux/module.h> 18 #include <linux/bitops.h> 19 #include <linux/capability.h> 20 #include <linux/delay.h> 21 #include <linux/mutex.h> 22 #include <linux/slab.h> 23 24 #include <net/sock.h> /* for struct sock */ 25 26 #include "common.h" 27 #include "resources.h" 28 29 30 LIST_HEAD(atm_devs); 31 DEFINE_MUTEX(atm_dev_mutex); 32 33 static struct atm_dev *__alloc_atm_dev(const char *type) 34 { 35 struct atm_dev *dev; 36 37 dev = kzalloc_obj(*dev); 38 if (!dev) 39 return NULL; 40 dev->type = type; 41 dev->signal = ATM_PHY_SIG_UNKNOWN; 42 dev->link_rate = ATM_OC3_PCR; 43 44 return dev; 45 } 46 47 static struct atm_dev *__atm_dev_lookup(int number) 48 { 49 struct atm_dev *dev; 50 51 list_for_each_entry(dev, &atm_devs, dev_list) { 52 if (dev->number == number) { 53 atm_dev_hold(dev); 54 return dev; 55 } 56 } 57 return NULL; 58 } 59 60 struct atm_dev *atm_dev_lookup(int number) 61 { 62 struct atm_dev *dev; 63 64 mutex_lock(&atm_dev_mutex); 65 dev = __atm_dev_lookup(number); 66 mutex_unlock(&atm_dev_mutex); 67 return dev; 68 } 69 EXPORT_SYMBOL(atm_dev_lookup); 70 71 struct atm_dev *atm_dev_register(const char *type, struct device *parent, 72 const struct atmdev_ops *ops, int number, 73 unsigned long *flags) 74 { 75 struct atm_dev *dev, *inuse; 76 77 dev = __alloc_atm_dev(type); 78 if (!dev) { 79 pr_err("no space for dev %s\n", type); 80 return NULL; 81 } 82 mutex_lock(&atm_dev_mutex); 83 if (number != -1) { 84 inuse = __atm_dev_lookup(number); 85 if (inuse) { 86 atm_dev_put(inuse); 87 mutex_unlock(&atm_dev_mutex); 88 kfree(dev); 89 return NULL; 90 } 91 dev->number = number; 92 } else { 93 dev->number = 0; 94 while ((inuse = __atm_dev_lookup(dev->number))) { 95 atm_dev_put(inuse); 96 dev->number++; 97 } 98 } 99 100 dev->ops = ops; 101 if (flags) 102 dev->flags = *flags; 103 else 104 memset(&dev->flags, 0, sizeof(dev->flags)); 105 memset(&dev->stats, 0, sizeof(dev->stats)); 106 refcount_set(&dev->refcnt, 1); 107 108 if (atm_proc_dev_register(dev) < 0) { 109 pr_err("atm_proc_dev_register failed for dev %s\n", type); 110 mutex_unlock(&atm_dev_mutex); 111 kfree(dev); 112 return NULL; 113 } 114 115 if (atm_register_sysfs(dev, parent) < 0) { 116 pr_err("atm_register_sysfs failed for dev %s\n", type); 117 atm_proc_dev_deregister(dev); 118 goto out_fail; 119 } 120 121 list_add_tail(&dev->dev_list, &atm_devs); 122 123 out: 124 mutex_unlock(&atm_dev_mutex); 125 return dev; 126 127 out_fail: 128 put_device(&dev->class_dev); 129 dev = NULL; 130 goto out; 131 } 132 EXPORT_SYMBOL(atm_dev_register); 133 134 void atm_dev_deregister(struct atm_dev *dev) 135 { 136 BUG_ON(test_bit(ATM_DF_REMOVED, &dev->flags)); 137 set_bit(ATM_DF_REMOVED, &dev->flags); 138 139 /* 140 * if we remove current device from atm_devs list, new device 141 * with same number can appear, such we need deregister proc, 142 * release async all vccs and remove them from vccs list too 143 */ 144 mutex_lock(&atm_dev_mutex); 145 list_del(&dev->dev_list); 146 atm_dev_release_vccs(dev); 147 atm_unregister_sysfs(dev); 148 atm_proc_dev_deregister(dev); 149 mutex_unlock(&atm_dev_mutex); 150 151 atm_dev_put(dev); 152 } 153 EXPORT_SYMBOL(atm_dev_deregister); 154 155 static void copy_aal_stats(struct k_atm_aal_stats *from, 156 struct atm_aal_stats *to) 157 { 158 #define __HANDLE_ITEM(i) to->i = atomic_read(&from->i) 159 __AAL_STAT_ITEMS 160 #undef __HANDLE_ITEM 161 } 162 163 static void subtract_aal_stats(struct k_atm_aal_stats *from, 164 struct atm_aal_stats *to) 165 { 166 #define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i) 167 __AAL_STAT_ITEMS 168 #undef __HANDLE_ITEM 169 } 170 171 static int fetch_stats(struct atm_dev *dev, struct atm_dev_stats __user *arg, 172 int zero) 173 { 174 struct atm_dev_stats tmp; 175 int error = 0; 176 177 copy_aal_stats(&dev->stats.aal0, &tmp.aal0); 178 copy_aal_stats(&dev->stats.aal34, &tmp.aal34); 179 copy_aal_stats(&dev->stats.aal5, &tmp.aal5); 180 if (arg) 181 error = copy_to_user(arg, &tmp, sizeof(tmp)); 182 if (zero && !error) { 183 subtract_aal_stats(&dev->stats.aal0, &tmp.aal0); 184 subtract_aal_stats(&dev->stats.aal34, &tmp.aal34); 185 subtract_aal_stats(&dev->stats.aal5, &tmp.aal5); 186 } 187 return error ? -EFAULT : 0; 188 } 189 190 int atm_getnames(void __user *buf, int __user *iobuf_len) 191 { 192 int error, len, size = 0; 193 struct atm_dev *dev; 194 struct list_head *p; 195 int *tmp_buf, *tmp_p; 196 197 if (get_user(len, iobuf_len)) 198 return -EFAULT; 199 mutex_lock(&atm_dev_mutex); 200 list_for_each(p, &atm_devs) 201 size += sizeof(int); 202 if (size > len) { 203 mutex_unlock(&atm_dev_mutex); 204 return -E2BIG; 205 } 206 tmp_buf = kmalloc(size, GFP_ATOMIC); 207 if (!tmp_buf) { 208 mutex_unlock(&atm_dev_mutex); 209 return -ENOMEM; 210 } 211 tmp_p = tmp_buf; 212 list_for_each_entry(dev, &atm_devs, dev_list) { 213 *tmp_p++ = dev->number; 214 } 215 mutex_unlock(&atm_dev_mutex); 216 error = ((copy_to_user(buf, tmp_buf, size)) || 217 put_user(size, iobuf_len)) 218 ? -EFAULT : 0; 219 kfree(tmp_buf); 220 return error; 221 } 222 223 int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, 224 int number, int compat) 225 { 226 struct atm_dev *dev; 227 int error, size = 0; 228 229 dev = try_then_request_module(atm_dev_lookup(number), "atm-device-%d", 230 number); 231 if (!dev) 232 return -ENODEV; 233 234 switch (cmd) { 235 case ATM_GETTYPE: 236 size = strlen(dev->type) + 1; 237 if (copy_to_user(buf, dev->type, size)) { 238 error = -EFAULT; 239 goto done; 240 } 241 break; 242 case ATM_GETESI: 243 size = ESI_LEN; 244 if (copy_to_user(buf, dev->esi, size)) { 245 error = -EFAULT; 246 goto done; 247 } 248 break; 249 case ATM_SETESI: 250 { 251 int i; 252 253 for (i = 0; i < ESI_LEN; i++) 254 if (dev->esi[i]) { 255 error = -EEXIST; 256 goto done; 257 } 258 } 259 fallthrough; 260 case ATM_SETESIF: 261 { 262 unsigned char esi[ESI_LEN]; 263 264 if (!capable(CAP_NET_ADMIN)) { 265 error = -EPERM; 266 goto done; 267 } 268 if (copy_from_user(esi, buf, ESI_LEN)) { 269 error = -EFAULT; 270 goto done; 271 } 272 memcpy(dev->esi, esi, ESI_LEN); 273 error = ESI_LEN; 274 goto done; 275 } 276 case ATM_GETSTATZ: 277 if (!capable(CAP_NET_ADMIN)) { 278 error = -EPERM; 279 goto done; 280 } 281 fallthrough; 282 case ATM_GETSTAT: 283 size = sizeof(struct atm_dev_stats); 284 error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ); 285 if (error) 286 goto done; 287 break; 288 case ATM_GETCIRANGE: 289 size = sizeof(struct atm_cirange); 290 if (copy_to_user(buf, &dev->ci_range, size)) { 291 error = -EFAULT; 292 goto done; 293 } 294 break; 295 case ATM_GETLINKRATE: 296 size = sizeof(int); 297 if (copy_to_user(buf, &dev->link_rate, size)) { 298 error = -EFAULT; 299 goto done; 300 } 301 break; 302 case ATM_SETLOOP: 303 if (__ATM_LM_XTRMT((int) (unsigned long) buf) && 304 __ATM_LM_XTLOC((int) (unsigned long) buf) > 305 __ATM_LM_XTRMT((int) (unsigned long) buf)) { 306 error = -EINVAL; 307 goto done; 308 } 309 fallthrough; 310 case ATM_SETCIRANGE: 311 if (!capable(CAP_NET_ADMIN)) { 312 error = -EPERM; 313 goto done; 314 } 315 fallthrough; 316 default: 317 if (IS_ENABLED(CONFIG_COMPAT) && compat) { 318 #ifdef CONFIG_COMPAT 319 if (!dev->ops->compat_ioctl) { 320 error = -EINVAL; 321 goto done; 322 } 323 size = dev->ops->compat_ioctl(dev, cmd, buf); 324 #endif 325 } else { 326 if (!dev->ops->ioctl) { 327 error = -EINVAL; 328 goto done; 329 } 330 size = dev->ops->ioctl(dev, cmd, buf); 331 } 332 if (size < 0) { 333 error = (size == -ENOIOCTLCMD ? -ENOTTY : size); 334 goto done; 335 } 336 } 337 338 if (size) 339 error = put_user(size, sioc_len) ? -EFAULT : 0; 340 else 341 error = 0; 342 done: 343 atm_dev_put(dev); 344 return error; 345 } 346 347 #ifdef CONFIG_PROC_FS 348 void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) 349 { 350 mutex_lock(&atm_dev_mutex); 351 return seq_list_start_head(&atm_devs, *pos); 352 } 353 354 void atm_dev_seq_stop(struct seq_file *seq, void *v) 355 { 356 mutex_unlock(&atm_dev_mutex); 357 } 358 359 void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 360 { 361 return seq_list_next(v, &atm_devs, pos); 362 } 363 #endif 364