From 5d7a7200a4c5a25493cc4b7dbee8daf8e4e3216e Mon Sep 17 00:00:00 2001 From: Ravi Vembu Date: Tue, 21 Mar 2017 14:17:12 -0500 Subject: [PATCH] usb: configfs: Implement secure attribute Implement the secure attribute for locking USB access from the gadget driver. echo 1 > /sys/class/android_usb/android0/secure will lock USB access and disable USB enumeration. Change-Id: I9c7bcb27cfd4ce4f28520d938c604607ec6c2431 Moto-CRs-fixed: (CR) Reviewed-on: https://gerrit.mot.com/1750996 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Zonghua Liu Reviewed-by: Yuecai Liu Reviewed-by: Jianqi Yang Submit-Approved: Jira Key Reviewed-on: https://gerrit.mot.com/1785337 Reviewed-by: Huosheng Liao --- drivers/usb/gadget/configfs.c | 88 ++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 7ed6bb988eaf..849dce3f31c1 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -96,6 +96,7 @@ struct gadget_info { struct work_struct work; struct device *dev; #endif + bool secure; }; static inline struct gadget_info *to_gadget_info(struct config_item *item) @@ -291,11 +292,19 @@ static int unregister_gadget(struct gadget_info *gi) if (!gi->composite.gadget_driver.udc_name) return -ENODEV; + if (gi->secure) { + gi->unbinding = false; + kfree(gi->composite.gadget_driver.udc_name); + gi->composite.gadget_driver.udc_name = NULL; + return 0; + } + gi->unbinding = true; ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver); - if (ret) + if (ret) { + pr_err("unregister gadget failed, ret = %d\n", ret); return ret; - + } gi->unbinding = false; kfree(gi->composite.gadget_driver.udc_name); gi->composite.gadget_driver.udc_name = NULL; @@ -318,6 +327,8 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, if (name[len - 1] == '\n') name[len - 1] = '\0'; + pr_debug("UDC store = %s\n", name); + mutex_lock(&gi->lock); if (!strlen(name) || strcmp(name, "none") == 0) { @@ -331,10 +342,12 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, goto err; } gi->composite.gadget_driver.udc_name = name; - ret = usb_gadget_probe_driver(&gi->composite.gadget_driver); - if (ret) { - gi->composite.gadget_driver.udc_name = NULL; - goto err; + if (!gi->secure) { + ret = usb_gadget_probe_driver(&gi->composite.gadget_driver); + if (ret) { + gi->composite.gadget_driver.udc_name = NULL; + goto err; + } } #ifdef CONFIG_USB_CONFIGFS_UEVENT schedule_work(&gi->work); @@ -1786,8 +1799,71 @@ out: static DEVICE_ATTR(state, S_IRUGO, state_show, NULL); +static ssize_t secure_show(struct device *pdev, struct device_attribute *attr, + char *buf) +{ + struct gadget_info *gi = dev_get_drvdata(pdev); + + if (!gi) + return -ENODEV; + + return scnprintf(buf, PAGE_SIZE, "%d\n", gi->secure); +} + +static ssize_t secure_store(struct device *pdev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct gadget_info *gi = dev_get_drvdata(pdev); + unsigned long mode, r; + int ret; + + if (!gi) + return -ENODEV; + + r = kstrtoul(buf, 0, &mode); + if (r) { + dev_err(pdev, "Invalid value = %lu\n", mode); + return -EINVAL; + } + + mode = !!mode; + if (mode == gi->secure) + return count; + + mutex_lock(&gi->lock); + + gi->secure = mode; + + if (!gi->composite.gadget_driver.udc_name) { + mutex_unlock(&gi->lock); + return count; + } + pr_debug("Secure Store , UDC = %s, secure = %d\n", + gi->composite.gadget_driver.udc_name, + gi->secure); + + if (gi->secure) { + ret = usb_gadget_unregister_driver( + &gi->composite.gadget_driver); + if (ret) + pr_err("Failed detaching UDC from gadget %d\n", ret); + } else { + ret = usb_gadget_probe_driver(&gi->composite.gadget_driver); + if (ret) { + gi->composite.gadget_driver.udc_name = NULL; + pr_err("Failed attaching UDC to gadget %d\n", ret); + } + } + mutex_unlock(&gi->lock); + + return count; +} + +static DEVICE_ATTR(secure, S_IRUGO | S_IWUSR, secure_show, secure_store); + static struct device_attribute *android_usb_attributes[] = { &dev_attr_state, + &dev_attr_secure, NULL };