.. | .. |
---|
17 | 17 | #include <linux/blkdev.h> |
---|
18 | 18 | #include <linux/pagemap.h> |
---|
19 | 19 | #include <linux/export.h> |
---|
| 20 | +#include <linux/fs_parser.h> |
---|
20 | 21 | #include <linux/hid.h> |
---|
| 22 | +#include <linux/mm.h> |
---|
21 | 23 | #include <linux/module.h> |
---|
| 24 | +#include <linux/scatterlist.h> |
---|
22 | 25 | #include <linux/sched/signal.h> |
---|
23 | 26 | #include <linux/uio.h> |
---|
| 27 | +#include <linux/vmalloc.h> |
---|
24 | 28 | #include <asm/unaligned.h> |
---|
25 | 29 | |
---|
| 30 | +#include <linux/usb/ccid.h> |
---|
26 | 31 | #include <linux/usb/composite.h> |
---|
27 | 32 | #include <linux/usb/functionfs.h> |
---|
28 | 33 | |
---|
29 | 34 | #include <linux/aio.h> |
---|
30 | | -#include <linux/mmu_context.h> |
---|
| 35 | +#include <linux/kthread.h> |
---|
31 | 36 | #include <linux/poll.h> |
---|
32 | 37 | #include <linux/eventfd.h> |
---|
33 | 38 | |
---|
.. | .. |
---|
117 | 122 | struct usb_endpoint_descriptor *descs[3]; |
---|
118 | 123 | |
---|
119 | 124 | u8 num; |
---|
120 | | - |
---|
121 | | - int status; /* P: epfile->mutex */ |
---|
122 | 125 | }; |
---|
123 | 126 | |
---|
124 | 127 | struct ffs_epfile { |
---|
.. | .. |
---|
218 | 221 | |
---|
219 | 222 | struct usb_ep *ep; |
---|
220 | 223 | struct usb_request *req; |
---|
| 224 | + struct sg_table sgt; |
---|
| 225 | + bool use_sg; |
---|
221 | 226 | |
---|
222 | 227 | struct ffs_data *ffs; |
---|
| 228 | + |
---|
| 229 | + int status; |
---|
| 230 | + struct completion done; |
---|
223 | 231 | }; |
---|
224 | 232 | |
---|
225 | 233 | struct ffs_desc_helper { |
---|
.. | .. |
---|
270 | 278 | { |
---|
271 | 279 | struct usb_request *req = ffs->ep0req; |
---|
272 | 280 | int ret; |
---|
| 281 | + |
---|
| 282 | + if (!req) { |
---|
| 283 | + spin_unlock_irq(&ffs->ev.waitq.lock); |
---|
| 284 | + return -EINVAL; |
---|
| 285 | + } |
---|
273 | 286 | |
---|
274 | 287 | req->zero = len < le16_to_cpu(ffs->ev.setup.wLength); |
---|
275 | 288 | |
---|
.. | .. |
---|
561 | 574 | spin_unlock_irq(&ffs->ev.waitq.lock); |
---|
562 | 575 | |
---|
563 | 576 | if (likely(len)) { |
---|
564 | | - data = kmalloc(len, GFP_KERNEL); |
---|
| 577 | + data = kmalloc(ALIGN(len, cache_line_size()), GFP_KERNEL); |
---|
565 | 578 | if (unlikely(!data)) { |
---|
566 | 579 | ret = -ENOMEM; |
---|
567 | 580 | goto done_mutex; |
---|
.. | .. |
---|
698 | 711 | |
---|
699 | 712 | static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req) |
---|
700 | 713 | { |
---|
| 714 | + struct ffs_io_data *io_data = req->context; |
---|
| 715 | + |
---|
701 | 716 | ENTER(); |
---|
702 | | - if (likely(req->context)) { |
---|
703 | | - struct ffs_ep *ep = _ep->driver_data; |
---|
704 | | - ep->status = req->status ? req->status : req->actual; |
---|
705 | | - complete(req->context); |
---|
706 | | - } |
---|
| 717 | + if (req->status) |
---|
| 718 | + io_data->status = req->status; |
---|
| 719 | + else |
---|
| 720 | + io_data->status = req->actual; |
---|
| 721 | + |
---|
| 722 | + complete(&io_data->done); |
---|
707 | 723 | } |
---|
708 | 724 | |
---|
709 | 725 | static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter) |
---|
.. | .. |
---|
749 | 765 | return ret; |
---|
750 | 766 | } |
---|
751 | 767 | |
---|
| 768 | +/* |
---|
| 769 | + * allocate a virtually contiguous buffer and create a scatterlist describing it |
---|
| 770 | + * @sg_table - pointer to a place to be filled with sg_table contents |
---|
| 771 | + * @size - required buffer size |
---|
| 772 | + */ |
---|
| 773 | +static void *ffs_build_sg_list(struct sg_table *sgt, size_t sz) |
---|
| 774 | +{ |
---|
| 775 | + struct page **pages; |
---|
| 776 | + void *vaddr, *ptr; |
---|
| 777 | + unsigned int n_pages; |
---|
| 778 | + int i; |
---|
| 779 | + |
---|
| 780 | + vaddr = vmalloc(sz); |
---|
| 781 | + if (!vaddr) |
---|
| 782 | + return NULL; |
---|
| 783 | + |
---|
| 784 | + n_pages = PAGE_ALIGN(sz) >> PAGE_SHIFT; |
---|
| 785 | + pages = kvmalloc_array(n_pages, sizeof(struct page *), GFP_KERNEL); |
---|
| 786 | + if (!pages) { |
---|
| 787 | + vfree(vaddr); |
---|
| 788 | + |
---|
| 789 | + return NULL; |
---|
| 790 | + } |
---|
| 791 | + for (i = 0, ptr = vaddr; i < n_pages; ++i, ptr += PAGE_SIZE) |
---|
| 792 | + pages[i] = vmalloc_to_page(ptr); |
---|
| 793 | + |
---|
| 794 | + if (sg_alloc_table_from_pages(sgt, pages, n_pages, 0, sz, GFP_KERNEL)) { |
---|
| 795 | + kvfree(pages); |
---|
| 796 | + vfree(vaddr); |
---|
| 797 | + |
---|
| 798 | + return NULL; |
---|
| 799 | + } |
---|
| 800 | + kvfree(pages); |
---|
| 801 | + |
---|
| 802 | + return vaddr; |
---|
| 803 | +} |
---|
| 804 | + |
---|
| 805 | +static inline void *ffs_alloc_buffer(struct ffs_io_data *io_data, |
---|
| 806 | + size_t data_len) |
---|
| 807 | +{ |
---|
| 808 | + if (io_data->use_sg) |
---|
| 809 | + return ffs_build_sg_list(&io_data->sgt, data_len); |
---|
| 810 | + |
---|
| 811 | + return kmalloc(ALIGN(data_len, cache_line_size()), GFP_KERNEL); |
---|
| 812 | +} |
---|
| 813 | + |
---|
| 814 | +static inline void ffs_free_buffer(struct ffs_io_data *io_data) |
---|
| 815 | +{ |
---|
| 816 | + if (!io_data->buf) |
---|
| 817 | + return; |
---|
| 818 | + |
---|
| 819 | + if (io_data->use_sg) { |
---|
| 820 | + sg_free_table(&io_data->sgt); |
---|
| 821 | + vfree(io_data->buf); |
---|
| 822 | + } else { |
---|
| 823 | + kfree(io_data->buf); |
---|
| 824 | + } |
---|
| 825 | +} |
---|
| 826 | + |
---|
752 | 827 | static void ffs_user_copy_worker(struct work_struct *work) |
---|
753 | 828 | { |
---|
754 | 829 | struct ffs_io_data *io_data = container_of(work, struct ffs_io_data, |
---|
.. | .. |
---|
758 | 833 | bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD; |
---|
759 | 834 | |
---|
760 | 835 | if (io_data->read && ret > 0) { |
---|
761 | | - mm_segment_t oldfs = get_fs(); |
---|
762 | | - |
---|
763 | | - set_fs(USER_DS); |
---|
764 | | - use_mm(io_data->mm); |
---|
| 836 | + kthread_use_mm(io_data->mm); |
---|
765 | 837 | ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data); |
---|
766 | | - unuse_mm(io_data->mm); |
---|
767 | | - set_fs(oldfs); |
---|
| 838 | + kthread_unuse_mm(io_data->mm); |
---|
768 | 839 | } |
---|
769 | 840 | |
---|
770 | 841 | io_data->kiocb->ki_complete(io_data->kiocb, ret, ret); |
---|
.. | .. |
---|
776 | 847 | |
---|
777 | 848 | if (io_data->read) |
---|
778 | 849 | kfree(io_data->to_free); |
---|
779 | | - kfree(io_data->buf); |
---|
| 850 | + ffs_free_buffer(io_data); |
---|
780 | 851 | kfree(io_data); |
---|
781 | 852 | } |
---|
782 | 853 | |
---|
.. | .. |
---|
946 | 1017 | */ |
---|
947 | 1018 | if (io_data->read) |
---|
948 | 1019 | data_len = usb_ep_align_maybe(gadget, ep->ep, data_len); |
---|
| 1020 | + |
---|
| 1021 | + io_data->use_sg = gadget->sg_supported && data_len > PAGE_SIZE; |
---|
949 | 1022 | spin_unlock_irq(&epfile->ffs->eps_lock); |
---|
950 | 1023 | |
---|
951 | | - data = kmalloc(data_len, GFP_KERNEL); |
---|
| 1024 | + data = ffs_alloc_buffer(io_data, data_len); |
---|
952 | 1025 | if (unlikely(!data)) { |
---|
953 | 1026 | ret = -ENOMEM; |
---|
954 | 1027 | goto error_mutex; |
---|
.. | .. |
---|
984 | 1057 | WARN(1, "%s: data_len == -EINVAL\n", __func__); |
---|
985 | 1058 | ret = -EINVAL; |
---|
986 | 1059 | } else if (!io_data->aio) { |
---|
987 | | - DECLARE_COMPLETION_ONSTACK(done); |
---|
988 | 1060 | bool interrupted = false; |
---|
989 | 1061 | |
---|
990 | 1062 | req = ep->req; |
---|
991 | | - req->buf = data; |
---|
992 | | - req->length = data_len; |
---|
| 1063 | + if (io_data->use_sg) { |
---|
| 1064 | + req->buf = NULL; |
---|
| 1065 | + req->sg = io_data->sgt.sgl; |
---|
| 1066 | + req->num_sgs = io_data->sgt.nents; |
---|
| 1067 | + } else { |
---|
| 1068 | + req->buf = data; |
---|
| 1069 | + req->num_sgs = 0; |
---|
| 1070 | + } |
---|
| 1071 | + req->length = data_len; |
---|
993 | 1072 | |
---|
994 | | - req->context = &done; |
---|
| 1073 | + io_data->buf = data; |
---|
| 1074 | + |
---|
| 1075 | + init_completion(&io_data->done); |
---|
| 1076 | + req->context = io_data; |
---|
995 | 1077 | req->complete = ffs_epfile_io_complete; |
---|
996 | 1078 | |
---|
997 | 1079 | ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); |
---|
.. | .. |
---|
1000 | 1082 | |
---|
1001 | 1083 | spin_unlock_irq(&epfile->ffs->eps_lock); |
---|
1002 | 1084 | |
---|
1003 | | - if (unlikely(wait_for_completion_interruptible(&done))) { |
---|
| 1085 | + if (unlikely(wait_for_completion_interruptible(&io_data->done))) { |
---|
| 1086 | + spin_lock_irq(&epfile->ffs->eps_lock); |
---|
| 1087 | + if (epfile->ep != ep) { |
---|
| 1088 | + ret = -ESHUTDOWN; |
---|
| 1089 | + goto error_lock; |
---|
| 1090 | + } |
---|
1004 | 1091 | /* |
---|
1005 | 1092 | * To avoid race condition with ffs_epfile_io_complete, |
---|
1006 | 1093 | * dequeue the request first then check |
---|
.. | .. |
---|
1008 | 1095 | * condition with req->complete callback. |
---|
1009 | 1096 | */ |
---|
1010 | 1097 | usb_ep_dequeue(ep->ep, req); |
---|
1011 | | - wait_for_completion(&done); |
---|
1012 | | - interrupted = ep->status < 0; |
---|
| 1098 | + spin_unlock_irq(&epfile->ffs->eps_lock); |
---|
| 1099 | + wait_for_completion(&io_data->done); |
---|
| 1100 | + interrupted = io_data->status < 0; |
---|
1013 | 1101 | } |
---|
1014 | 1102 | |
---|
1015 | 1103 | if (interrupted) |
---|
1016 | 1104 | ret = -EINTR; |
---|
1017 | | - else if (io_data->read && ep->status > 0) |
---|
1018 | | - ret = __ffs_epfile_read_data(epfile, data, ep->status, |
---|
| 1105 | + else if (io_data->read && io_data->status > 0) |
---|
| 1106 | + ret = __ffs_epfile_read_data(epfile, data, io_data->status, |
---|
1019 | 1107 | &io_data->data); |
---|
1020 | 1108 | else |
---|
1021 | | - ret = ep->status; |
---|
| 1109 | + ret = io_data->status; |
---|
1022 | 1110 | goto error_mutex; |
---|
1023 | 1111 | } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) { |
---|
1024 | 1112 | ret = -ENOMEM; |
---|
1025 | 1113 | } else { |
---|
1026 | | - req->buf = data; |
---|
1027 | | - req->length = data_len; |
---|
| 1114 | + if (io_data->use_sg) { |
---|
| 1115 | + req->buf = NULL; |
---|
| 1116 | + req->sg = io_data->sgt.sgl; |
---|
| 1117 | + req->num_sgs = io_data->sgt.nents; |
---|
| 1118 | + } else { |
---|
| 1119 | + req->buf = data; |
---|
| 1120 | + req->num_sgs = 0; |
---|
| 1121 | + } |
---|
| 1122 | + req->length = data_len; |
---|
1028 | 1123 | |
---|
1029 | 1124 | io_data->buf = data; |
---|
1030 | 1125 | io_data->ep = ep->ep; |
---|
.. | .. |
---|
1054 | 1149 | error_mutex: |
---|
1055 | 1150 | mutex_unlock(&epfile->mutex); |
---|
1056 | 1151 | error: |
---|
1057 | | - kfree(data); |
---|
| 1152 | + if (ret != -EIOCBQUEUED) /* don't free if there is iocb queued */ |
---|
| 1153 | + ffs_free_buffer(io_data); |
---|
1058 | 1154 | return ret; |
---|
1059 | 1155 | } |
---|
1060 | 1156 | |
---|
.. | .. |
---|
1274 | 1370 | return ret; |
---|
1275 | 1371 | } |
---|
1276 | 1372 | |
---|
1277 | | -#ifdef CONFIG_COMPAT |
---|
1278 | | -static long ffs_epfile_compat_ioctl(struct file *file, unsigned code, |
---|
1279 | | - unsigned long value) |
---|
1280 | | -{ |
---|
1281 | | - return ffs_epfile_ioctl(file, code, value); |
---|
1282 | | -} |
---|
1283 | | -#endif |
---|
1284 | | - |
---|
1285 | 1373 | static const struct file_operations ffs_epfile_operations = { |
---|
1286 | 1374 | .llseek = no_llseek, |
---|
1287 | 1375 | |
---|
.. | .. |
---|
1290 | 1378 | .read_iter = ffs_epfile_read_iter, |
---|
1291 | 1379 | .release = ffs_epfile_release, |
---|
1292 | 1380 | .unlocked_ioctl = ffs_epfile_ioctl, |
---|
1293 | | -#ifdef CONFIG_COMPAT |
---|
1294 | | - .compat_ioctl = ffs_epfile_compat_ioctl, |
---|
1295 | | -#endif |
---|
| 1381 | + .compat_ioctl = compat_ptr_ioctl, |
---|
1296 | 1382 | }; |
---|
1297 | 1383 | |
---|
1298 | 1384 | |
---|
.. | .. |
---|
1374 | 1460 | struct ffs_data *ffs_data; |
---|
1375 | 1461 | }; |
---|
1376 | 1462 | |
---|
1377 | | -static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) |
---|
| 1463 | +static int ffs_sb_fill(struct super_block *sb, struct fs_context *fc) |
---|
1378 | 1464 | { |
---|
1379 | | - struct ffs_sb_fill_data *data = _data; |
---|
| 1465 | + struct ffs_sb_fill_data *data = fc->fs_private; |
---|
1380 | 1466 | struct inode *inode; |
---|
1381 | 1467 | struct ffs_data *ffs = data->ffs_data; |
---|
1382 | 1468 | |
---|
.. | .. |
---|
1409 | 1495 | return 0; |
---|
1410 | 1496 | } |
---|
1411 | 1497 | |
---|
1412 | | -static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts) |
---|
| 1498 | +enum { |
---|
| 1499 | + Opt_no_disconnect, |
---|
| 1500 | + Opt_rmode, |
---|
| 1501 | + Opt_fmode, |
---|
| 1502 | + Opt_mode, |
---|
| 1503 | + Opt_uid, |
---|
| 1504 | + Opt_gid, |
---|
| 1505 | +}; |
---|
| 1506 | + |
---|
| 1507 | +static const struct fs_parameter_spec ffs_fs_fs_parameters[] = { |
---|
| 1508 | + fsparam_bool ("no_disconnect", Opt_no_disconnect), |
---|
| 1509 | + fsparam_u32 ("rmode", Opt_rmode), |
---|
| 1510 | + fsparam_u32 ("fmode", Opt_fmode), |
---|
| 1511 | + fsparam_u32 ("mode", Opt_mode), |
---|
| 1512 | + fsparam_u32 ("uid", Opt_uid), |
---|
| 1513 | + fsparam_u32 ("gid", Opt_gid), |
---|
| 1514 | + {} |
---|
| 1515 | +}; |
---|
| 1516 | + |
---|
| 1517 | +static int ffs_fs_parse_param(struct fs_context *fc, struct fs_parameter *param) |
---|
1413 | 1518 | { |
---|
| 1519 | + struct ffs_sb_fill_data *data = fc->fs_private; |
---|
| 1520 | + struct fs_parse_result result; |
---|
| 1521 | + int opt; |
---|
| 1522 | + |
---|
1414 | 1523 | ENTER(); |
---|
1415 | 1524 | |
---|
1416 | | - if (!opts || !*opts) |
---|
1417 | | - return 0; |
---|
| 1525 | + opt = fs_parse(fc, ffs_fs_fs_parameters, param, &result); |
---|
| 1526 | + if (opt < 0) |
---|
| 1527 | + return opt; |
---|
1418 | 1528 | |
---|
1419 | | - for (;;) { |
---|
1420 | | - unsigned long value; |
---|
1421 | | - char *eq, *comma; |
---|
| 1529 | + switch (opt) { |
---|
| 1530 | + case Opt_no_disconnect: |
---|
| 1531 | + data->no_disconnect = result.boolean; |
---|
| 1532 | + break; |
---|
| 1533 | + case Opt_rmode: |
---|
| 1534 | + data->root_mode = (result.uint_32 & 0555) | S_IFDIR; |
---|
| 1535 | + break; |
---|
| 1536 | + case Opt_fmode: |
---|
| 1537 | + data->perms.mode = (result.uint_32 & 0666) | S_IFREG; |
---|
| 1538 | + break; |
---|
| 1539 | + case Opt_mode: |
---|
| 1540 | + data->root_mode = (result.uint_32 & 0555) | S_IFDIR; |
---|
| 1541 | + data->perms.mode = (result.uint_32 & 0666) | S_IFREG; |
---|
| 1542 | + break; |
---|
1422 | 1543 | |
---|
1423 | | - /* Option limit */ |
---|
1424 | | - comma = strchr(opts, ','); |
---|
1425 | | - if (comma) |
---|
1426 | | - *comma = 0; |
---|
| 1544 | + case Opt_uid: |
---|
| 1545 | + data->perms.uid = make_kuid(current_user_ns(), result.uint_32); |
---|
| 1546 | + if (!uid_valid(data->perms.uid)) |
---|
| 1547 | + goto unmapped_value; |
---|
| 1548 | + break; |
---|
| 1549 | + case Opt_gid: |
---|
| 1550 | + data->perms.gid = make_kgid(current_user_ns(), result.uint_32); |
---|
| 1551 | + if (!gid_valid(data->perms.gid)) |
---|
| 1552 | + goto unmapped_value; |
---|
| 1553 | + break; |
---|
1427 | 1554 | |
---|
1428 | | - /* Value limit */ |
---|
1429 | | - eq = strchr(opts, '='); |
---|
1430 | | - if (unlikely(!eq)) { |
---|
1431 | | - pr_err("'=' missing in %s\n", opts); |
---|
1432 | | - return -EINVAL; |
---|
1433 | | - } |
---|
1434 | | - *eq = 0; |
---|
1435 | | - |
---|
1436 | | - /* Parse value */ |
---|
1437 | | - if (kstrtoul(eq + 1, 0, &value)) { |
---|
1438 | | - pr_err("%s: invalid value: %s\n", opts, eq + 1); |
---|
1439 | | - return -EINVAL; |
---|
1440 | | - } |
---|
1441 | | - |
---|
1442 | | - /* Interpret option */ |
---|
1443 | | - switch (eq - opts) { |
---|
1444 | | - case 13: |
---|
1445 | | - if (!memcmp(opts, "no_disconnect", 13)) |
---|
1446 | | - data->no_disconnect = !!value; |
---|
1447 | | - else |
---|
1448 | | - goto invalid; |
---|
1449 | | - break; |
---|
1450 | | - case 5: |
---|
1451 | | - if (!memcmp(opts, "rmode", 5)) |
---|
1452 | | - data->root_mode = (value & 0555) | S_IFDIR; |
---|
1453 | | - else if (!memcmp(opts, "fmode", 5)) |
---|
1454 | | - data->perms.mode = (value & 0666) | S_IFREG; |
---|
1455 | | - else |
---|
1456 | | - goto invalid; |
---|
1457 | | - break; |
---|
1458 | | - |
---|
1459 | | - case 4: |
---|
1460 | | - if (!memcmp(opts, "mode", 4)) { |
---|
1461 | | - data->root_mode = (value & 0555) | S_IFDIR; |
---|
1462 | | - data->perms.mode = (value & 0666) | S_IFREG; |
---|
1463 | | - } else { |
---|
1464 | | - goto invalid; |
---|
1465 | | - } |
---|
1466 | | - break; |
---|
1467 | | - |
---|
1468 | | - case 3: |
---|
1469 | | - if (!memcmp(opts, "uid", 3)) { |
---|
1470 | | - data->perms.uid = make_kuid(current_user_ns(), value); |
---|
1471 | | - if (!uid_valid(data->perms.uid)) { |
---|
1472 | | - pr_err("%s: unmapped value: %lu\n", opts, value); |
---|
1473 | | - return -EINVAL; |
---|
1474 | | - } |
---|
1475 | | - } else if (!memcmp(opts, "gid", 3)) { |
---|
1476 | | - data->perms.gid = make_kgid(current_user_ns(), value); |
---|
1477 | | - if (!gid_valid(data->perms.gid)) { |
---|
1478 | | - pr_err("%s: unmapped value: %lu\n", opts, value); |
---|
1479 | | - return -EINVAL; |
---|
1480 | | - } |
---|
1481 | | - } else { |
---|
1482 | | - goto invalid; |
---|
1483 | | - } |
---|
1484 | | - break; |
---|
1485 | | - |
---|
1486 | | - default: |
---|
1487 | | -invalid: |
---|
1488 | | - pr_err("%s: invalid option\n", opts); |
---|
1489 | | - return -EINVAL; |
---|
1490 | | - } |
---|
1491 | | - |
---|
1492 | | - /* Next iteration */ |
---|
1493 | | - if (!comma) |
---|
1494 | | - break; |
---|
1495 | | - opts = comma + 1; |
---|
| 1555 | + default: |
---|
| 1556 | + return -ENOPARAM; |
---|
1496 | 1557 | } |
---|
1497 | 1558 | |
---|
1498 | 1559 | return 0; |
---|
| 1560 | + |
---|
| 1561 | +unmapped_value: |
---|
| 1562 | + return invalf(fc, "%s: unmapped value: %u", param->key, result.uint_32); |
---|
1499 | 1563 | } |
---|
1500 | 1564 | |
---|
1501 | | -/* "mount -t functionfs dev_name /dev/function" ends up here */ |
---|
1502 | | - |
---|
1503 | | -static struct dentry * |
---|
1504 | | -ffs_fs_mount(struct file_system_type *t, int flags, |
---|
1505 | | - const char *dev_name, void *opts) |
---|
| 1565 | +/* |
---|
| 1566 | + * Set up the superblock for a mount. |
---|
| 1567 | + */ |
---|
| 1568 | +static int ffs_fs_get_tree(struct fs_context *fc) |
---|
1506 | 1569 | { |
---|
1507 | | - struct ffs_sb_fill_data data = { |
---|
1508 | | - .perms = { |
---|
1509 | | - .mode = S_IFREG | 0600, |
---|
1510 | | - .uid = GLOBAL_ROOT_UID, |
---|
1511 | | - .gid = GLOBAL_ROOT_GID, |
---|
1512 | | - }, |
---|
1513 | | - .root_mode = S_IFDIR | 0500, |
---|
1514 | | - .no_disconnect = false, |
---|
1515 | | - }; |
---|
1516 | | - struct dentry *rv; |
---|
1517 | | - int ret; |
---|
| 1570 | + struct ffs_sb_fill_data *ctx = fc->fs_private; |
---|
1518 | 1571 | struct ffs_data *ffs; |
---|
| 1572 | + int ret; |
---|
1519 | 1573 | |
---|
1520 | 1574 | ENTER(); |
---|
1521 | 1575 | |
---|
1522 | | - ret = ffs_fs_parse_opts(&data, opts); |
---|
1523 | | - if (unlikely(ret < 0)) |
---|
1524 | | - return ERR_PTR(ret); |
---|
| 1576 | + if (!fc->source) |
---|
| 1577 | + return invalf(fc, "No source specified"); |
---|
1525 | 1578 | |
---|
1526 | | - ffs = ffs_data_new(dev_name); |
---|
| 1579 | + ffs = ffs_data_new(fc->source); |
---|
1527 | 1580 | if (unlikely(!ffs)) |
---|
1528 | | - return ERR_PTR(-ENOMEM); |
---|
1529 | | - ffs->file_perms = data.perms; |
---|
1530 | | - ffs->no_disconnect = data.no_disconnect; |
---|
| 1581 | + return -ENOMEM; |
---|
| 1582 | + ffs->file_perms = ctx->perms; |
---|
| 1583 | + ffs->no_disconnect = ctx->no_disconnect; |
---|
1531 | 1584 | |
---|
1532 | | - ffs->dev_name = kstrdup(dev_name, GFP_KERNEL); |
---|
| 1585 | + ffs->dev_name = kstrdup(fc->source, GFP_KERNEL); |
---|
1533 | 1586 | if (unlikely(!ffs->dev_name)) { |
---|
1534 | 1587 | ffs_data_put(ffs); |
---|
1535 | | - return ERR_PTR(-ENOMEM); |
---|
| 1588 | + return -ENOMEM; |
---|
1536 | 1589 | } |
---|
1537 | 1590 | |
---|
1538 | | - ret = ffs_acquire_dev(dev_name, ffs); |
---|
| 1591 | + ret = ffs_acquire_dev(ffs->dev_name, ffs); |
---|
1539 | 1592 | if (ret) { |
---|
1540 | 1593 | ffs_data_put(ffs); |
---|
1541 | | - return ERR_PTR(ret); |
---|
| 1594 | + return ret; |
---|
1542 | 1595 | } |
---|
1543 | | - data.ffs_data = ffs; |
---|
1544 | 1596 | |
---|
1545 | | - rv = mount_nodev(t, flags, &data, ffs_sb_fill); |
---|
1546 | | - if (IS_ERR(rv) && data.ffs_data) |
---|
1547 | | - ffs_data_put(data.ffs_data); |
---|
1548 | | - return rv; |
---|
| 1597 | + ctx->ffs_data = ffs; |
---|
| 1598 | + return get_tree_nodev(fc, ffs_sb_fill); |
---|
| 1599 | +} |
---|
| 1600 | + |
---|
| 1601 | +static void ffs_fs_free_fc(struct fs_context *fc) |
---|
| 1602 | +{ |
---|
| 1603 | + struct ffs_sb_fill_data *ctx = fc->fs_private; |
---|
| 1604 | + |
---|
| 1605 | + if (ctx) { |
---|
| 1606 | + if (ctx->ffs_data) { |
---|
| 1607 | + ffs_data_put(ctx->ffs_data); |
---|
| 1608 | + } |
---|
| 1609 | + |
---|
| 1610 | + kfree(ctx); |
---|
| 1611 | + } |
---|
| 1612 | +} |
---|
| 1613 | + |
---|
| 1614 | +static const struct fs_context_operations ffs_fs_context_ops = { |
---|
| 1615 | + .free = ffs_fs_free_fc, |
---|
| 1616 | + .parse_param = ffs_fs_parse_param, |
---|
| 1617 | + .get_tree = ffs_fs_get_tree, |
---|
| 1618 | +}; |
---|
| 1619 | + |
---|
| 1620 | +static int ffs_fs_init_fs_context(struct fs_context *fc) |
---|
| 1621 | +{ |
---|
| 1622 | + struct ffs_sb_fill_data *ctx; |
---|
| 1623 | + |
---|
| 1624 | + ctx = kzalloc(sizeof(struct ffs_sb_fill_data), GFP_KERNEL); |
---|
| 1625 | + if (!ctx) |
---|
| 1626 | + return -ENOMEM; |
---|
| 1627 | + |
---|
| 1628 | + ctx->perms.mode = S_IFREG | 0600; |
---|
| 1629 | + ctx->perms.uid = GLOBAL_ROOT_UID; |
---|
| 1630 | + ctx->perms.gid = GLOBAL_ROOT_GID; |
---|
| 1631 | + ctx->root_mode = S_IFDIR | 0500; |
---|
| 1632 | + ctx->no_disconnect = false; |
---|
| 1633 | + |
---|
| 1634 | + fc->fs_private = ctx; |
---|
| 1635 | + fc->ops = &ffs_fs_context_ops; |
---|
| 1636 | + return 0; |
---|
1549 | 1637 | } |
---|
1550 | 1638 | |
---|
1551 | 1639 | static void |
---|
.. | .. |
---|
1561 | 1649 | static struct file_system_type ffs_fs_type = { |
---|
1562 | 1650 | .owner = THIS_MODULE, |
---|
1563 | 1651 | .name = "functionfs", |
---|
1564 | | - .mount = ffs_fs_mount, |
---|
| 1652 | + .init_fs_context = ffs_fs_init_fs_context, |
---|
| 1653 | + .parameters = ffs_fs_fs_parameters, |
---|
1565 | 1654 | .kill_sb = ffs_fs_kill_sb, |
---|
1566 | 1655 | }; |
---|
1567 | 1656 | MODULE_ALIAS_FS("functionfs"); |
---|
.. | .. |
---|
1626 | 1715 | ffs_data_clear(ffs); |
---|
1627 | 1716 | ffs_release_dev(ffs->private_data); |
---|
1628 | 1717 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || |
---|
1629 | | - waitqueue_active(&ffs->ep0req_completion.wait) || |
---|
| 1718 | + swait_active(&ffs->ep0req_completion.wait) || |
---|
1630 | 1719 | waitqueue_active(&ffs->wait)); |
---|
1631 | 1720 | destroy_workqueue(ffs->io_completion_wq); |
---|
1632 | 1721 | kfree(ffs->dev_name); |
---|
.. | .. |
---|
1807 | 1896 | ENTER(); |
---|
1808 | 1897 | |
---|
1809 | 1898 | if (!WARN_ON(!ffs->gadget)) { |
---|
| 1899 | + /* dequeue before freeing ep0req */ |
---|
| 1900 | + usb_ep_dequeue(ffs->gadget->ep0, ffs->ep0req); |
---|
| 1901 | + mutex_lock(&ffs->mutex); |
---|
1810 | 1902 | usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req); |
---|
1811 | 1903 | ffs->ep0req = NULL; |
---|
1812 | 1904 | ffs->gadget = NULL; |
---|
1813 | 1905 | clear_bit(FFS_FL_BOUND, &ffs->flags); |
---|
| 1906 | + mutex_unlock(&ffs->mutex); |
---|
1814 | 1907 | ffs_data_put(ffs); |
---|
1815 | 1908 | } |
---|
1816 | 1909 | } |
---|
.. | .. |
---|
1964 | 2057 | |
---|
1965 | 2058 | static int __must_check ffs_do_single_desc(char *data, unsigned len, |
---|
1966 | 2059 | ffs_entity_callback entity, |
---|
1967 | | - void *priv) |
---|
| 2060 | + void *priv, int *current_class) |
---|
1968 | 2061 | { |
---|
1969 | 2062 | struct usb_descriptor_header *_ds = (void *)data; |
---|
1970 | 2063 | u8 length; |
---|
.. | .. |
---|
2022 | 2115 | __entity(INTERFACE, ds->bInterfaceNumber); |
---|
2023 | 2116 | if (ds->iInterface) |
---|
2024 | 2117 | __entity(STRING, ds->iInterface); |
---|
| 2118 | + *current_class = ds->bInterfaceClass; |
---|
2025 | 2119 | } |
---|
2026 | 2120 | break; |
---|
2027 | 2121 | |
---|
.. | .. |
---|
2035 | 2129 | } |
---|
2036 | 2130 | break; |
---|
2037 | 2131 | |
---|
2038 | | - case HID_DT_HID: |
---|
2039 | | - pr_vdebug("hid descriptor\n"); |
---|
2040 | | - if (length != sizeof(struct hid_descriptor)) |
---|
2041 | | - goto inv_length; |
---|
2042 | | - break; |
---|
| 2132 | + case USB_TYPE_CLASS | 0x01: |
---|
| 2133 | + if (*current_class == USB_INTERFACE_CLASS_HID) { |
---|
| 2134 | + pr_vdebug("hid descriptor\n"); |
---|
| 2135 | + if (length != sizeof(struct hid_descriptor)) |
---|
| 2136 | + goto inv_length; |
---|
| 2137 | + break; |
---|
| 2138 | + } else if (*current_class == USB_INTERFACE_CLASS_CCID) { |
---|
| 2139 | + pr_vdebug("ccid descriptor\n"); |
---|
| 2140 | + if (length != sizeof(struct ccid_descriptor)) |
---|
| 2141 | + goto inv_length; |
---|
| 2142 | + break; |
---|
| 2143 | + } else { |
---|
| 2144 | + pr_vdebug("unknown descriptor: %d for class %d\n", |
---|
| 2145 | + _ds->bDescriptorType, *current_class); |
---|
| 2146 | + return -EINVAL; |
---|
| 2147 | + } |
---|
2043 | 2148 | |
---|
2044 | 2149 | case USB_DT_OTG: |
---|
2045 | 2150 | if (length != sizeof(struct usb_otg_descriptor)) |
---|
.. | .. |
---|
2096 | 2201 | { |
---|
2097 | 2202 | const unsigned _len = len; |
---|
2098 | 2203 | unsigned long num = 0; |
---|
| 2204 | + int current_class = -1; |
---|
2099 | 2205 | |
---|
2100 | 2206 | ENTER(); |
---|
2101 | 2207 | |
---|
.. | .. |
---|
2116 | 2222 | if (!data) |
---|
2117 | 2223 | return _len - len; |
---|
2118 | 2224 | |
---|
2119 | | - ret = ffs_do_single_desc(data, len, entity, priv); |
---|
| 2225 | + ret = ffs_do_single_desc(data, len, entity, priv, |
---|
| 2226 | + ¤t_class); |
---|
2120 | 2227 | if (unlikely(ret < 0)) { |
---|
2121 | 2228 | pr_debug("%s returns %d\n", __func__, ret); |
---|
2122 | 2229 | return ret; |
---|
.. | .. |
---|
2295 | 2402 | return _len - len; |
---|
2296 | 2403 | } |
---|
2297 | 2404 | |
---|
2298 | | -/** |
---|
| 2405 | +/* |
---|
2299 | 2406 | * Validate contents of the buffer from userspace related to OS descriptors. |
---|
2300 | 2407 | */ |
---|
2301 | 2408 | static int __ffs_data_do_os_desc(enum ffs_os_desc_type type, |
---|
.. | .. |
---|
2447 | 2554 | os_descs_count = get_unaligned_le32(data); |
---|
2448 | 2555 | data += 4; |
---|
2449 | 2556 | len -= 4; |
---|
2450 | | - }; |
---|
| 2557 | + } |
---|
2451 | 2558 | |
---|
2452 | 2559 | /* Read descriptors */ |
---|
2453 | 2560 | raw_descs = data; |
---|
.. | .. |
---|
2670 | 2777 | switch (type) { |
---|
2671 | 2778 | case FUNCTIONFS_RESUME: |
---|
2672 | 2779 | rem_type2 = FUNCTIONFS_SUSPEND; |
---|
2673 | | - /* FALL THROUGH */ |
---|
| 2780 | + fallthrough; |
---|
2674 | 2781 | case FUNCTIONFS_SUSPEND: |
---|
2675 | 2782 | case FUNCTIONFS_SETUP: |
---|
2676 | 2783 | rem_type1 = type; |
---|
.. | .. |
---|
2788 | 2895 | struct usb_request *req; |
---|
2789 | 2896 | struct usb_ep *ep; |
---|
2790 | 2897 | u8 bEndpointAddress; |
---|
| 2898 | + u16 wMaxPacketSize; |
---|
2791 | 2899 | |
---|
2792 | 2900 | /* |
---|
2793 | 2901 | * We back up bEndpointAddress because autoconfig overwrites |
---|
2794 | 2902 | * it with physical endpoint address. |
---|
2795 | 2903 | */ |
---|
2796 | 2904 | bEndpointAddress = ds->bEndpointAddress; |
---|
| 2905 | + /* |
---|
| 2906 | + * We back up wMaxPacketSize because autoconfig treats |
---|
| 2907 | + * endpoint descriptors as if they were full speed. |
---|
| 2908 | + */ |
---|
| 2909 | + wMaxPacketSize = ds->wMaxPacketSize; |
---|
2797 | 2910 | pr_vdebug("autoconfig\n"); |
---|
2798 | 2911 | ep = usb_ep_autoconfig(func->gadget, ds); |
---|
2799 | 2912 | if (unlikely(!ep)) |
---|
.. | .. |
---|
2815 | 2928 | */ |
---|
2816 | 2929 | if (func->ffs->user_flags & FUNCTIONFS_VIRTUAL_ADDR) |
---|
2817 | 2930 | ds->bEndpointAddress = bEndpointAddress; |
---|
| 2931 | + /* |
---|
| 2932 | + * Restore wMaxPacketSize which was potentially |
---|
| 2933 | + * overwritten by autoconfig. |
---|
| 2934 | + */ |
---|
| 2935 | + ds->wMaxPacketSize = wMaxPacketSize; |
---|
2818 | 2936 | } |
---|
2819 | 2937 | ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); |
---|
2820 | 2938 | |
---|
.. | .. |
---|
3449 | 3567 | |
---|
3450 | 3568 | static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) |
---|
3451 | 3569 | { |
---|
3452 | | - if (strlen(name) >= FIELD_SIZEOF(struct ffs_dev, name)) |
---|
| 3570 | + if (strlen(name) >= sizeof_field(struct ffs_dev, name)) |
---|
3453 | 3571 | return -ENAMETOOLONG; |
---|
3454 | 3572 | return ffs_name_dev(to_f_fs_opts(fi)->dev, name); |
---|
3455 | 3573 | } |
---|