diff options
Diffstat (limited to 'drivers/usb/gadget/function/f_fs.c')
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 140 |
1 files changed, 86 insertions, 54 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index c5c8363f114f..61546d25a263 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -248,8 +248,8 @@ EXPORT_SYMBOL_GPL(ffs_lock); | |||
248 | static struct ffs_dev *_ffs_find_dev(const char *name); | 248 | static struct ffs_dev *_ffs_find_dev(const char *name); |
249 | static struct ffs_dev *_ffs_alloc_dev(void); | 249 | static struct ffs_dev *_ffs_alloc_dev(void); |
250 | static void _ffs_free_dev(struct ffs_dev *dev); | 250 | static void _ffs_free_dev(struct ffs_dev *dev); |
251 | static void *ffs_acquire_dev(const char *dev_name); | 251 | static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data); |
252 | static void ffs_release_dev(struct ffs_data *ffs_data); | 252 | static void ffs_release_dev(struct ffs_dev *ffs_dev); |
253 | static int ffs_ready(struct ffs_data *ffs); | 253 | static int ffs_ready(struct ffs_data *ffs); |
254 | static void ffs_closed(struct ffs_data *ffs); | 254 | static void ffs_closed(struct ffs_data *ffs); |
255 | 255 | ||
@@ -609,7 +609,7 @@ static int ffs_ep0_open(struct inode *inode, struct file *file) | |||
609 | file->private_data = ffs; | 609 | file->private_data = ffs; |
610 | ffs_data_opened(ffs); | 610 | ffs_data_opened(ffs); |
611 | 611 | ||
612 | return 0; | 612 | return stream_open(inode, file); |
613 | } | 613 | } |
614 | 614 | ||
615 | static int ffs_ep0_release(struct inode *inode, struct file *file) | 615 | static int ffs_ep0_release(struct inode *inode, struct file *file) |
@@ -1073,7 +1073,7 @@ ffs_epfile_open(struct inode *inode, struct file *file) | |||
1073 | file->private_data = epfile; | 1073 | file->private_data = epfile; |
1074 | ffs_data_opened(epfile->ffs); | 1074 | ffs_data_opened(epfile->ffs); |
1075 | 1075 | ||
1076 | return 0; | 1076 | return stream_open(inode, file); |
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | static void ffs_aio_cancel_worker(struct work_struct *work) | 1079 | static void ffs_aio_cancel_worker(struct work_struct *work) |
@@ -1516,7 +1516,6 @@ ffs_fs_mount(struct file_system_type *t, int flags, | |||
1516 | }; | 1516 | }; |
1517 | struct dentry *rv; | 1517 | struct dentry *rv; |
1518 | int ret; | 1518 | int ret; |
1519 | void *ffs_dev; | ||
1520 | struct ffs_data *ffs; | 1519 | struct ffs_data *ffs; |
1521 | 1520 | ||
1522 | ENTER(); | 1521 | ENTER(); |
@@ -1537,19 +1536,16 @@ ffs_fs_mount(struct file_system_type *t, int flags, | |||
1537 | return ERR_PTR(-ENOMEM); | 1536 | return ERR_PTR(-ENOMEM); |
1538 | } | 1537 | } |
1539 | 1538 | ||
1540 | ffs_dev = ffs_acquire_dev(dev_name); | 1539 | ret = ffs_acquire_dev(dev_name, ffs); |
1541 | if (IS_ERR(ffs_dev)) { | 1540 | if (ret) { |
1542 | ffs_data_put(ffs); | 1541 | ffs_data_put(ffs); |
1543 | return ERR_CAST(ffs_dev); | 1542 | return ERR_PTR(ret); |
1544 | } | 1543 | } |
1545 | ffs->private_data = ffs_dev; | ||
1546 | data.ffs_data = ffs; | 1544 | data.ffs_data = ffs; |
1547 | 1545 | ||
1548 | rv = mount_nodev(t, flags, &data, ffs_sb_fill); | 1546 | rv = mount_nodev(t, flags, &data, ffs_sb_fill); |
1549 | if (IS_ERR(rv) && data.ffs_data) { | 1547 | if (IS_ERR(rv) && data.ffs_data) |
1550 | ffs_release_dev(data.ffs_data); | ||
1551 | ffs_data_put(data.ffs_data); | 1548 | ffs_data_put(data.ffs_data); |
1552 | } | ||
1553 | return rv; | 1549 | return rv; |
1554 | } | 1550 | } |
1555 | 1551 | ||
@@ -1559,10 +1555,8 @@ ffs_fs_kill_sb(struct super_block *sb) | |||
1559 | ENTER(); | 1555 | ENTER(); |
1560 | 1556 | ||
1561 | kill_litter_super(sb); | 1557 | kill_litter_super(sb); |
1562 | if (sb->s_fs_info) { | 1558 | if (sb->s_fs_info) |
1563 | ffs_release_dev(sb->s_fs_info); | ||
1564 | ffs_data_closed(sb->s_fs_info); | 1559 | ffs_data_closed(sb->s_fs_info); |
1565 | } | ||
1566 | } | 1560 | } |
1567 | 1561 | ||
1568 | static struct file_system_type ffs_fs_type = { | 1562 | static struct file_system_type ffs_fs_type = { |
@@ -1631,6 +1625,7 @@ static void ffs_data_put(struct ffs_data *ffs) | |||
1631 | if (unlikely(refcount_dec_and_test(&ffs->ref))) { | 1625 | if (unlikely(refcount_dec_and_test(&ffs->ref))) { |
1632 | pr_info("%s(): freeing\n", __func__); | 1626 | pr_info("%s(): freeing\n", __func__); |
1633 | ffs_data_clear(ffs); | 1627 | ffs_data_clear(ffs); |
1628 | ffs_release_dev(ffs->private_data); | ||
1634 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || | 1629 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || |
1635 | waitqueue_active(&ffs->ep0req_completion.wait) || | 1630 | waitqueue_active(&ffs->ep0req_completion.wait) || |
1636 | waitqueue_active(&ffs->wait)); | 1631 | waitqueue_active(&ffs->wait)); |
@@ -1642,16 +1637,24 @@ static void ffs_data_put(struct ffs_data *ffs) | |||
1642 | 1637 | ||
1643 | static void ffs_data_closed(struct ffs_data *ffs) | 1638 | static void ffs_data_closed(struct ffs_data *ffs) |
1644 | { | 1639 | { |
1640 | struct ffs_epfile *epfiles; | ||
1641 | unsigned long flags; | ||
1642 | |||
1645 | ENTER(); | 1643 | ENTER(); |
1646 | 1644 | ||
1647 | if (atomic_dec_and_test(&ffs->opened)) { | 1645 | if (atomic_dec_and_test(&ffs->opened)) { |
1648 | if (ffs->no_disconnect) { | 1646 | if (ffs->no_disconnect) { |
1649 | ffs->state = FFS_DEACTIVATED; | 1647 | ffs->state = FFS_DEACTIVATED; |
1650 | if (ffs->epfiles) { | 1648 | spin_lock_irqsave(&ffs->eps_lock, flags); |
1651 | ffs_epfiles_destroy(ffs->epfiles, | 1649 | epfiles = ffs->epfiles; |
1652 | ffs->eps_count); | 1650 | ffs->epfiles = NULL; |
1653 | ffs->epfiles = NULL; | 1651 | spin_unlock_irqrestore(&ffs->eps_lock, |
1654 | } | 1652 | flags); |
1653 | |||
1654 | if (epfiles) | ||
1655 | ffs_epfiles_destroy(epfiles, | ||
1656 | ffs->eps_count); | ||
1657 | |||
1655 | if (ffs->setup_state == FFS_SETUP_PENDING) | 1658 | if (ffs->setup_state == FFS_SETUP_PENDING) |
1656 | __ffs_ep0_stall(ffs); | 1659 | __ffs_ep0_stall(ffs); |
1657 | } else { | 1660 | } else { |
@@ -1698,17 +1701,34 @@ static struct ffs_data *ffs_data_new(const char *dev_name) | |||
1698 | 1701 | ||
1699 | static void ffs_data_clear(struct ffs_data *ffs) | 1702 | static void ffs_data_clear(struct ffs_data *ffs) |
1700 | { | 1703 | { |
1704 | struct ffs_epfile *epfiles; | ||
1705 | unsigned long flags; | ||
1706 | |||
1701 | ENTER(); | 1707 | ENTER(); |
1702 | 1708 | ||
1703 | ffs_closed(ffs); | 1709 | ffs_closed(ffs); |
1704 | 1710 | ||
1705 | BUG_ON(ffs->gadget); | 1711 | BUG_ON(ffs->gadget); |
1706 | 1712 | ||
1707 | if (ffs->epfiles) | 1713 | spin_lock_irqsave(&ffs->eps_lock, flags); |
1708 | ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count); | 1714 | epfiles = ffs->epfiles; |
1715 | ffs->epfiles = NULL; | ||
1716 | spin_unlock_irqrestore(&ffs->eps_lock, flags); | ||
1709 | 1717 | ||
1710 | if (ffs->ffs_eventfd) | 1718 | /* |
1719 | * potential race possible between ffs_func_eps_disable | ||
1720 | * & ffs_epfile_release therefore maintaining a local | ||
1721 | * copy of epfile will save us from use-after-free. | ||
1722 | */ | ||
1723 | if (epfiles) { | ||
1724 | ffs_epfiles_destroy(epfiles, ffs->eps_count); | ||
1725 | ffs->epfiles = NULL; | ||
1726 | } | ||
1727 | |||
1728 | if (ffs->ffs_eventfd) { | ||
1711 | eventfd_ctx_put(ffs->ffs_eventfd); | 1729 | eventfd_ctx_put(ffs->ffs_eventfd); |
1730 | ffs->ffs_eventfd = NULL; | ||
1731 | } | ||
1712 | 1732 | ||
1713 | kfree(ffs->raw_descs_data); | 1733 | kfree(ffs->raw_descs_data); |
1714 | kfree(ffs->raw_strings); | 1734 | kfree(ffs->raw_strings); |
@@ -1721,7 +1741,6 @@ static void ffs_data_reset(struct ffs_data *ffs) | |||
1721 | 1741 | ||
1722 | ffs_data_clear(ffs); | 1742 | ffs_data_clear(ffs); |
1723 | 1743 | ||
1724 | ffs->epfiles = NULL; | ||
1725 | ffs->raw_descs_data = NULL; | 1744 | ffs->raw_descs_data = NULL; |
1726 | ffs->raw_descs = NULL; | 1745 | ffs->raw_descs = NULL; |
1727 | ffs->raw_strings = NULL; | 1746 | ffs->raw_strings = NULL; |
@@ -1850,12 +1869,15 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) | |||
1850 | 1869 | ||
1851 | static void ffs_func_eps_disable(struct ffs_function *func) | 1870 | static void ffs_func_eps_disable(struct ffs_function *func) |
1852 | { | 1871 | { |
1853 | struct ffs_ep *ep = func->eps; | 1872 | struct ffs_ep *ep; |
1854 | struct ffs_epfile *epfile = func->ffs->epfiles; | 1873 | struct ffs_epfile *epfile; |
1855 | unsigned count = func->ffs->eps_count; | 1874 | unsigned short count; |
1856 | unsigned long flags; | 1875 | unsigned long flags; |
1857 | 1876 | ||
1858 | spin_lock_irqsave(&func->ffs->eps_lock, flags); | 1877 | spin_lock_irqsave(&func->ffs->eps_lock, flags); |
1878 | count = func->ffs->eps_count; | ||
1879 | epfile = func->ffs->epfiles; | ||
1880 | ep = func->eps; | ||
1859 | while (count--) { | 1881 | while (count--) { |
1860 | /* pending requests get nuked */ | 1882 | /* pending requests get nuked */ |
1861 | if (likely(ep->ep)) | 1883 | if (likely(ep->ep)) |
@@ -1873,14 +1895,18 @@ static void ffs_func_eps_disable(struct ffs_function *func) | |||
1873 | 1895 | ||
1874 | static int ffs_func_eps_enable(struct ffs_function *func) | 1896 | static int ffs_func_eps_enable(struct ffs_function *func) |
1875 | { | 1897 | { |
1876 | struct ffs_data *ffs = func->ffs; | 1898 | struct ffs_data *ffs; |
1877 | struct ffs_ep *ep = func->eps; | 1899 | struct ffs_ep *ep; |
1878 | struct ffs_epfile *epfile = ffs->epfiles; | 1900 | struct ffs_epfile *epfile; |
1879 | unsigned count = ffs->eps_count; | 1901 | unsigned short count; |
1880 | unsigned long flags; | 1902 | unsigned long flags; |
1881 | int ret = 0; | 1903 | int ret = 0; |
1882 | 1904 | ||
1883 | spin_lock_irqsave(&func->ffs->eps_lock, flags); | 1905 | spin_lock_irqsave(&func->ffs->eps_lock, flags); |
1906 | ffs = func->ffs; | ||
1907 | ep = func->eps; | ||
1908 | epfile = ffs->epfiles; | ||
1909 | count = ffs->eps_count; | ||
1884 | while(count--) { | 1910 | while(count--) { |
1885 | ep->ep->driver_data = ep; | 1911 | ep->ep->driver_data = ep; |
1886 | 1912 | ||
@@ -2554,6 +2580,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, | |||
2554 | 2580 | ||
2555 | do { /* lang_count > 0 so we can use do-while */ | 2581 | do { /* lang_count > 0 so we can use do-while */ |
2556 | unsigned needed = needed_count; | 2582 | unsigned needed = needed_count; |
2583 | u32 str_per_lang = str_count; | ||
2557 | 2584 | ||
2558 | if (unlikely(len < 3)) | 2585 | if (unlikely(len < 3)) |
2559 | goto error_free; | 2586 | goto error_free; |
@@ -2589,7 +2616,7 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, | |||
2589 | 2616 | ||
2590 | data += length + 1; | 2617 | data += length + 1; |
2591 | len -= length + 1; | 2618 | len -= length + 1; |
2592 | } while (--str_count); | 2619 | } while (--str_per_lang); |
2593 | 2620 | ||
2594 | s->id = 0; /* terminator */ | 2621 | s->id = 0; /* terminator */ |
2595 | s->s = NULL; | 2622 | s->s = NULL; |
@@ -2934,6 +2961,7 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, | |||
2934 | struct ffs_function *func = ffs_func_from_usb(f); | 2961 | struct ffs_function *func = ffs_func_from_usb(f); |
2935 | struct f_fs_opts *ffs_opts = | 2962 | struct f_fs_opts *ffs_opts = |
2936 | container_of(f->fi, struct f_fs_opts, func_inst); | 2963 | container_of(f->fi, struct f_fs_opts, func_inst); |
2964 | struct ffs_data *ffs_data; | ||
2937 | int ret; | 2965 | int ret; |
2938 | 2966 | ||
2939 | ENTER(); | 2967 | ENTER(); |
@@ -2948,12 +2976,13 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, | |||
2948 | if (!ffs_opts->no_configfs) | 2976 | if (!ffs_opts->no_configfs) |
2949 | ffs_dev_lock(); | 2977 | ffs_dev_lock(); |
2950 | ret = ffs_opts->dev->desc_ready ? 0 : -ENODEV; | 2978 | ret = ffs_opts->dev->desc_ready ? 0 : -ENODEV; |
2951 | func->ffs = ffs_opts->dev->ffs_data; | 2979 | ffs_data = ffs_opts->dev->ffs_data; |
2952 | if (!ffs_opts->no_configfs) | 2980 | if (!ffs_opts->no_configfs) |
2953 | ffs_dev_unlock(); | 2981 | ffs_dev_unlock(); |
2954 | if (ret) | 2982 | if (ret) |
2955 | return ERR_PTR(ret); | 2983 | return ERR_PTR(ret); |
2956 | 2984 | ||
2985 | func->ffs = ffs_data; | ||
2957 | func->conf = c; | 2986 | func->conf = c; |
2958 | func->gadget = c->cdev->gadget; | 2987 | func->gadget = c->cdev->gadget; |
2959 | 2988 | ||
@@ -3408,6 +3437,7 @@ static void ffs_free_inst(struct usb_function_instance *f) | |||
3408 | struct f_fs_opts *opts; | 3437 | struct f_fs_opts *opts; |
3409 | 3438 | ||
3410 | opts = to_f_fs_opts(f); | 3439 | opts = to_f_fs_opts(f); |
3440 | ffs_release_dev(opts->dev); | ||
3411 | ffs_dev_lock(); | 3441 | ffs_dev_lock(); |
3412 | _ffs_free_dev(opts->dev); | 3442 | _ffs_free_dev(opts->dev); |
3413 | ffs_dev_unlock(); | 3443 | ffs_dev_unlock(); |
@@ -3469,6 +3499,9 @@ static void ffs_func_unbind(struct usb_configuration *c, | |||
3469 | ffs->func = NULL; | 3499 | ffs->func = NULL; |
3470 | } | 3500 | } |
3471 | 3501 | ||
3502 | /* Drain any pending AIO completions */ | ||
3503 | drain_workqueue(ffs->io_completion_wq); | ||
3504 | |||
3472 | if (!--opts->refcnt) | 3505 | if (!--opts->refcnt) |
3473 | functionfs_unbind(ffs); | 3506 | functionfs_unbind(ffs); |
3474 | 3507 | ||
@@ -3592,47 +3625,48 @@ static void _ffs_free_dev(struct ffs_dev *dev) | |||
3592 | { | 3625 | { |
3593 | list_del(&dev->entry); | 3626 | list_del(&dev->entry); |
3594 | 3627 | ||
3595 | /* Clear the private_data pointer to stop incorrect dev access */ | ||
3596 | if (dev->ffs_data) | ||
3597 | dev->ffs_data->private_data = NULL; | ||
3598 | |||
3599 | kfree(dev); | 3628 | kfree(dev); |
3600 | if (list_empty(&ffs_devices)) | 3629 | if (list_empty(&ffs_devices)) |
3601 | functionfs_cleanup(); | 3630 | functionfs_cleanup(); |
3602 | } | 3631 | } |
3603 | 3632 | ||
3604 | static void *ffs_acquire_dev(const char *dev_name) | 3633 | static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data) |
3605 | { | 3634 | { |
3635 | int ret = 0; | ||
3606 | struct ffs_dev *ffs_dev; | 3636 | struct ffs_dev *ffs_dev; |
3607 | 3637 | ||
3608 | ENTER(); | 3638 | ENTER(); |
3609 | ffs_dev_lock(); | 3639 | ffs_dev_lock(); |
3610 | 3640 | ||
3611 | ffs_dev = _ffs_find_dev(dev_name); | 3641 | ffs_dev = _ffs_find_dev(dev_name); |
3612 | if (!ffs_dev) | 3642 | if (!ffs_dev) { |
3613 | ffs_dev = ERR_PTR(-ENOENT); | 3643 | ret = -ENOENT; |
3614 | else if (ffs_dev->mounted) | 3644 | } else if (ffs_dev->mounted) { |
3615 | ffs_dev = ERR_PTR(-EBUSY); | 3645 | ret = -EBUSY; |
3616 | else if (ffs_dev->ffs_acquire_dev_callback && | 3646 | } else if (ffs_dev->ffs_acquire_dev_callback && |
3617 | ffs_dev->ffs_acquire_dev_callback(ffs_dev)) | 3647 | ffs_dev->ffs_acquire_dev_callback(ffs_dev)) { |
3618 | ffs_dev = ERR_PTR(-ENOENT); | 3648 | ret = -ENOENT; |
3619 | else | 3649 | } else { |
3620 | ffs_dev->mounted = true; | 3650 | ffs_dev->mounted = true; |
3651 | ffs_dev->ffs_data = ffs_data; | ||
3652 | ffs_data->private_data = ffs_dev; | ||
3653 | } | ||
3621 | 3654 | ||
3622 | ffs_dev_unlock(); | 3655 | ffs_dev_unlock(); |
3623 | return ffs_dev; | 3656 | return ret; |
3624 | } | 3657 | } |
3625 | 3658 | ||
3626 | static void ffs_release_dev(struct ffs_data *ffs_data) | 3659 | static void ffs_release_dev(struct ffs_dev *ffs_dev) |
3627 | { | 3660 | { |
3628 | struct ffs_dev *ffs_dev; | ||
3629 | |||
3630 | ENTER(); | 3661 | ENTER(); |
3631 | ffs_dev_lock(); | 3662 | ffs_dev_lock(); |
3632 | 3663 | ||
3633 | ffs_dev = ffs_data->private_data; | 3664 | if (ffs_dev && ffs_dev->mounted) { |
3634 | if (ffs_dev) { | ||
3635 | ffs_dev->mounted = false; | 3665 | ffs_dev->mounted = false; |
3666 | if (ffs_dev->ffs_data) { | ||
3667 | ffs_dev->ffs_data->private_data = NULL; | ||
3668 | ffs_dev->ffs_data = NULL; | ||
3669 | } | ||
3636 | 3670 | ||
3637 | if (ffs_dev->ffs_release_dev_callback) | 3671 | if (ffs_dev->ffs_release_dev_callback) |
3638 | ffs_dev->ffs_release_dev_callback(ffs_dev); | 3672 | ffs_dev->ffs_release_dev_callback(ffs_dev); |
@@ -3660,7 +3694,6 @@ static int ffs_ready(struct ffs_data *ffs) | |||
3660 | } | 3694 | } |
3661 | 3695 | ||
3662 | ffs_obj->desc_ready = true; | 3696 | ffs_obj->desc_ready = true; |
3663 | ffs_obj->ffs_data = ffs; | ||
3664 | 3697 | ||
3665 | if (ffs_obj->ffs_ready_callback) { | 3698 | if (ffs_obj->ffs_ready_callback) { |
3666 | ret = ffs_obj->ffs_ready_callback(ffs); | 3699 | ret = ffs_obj->ffs_ready_callback(ffs); |
@@ -3688,7 +3721,6 @@ static void ffs_closed(struct ffs_data *ffs) | |||
3688 | goto done; | 3721 | goto done; |
3689 | 3722 | ||
3690 | ffs_obj->desc_ready = false; | 3723 | ffs_obj->desc_ready = false; |
3691 | ffs_obj->ffs_data = NULL; | ||
3692 | 3724 | ||
3693 | if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags) && | 3725 | if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags) && |
3694 | ffs_obj->ffs_closed_callback) | 3726 | ffs_obj->ffs_closed_callback) |