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 <luliang@codeaurora.org>
This commit is contained in:
Liangliang Lu 2017-10-18 16:35:18 +08:00 • committed by Gerrit - the friendly Code Review server
commit ad2d551ece
2 changed files with 37 additions and 1 deletions

View file

@ -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)

View file

@ -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); \