aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Lin <jilin@nvidia.com>2017-01-13 16:07:58 +0800
committerMister Oyster <oysterized@gmail.com>2017-05-10 18:26:27 +0200
commit61d3dae3cbb5a8ecaca57e454ac95fac16fa4ff1 (patch)
tree93b37fcc609da0ff1fd692fee6f9fdfc4e3da3ef
parent34fb8d05322bd09a7a79bf6e9a40e846368947e7 (diff)
CHROMIUM: usb: gadget: configfs: Fix KASAN use-after-free
When gadget is disconnected, running sequence is like this. . composite_disconnect . Call trace: usb_string_copy+0xd0/0x128 gadget_config_name_configuration_store+0x4 gadget_config_name_attr_store+0x40/0x50 configfs_write_file+0x198/0x1f4 vfs_write+0x100/0x220 SyS_write+0x58/0xa8 . configfs_composite_unbind . configfs_composite_bind In configfs_composite_bind, it has "cn->strings.s = cn->configuration;" When usb_string_copy is invoked. it would allocate memory, copy input string, release previous pointed memory space, and use new allocated memory. When gadget is connected, host sends down request to get information. Call trace: usb_gadget_get_string+0xec/0x168 lookup_string+0x64/0x98 composite_setup+0xa34/0x1ee8 If gadget is disconnected and connected quickly, in the failed case, cn->configuration memory has been released by usb_string_copy kfree but configfs_composite_bind hasn't been run in time to assign new allocated "cn->configuration" pointer to "cn->strings.s". When "strlen(s->s) of usb_gadget_get_string is being executed, the dangling memory is accessed, "BUG: KASAN: use-after-free" error occurs. BUG=chrome-os-partner:58412 TEST=After smaug device was connected to ubuntu PC host, detached and attached type-C cable quickly several times without seeing "BUG: KASAN: use-after-free in usb_gadget_get_string". Change-Id: I58240ee7c55ae8f8fb8597d14f09c5ac07abb032 Signed-off-by: Jim Lin <jilin@nvidia.com> Reviewed-on: https://chromium-review.googlesource.com/428059 Commit-Ready: Jim Lin <jilin%nvidia.com@gtempaccount.com> Tested-by: Jim Lin <jilin%nvidia.com@gtempaccount.com> Reviewed-by: Adrian Salido <salidoa@google.com> Reviewed-by: Benson Leung <bleung@chromium.org> Git-repo: https://chromium.googlesource.com/chromiumos/third_party/kernel Git-commit: a7b597d255d70f6f0c6bfdfb7e4e04f67fcebf9d Signed-off-by: Dennis Cagle <d-cagle@codeaurora.org>
-rw-r--r--drivers/usb/gadget/configfs.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 3dab42451..5c50282a0 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -87,21 +87,28 @@ struct gadget_config_name {
struct list_head list;
};
+#define MAX_USB_STRING_LEN 126
+#define MAX_USB_STRING_WITH_NULL_LEN (MAX_USB_STRING_LEN+1)
+
static int usb_string_copy(const char *s, char **s_copy)
{
int ret;
char *str;
char *copy = *s_copy;
ret = strlen(s);
- if (ret > 126)
+ if (ret > MAX_USB_STRING_LEN)
return -EOVERFLOW;
- str = kstrdup(s, GFP_KERNEL);
- if (!str)
- return -ENOMEM;
+ if (copy) {
+ str = copy;
+ } else {
+ str = kmalloc(MAX_USB_STRING_WITH_NULL_LEN, GFP_KERNEL);
+ if (!str)
+ return -ENOMEM;
+ }
+ strncpy(str, s, MAX_USB_STRING_WITH_NULL_LEN);
if (str[ret - 1] == '\n')
str[ret - 1] = '\0';
- kfree(copy);
*s_copy = str;
return 0;
}