vhci_sysfs.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2003-2008 Takahiro Hirofuchi
  4. * Copyright (C) 2015-2016 Nobuo Iwata
  5. */
  6. #include <linux/kthread.h>
  7. #include <linux/file.h>
  8. #include <linux/net.h>
  9. #include <linux/platform_device.h>
  10. #include <linux/slab.h>
  11. #include "usbip_common.h"
  12. #include "vhci.h"
  13. /* TODO: refine locking ?*/
  14. /*
  15. * output example:
  16. * hub port sta spd dev sockfd local_busid
  17. * hs 0000 004 000 00000000 000003 1-2.3
  18. * ................................................
  19. * ss 0008 004 000 00000000 000004 2-3.4
  20. * ................................................
  21. *
  22. * Output includes socket fd instead of socket pointer address to avoid
  23. * leaking kernel memory address in:
  24. * /sys/devices/platform/vhci_hcd.0/status and in debug output.
  25. * The socket pointer address is not used at the moment and it was made
  26. * visible as a convenient way to find IP address from socket pointer
  27. * address by looking up /proc/net/{tcp,tcp6}. As this opens a security
  28. * hole, the change is made to use sockfd instead.
  29. *
  30. */
  31. static void port_show_vhci(char **out, int hub, int port, struct vhci_device *vdev)
  32. {
  33. if (hub == HUB_SPEED_HIGH)
  34. *out += sprintf(*out, "hs %04u %03u ",
  35. port, vdev->ud.status);
  36. else /* hub == HUB_SPEED_SUPER */
  37. *out += sprintf(*out, "ss %04u %03u ",
  38. port, vdev->ud.status);
  39. if (vdev->ud.status == VDEV_ST_USED) {
  40. *out += sprintf(*out, "%03u %08x ",
  41. vdev->speed, vdev->devid);
  42. *out += sprintf(*out, "%06u %s",
  43. vdev->ud.sockfd,
  44. dev_name(&vdev->udev->dev));
  45. } else {
  46. *out += sprintf(*out, "000 00000000 ");
  47. *out += sprintf(*out, "000000 0-0");
  48. }
  49. *out += sprintf(*out, "\n");
  50. }
  51. /* Sysfs entry to show port status */
  52. static ssize_t status_show_vhci(int pdev_nr, char *out)
  53. {
  54. struct platform_device *pdev = vhcis[pdev_nr].pdev;
  55. struct vhci *vhci;
  56. struct usb_hcd *hcd;
  57. struct vhci_hcd *vhci_hcd;
  58. char *s = out;
  59. int i;
  60. unsigned long flags;
  61. if (!pdev || !out) {
  62. usbip_dbg_vhci_sysfs("show status error\n");
  63. return 0;
  64. }
  65. hcd = platform_get_drvdata(pdev);
  66. vhci_hcd = hcd_to_vhci_hcd(hcd);
  67. vhci = vhci_hcd->vhci;
  68. spin_lock_irqsave(&vhci->lock, flags);
  69. for (i = 0; i < VHCI_HC_PORTS; i++) {
  70. struct vhci_device *vdev = &vhci->vhci_hcd_hs->vdev[i];
  71. spin_lock(&vdev->ud.lock);
  72. port_show_vhci(&out, HUB_SPEED_HIGH,
  73. pdev_nr * VHCI_PORTS + i, vdev);
  74. spin_unlock(&vdev->ud.lock);
  75. }
  76. for (i = 0; i < VHCI_HC_PORTS; i++) {
  77. struct vhci_device *vdev = &vhci->vhci_hcd_ss->vdev[i];
  78. spin_lock(&vdev->ud.lock);
  79. port_show_vhci(&out, HUB_SPEED_SUPER,
  80. pdev_nr * VHCI_PORTS + VHCI_HC_PORTS + i, vdev);
  81. spin_unlock(&vdev->ud.lock);
  82. }
  83. spin_unlock_irqrestore(&vhci->lock, flags);
  84. return out - s;
  85. }
  86. static ssize_t status_show_not_ready(int pdev_nr, char *out)
  87. {
  88. char *s = out;
  89. int i = 0;
  90. for (i = 0; i < VHCI_HC_PORTS; i++) {
  91. out += sprintf(out, "hs %04u %03u ",
  92. (pdev_nr * VHCI_PORTS) + i,
  93. VDEV_ST_NOTASSIGNED);
  94. out += sprintf(out, "000 00000000 0000000000000000 0-0");
  95. out += sprintf(out, "\n");
  96. }
  97. for (i = 0; i < VHCI_HC_PORTS; i++) {
  98. out += sprintf(out, "ss %04u %03u ",
  99. (pdev_nr * VHCI_PORTS) + VHCI_HC_PORTS + i,
  100. VDEV_ST_NOTASSIGNED);
  101. out += sprintf(out, "000 00000000 0000000000000000 0-0");
  102. out += sprintf(out, "\n");
  103. }
  104. return out - s;
  105. }
  106. static int status_name_to_id(const char *name)
  107. {
  108. char *c;
  109. long val;
  110. int ret;
  111. c = strchr(name, '.');
  112. if (c == NULL)
  113. return 0;
  114. ret = kstrtol(c+1, 10, &val);
  115. if (ret < 0)
  116. return ret;
  117. return val;
  118. }
  119. static ssize_t status_show(struct device *dev,
  120. struct device_attribute *attr, char *out)
  121. {
  122. char *s = out;
  123. int pdev_nr;
  124. out += sprintf(out,
  125. "hub port sta spd dev sockfd local_busid\n");
  126. pdev_nr = status_name_to_id(attr->attr.name);
  127. if (pdev_nr < 0)
  128. out += status_show_not_ready(pdev_nr, out);
  129. else
  130. out += status_show_vhci(pdev_nr, out);
  131. return out - s;
  132. }
  133. static ssize_t nports_show(struct device *dev, struct device_attribute *attr,
  134. char *out)
  135. {
  136. char *s = out;
  137. /*
  138. * Half the ports are for SPEED_HIGH and half for SPEED_SUPER,
  139. * thus the * 2.
  140. */
  141. out += sprintf(out, "%d\n", VHCI_PORTS * vhci_num_controllers);
  142. return out - s;
  143. }
  144. static DEVICE_ATTR_RO(nports);
  145. /* Sysfs entry to shutdown a virtual connection */
  146. static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport)
  147. {
  148. struct vhci_device *vdev = &vhci_hcd->vdev[rhport];
  149. struct vhci *vhci = vhci_hcd->vhci;
  150. unsigned long flags;
  151. usbip_dbg_vhci_sysfs("enter\n");
  152. /* lock */
  153. spin_lock_irqsave(&vhci->lock, flags);
  154. spin_lock(&vdev->ud.lock);
  155. if (vdev->ud.status == VDEV_ST_NULL) {
  156. pr_err("not connected %d\n", vdev->ud.status);
  157. /* unlock */
  158. spin_unlock(&vdev->ud.lock);
  159. spin_unlock_irqrestore(&vhci->lock, flags);
  160. return -EINVAL;
  161. }
  162. /* unlock */
  163. spin_unlock(&vdev->ud.lock);
  164. spin_unlock_irqrestore(&vhci->lock, flags);
  165. usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
  166. return 0;
  167. }
  168. static int valid_port(__u32 pdev_nr, __u32 rhport)
  169. {
  170. if (pdev_nr >= vhci_num_controllers) {
  171. pr_err("pdev %u\n", pdev_nr);
  172. return 0;
  173. }
  174. if (rhport >= VHCI_HC_PORTS) {
  175. pr_err("rhport %u\n", rhport);
  176. return 0;
  177. }
  178. return 1;
  179. }
  180. static ssize_t detach_store(struct device *dev, struct device_attribute *attr,
  181. const char *buf, size_t count)
  182. {
  183. __u32 port = 0, pdev_nr = 0, rhport = 0;
  184. struct usb_hcd *hcd;
  185. struct vhci_hcd *vhci_hcd;
  186. int ret;
  187. if (kstrtoint(buf, 10, &port) < 0)
  188. return -EINVAL;
  189. pdev_nr = port_to_pdev_nr(port);
  190. rhport = port_to_rhport(port);
  191. if (!valid_port(pdev_nr, rhport))
  192. return -EINVAL;
  193. hcd = platform_get_drvdata(vhcis[pdev_nr].pdev);
  194. if (hcd == NULL) {
  195. dev_err(dev, "port is not ready %u\n", port);
  196. return -EAGAIN;
  197. }
  198. usbip_dbg_vhci_sysfs("rhport %d\n", rhport);
  199. if ((port / VHCI_HC_PORTS) % 2)
  200. vhci_hcd = hcd_to_vhci_hcd(hcd)->vhci->vhci_hcd_ss;
  201. else
  202. vhci_hcd = hcd_to_vhci_hcd(hcd)->vhci->vhci_hcd_hs;
  203. ret = vhci_port_disconnect(vhci_hcd, rhport);
  204. if (ret < 0)
  205. return -EINVAL;
  206. usbip_dbg_vhci_sysfs("Leave\n");
  207. return count;
  208. }
  209. static DEVICE_ATTR_WO(detach);
  210. static int valid_args(__u32 pdev_nr, __u32 rhport, enum usb_device_speed speed)
  211. {
  212. if (!valid_port(pdev_nr, rhport)) {
  213. return 0;
  214. }
  215. switch (speed) {
  216. case USB_SPEED_LOW:
  217. case USB_SPEED_FULL:
  218. case USB_SPEED_HIGH:
  219. case USB_SPEED_WIRELESS:
  220. case USB_SPEED_SUPER:
  221. break;
  222. default:
  223. pr_err("Failed attach request for unsupported USB speed: %s\n",
  224. usb_speed_string(speed));
  225. return 0;
  226. }
  227. return 1;
  228. }
  229. /* Sysfs entry to establish a virtual connection */
  230. /*
  231. * To start a new USB/IP attachment, a userland program needs to setup a TCP
  232. * connection and then write its socket descriptor with remote device
  233. * information into this sysfs file.
  234. *
  235. * A remote device is virtually attached to the root-hub port of @rhport with
  236. * @speed. @devid is embedded into a request to specify the remote device in a
  237. * server host.
  238. *
  239. * write() returns 0 on success, else negative errno.
  240. */
  241. static ssize_t attach_store(struct device *dev, struct device_attribute *attr,
  242. const char *buf, size_t count)
  243. {
  244. struct socket *socket;
  245. int sockfd = 0;
  246. __u32 port = 0, pdev_nr = 0, rhport = 0, devid = 0, speed = 0;
  247. struct usb_hcd *hcd;
  248. struct vhci_hcd *vhci_hcd;
  249. struct vhci_device *vdev;
  250. struct vhci *vhci;
  251. int err;
  252. unsigned long flags;
  253. /*
  254. * @rhport: port number of vhci_hcd
  255. * @sockfd: socket descriptor of an established TCP connection
  256. * @devid: unique device identifier in a remote host
  257. * @speed: usb device speed in a remote host
  258. */
  259. if (sscanf(buf, "%u %u %u %u", &port, &sockfd, &devid, &speed) != 4)
  260. return -EINVAL;
  261. pdev_nr = port_to_pdev_nr(port);
  262. rhport = port_to_rhport(port);
  263. usbip_dbg_vhci_sysfs("port(%u) pdev(%d) rhport(%u)\n",
  264. port, pdev_nr, rhport);
  265. usbip_dbg_vhci_sysfs("sockfd(%u) devid(%u) speed(%u)\n",
  266. sockfd, devid, speed);
  267. /* check received parameters */
  268. if (!valid_args(pdev_nr, rhport, speed))
  269. return -EINVAL;
  270. hcd = platform_get_drvdata(vhcis[pdev_nr].pdev);
  271. if (hcd == NULL) {
  272. dev_err(dev, "port %d is not ready\n", port);
  273. return -EAGAIN;
  274. }
  275. vhci_hcd = hcd_to_vhci_hcd(hcd);
  276. vhci = vhci_hcd->vhci;
  277. if (speed == USB_SPEED_SUPER)
  278. vdev = &vhci->vhci_hcd_ss->vdev[rhport];
  279. else
  280. vdev = &vhci->vhci_hcd_hs->vdev[rhport];
  281. /* Extract socket from fd. */
  282. socket = sockfd_lookup(sockfd, &err);
  283. if (!socket)
  284. return -EINVAL;
  285. /* now need lock until setting vdev status as used */
  286. /* begin a lock */
  287. spin_lock_irqsave(&vhci->lock, flags);
  288. spin_lock(&vdev->ud.lock);
  289. if (vdev->ud.status != VDEV_ST_NULL) {
  290. /* end of the lock */
  291. spin_unlock(&vdev->ud.lock);
  292. spin_unlock_irqrestore(&vhci->lock, flags);
  293. sockfd_put(socket);
  294. dev_err(dev, "port %d already used\n", rhport);
  295. /*
  296. * Will be retried from userspace
  297. * if there's another free port.
  298. */
  299. return -EBUSY;
  300. }
  301. dev_info(dev, "pdev(%u) rhport(%u) sockfd(%d)\n",
  302. pdev_nr, rhport, sockfd);
  303. dev_info(dev, "devid(%u) speed(%u) speed_str(%s)\n",
  304. devid, speed, usb_speed_string(speed));
  305. vdev->devid = devid;
  306. vdev->speed = speed;
  307. vdev->ud.sockfd = sockfd;
  308. vdev->ud.tcp_socket = socket;
  309. vdev->ud.status = VDEV_ST_NOTASSIGNED;
  310. spin_unlock(&vdev->ud.lock);
  311. spin_unlock_irqrestore(&vhci->lock, flags);
  312. /* end the lock */
  313. vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
  314. vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
  315. rh_port_connect(vdev, speed);
  316. return count;
  317. }
  318. static DEVICE_ATTR_WO(attach);
  319. #define MAX_STATUS_NAME 16
  320. struct status_attr {
  321. struct device_attribute attr;
  322. char name[MAX_STATUS_NAME+1];
  323. };
  324. static struct status_attr *status_attrs;
  325. static void set_status_attr(int id)
  326. {
  327. struct status_attr *status;
  328. status = status_attrs + id;
  329. if (id == 0)
  330. strcpy(status->name, "status");
  331. else
  332. snprintf(status->name, MAX_STATUS_NAME+1, "status.%d", id);
  333. status->attr.attr.name = status->name;
  334. status->attr.attr.mode = S_IRUGO;
  335. status->attr.show = status_show;
  336. sysfs_attr_init(&status->attr.attr);
  337. }
  338. static int init_status_attrs(void)
  339. {
  340. int id;
  341. status_attrs = kcalloc(vhci_num_controllers, sizeof(struct status_attr),
  342. GFP_KERNEL);
  343. if (status_attrs == NULL)
  344. return -ENOMEM;
  345. for (id = 0; id < vhci_num_controllers; id++)
  346. set_status_attr(id);
  347. return 0;
  348. }
  349. static void finish_status_attrs(void)
  350. {
  351. kfree(status_attrs);
  352. }
  353. struct attribute_group vhci_attr_group = {
  354. .attrs = NULL,
  355. };
  356. int vhci_init_attr_group(void)
  357. {
  358. struct attribute **attrs;
  359. int ret, i;
  360. attrs = kcalloc((vhci_num_controllers + 5), sizeof(struct attribute *),
  361. GFP_KERNEL);
  362. if (attrs == NULL)
  363. return -ENOMEM;
  364. ret = init_status_attrs();
  365. if (ret) {
  366. kfree(attrs);
  367. return ret;
  368. }
  369. *attrs = &dev_attr_nports.attr;
  370. *(attrs + 1) = &dev_attr_detach.attr;
  371. *(attrs + 2) = &dev_attr_attach.attr;
  372. *(attrs + 3) = &dev_attr_usbip_debug.attr;
  373. for (i = 0; i < vhci_num_controllers; i++)
  374. *(attrs + i + 4) = &((status_attrs + i)->attr.attr);
  375. vhci_attr_group.attrs = attrs;
  376. return 0;
  377. }
  378. void vhci_finish_attr_group(void)
  379. {
  380. finish_status_attrs();
  381. kfree(vhci_attr_group.attrs);
  382. }