From ad2d551ece8785eaae1aabde3e19f3c3cc430991 Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Wed, 18 Oct 2017 16:35:18 +0800 Subject: [PATCH] usb: gadget: Add check gadget function bind or not For NCM gadget function, net device structure opts->net will be freed when NCM unbind, but user space related device node doesn't know it, will access net structre without checking it exist or not, leading to potential use-after-free. Fix this by adding check gadget function bind or not. Change-Id: I6af9e3868f71e7fa923600721e1f716508de9b55 Signed-off-by: Liangliang Lu --- drivers/usb/gadget/function/f_ncm.c | 3 +- .../usb/gadget/function/u_ether_configfs.h | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 3566dcf6445d..d9e2603fab10 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1659,6 +1659,8 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) DBG(c->cdev, "ncm unbind\n"); + opts->bound = false; + hrtimer_cancel(&ncm->task_timer); kfree(f->os_desc_table); @@ -1671,7 +1673,6 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) usb_ep_free_request(ncm->notify, ncm->notify_req); gether_cleanup(netdev_priv(opts->net)); - opts->bound = false; } static struct usb_function *ncm_alloc(struct usb_function_instance *fi) diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h index d8b92485b727..13b08ebfff57 100644 --- a/drivers/usb/gadget/function/u_ether_configfs.h +++ b/drivers/usb/gadget/function/u_ether_configfs.h @@ -32,6 +32,11 @@ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ int result; \ \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ mutex_lock(&opts->lock); \ result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \ mutex_unlock(&opts->lock); \ @@ -45,6 +50,11 @@ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ int ret; \ \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ mutex_lock(&opts->lock); \ if (opts->refcnt) { \ mutex_unlock(&opts->lock); \ @@ -67,6 +77,11 @@ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ int result; \ \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ mutex_lock(&opts->lock); \ result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \ mutex_unlock(&opts->lock); \ @@ -80,6 +95,11 @@ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ int ret; \ \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ mutex_lock(&opts->lock); \ if (opts->refcnt) { \ mutex_unlock(&opts->lock); \ @@ -102,6 +122,11 @@ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ unsigned qmult; \ \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ mutex_lock(&opts->lock); \ qmult = gether_get_qmult(opts->net); \ mutex_unlock(&opts->lock); \ @@ -115,6 +140,11 @@ u8 val; \ int ret; \ \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ mutex_lock(&opts->lock); \ if (opts->refcnt) { \ ret = -EBUSY; \ @@ -141,6 +171,11 @@ out: \ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ int ret; \ \ + if (opts->bound == false) { \ + pr_err("Gadget function do not bind yet.\n"); \ + return -ENODEV; \ + } \ + \ mutex_lock(&opts->lock); \ ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \ mutex_unlock(&opts->lock); \