/net/atm/ioctl.c

http://github.com/mirrors/linux · C · 354 lines · 289 code · 41 blank · 24 comment · 33 complexity · 32df8934759110f231730fa0bba2896d MD5 · raw file

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