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:
@@ -1682,6 +1682,8 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
|
|
||||||
DBG(c->cdev, "ncm unbind\n");
|
DBG(c->cdev, "ncm unbind\n");
|
||||||
|
|
||||||
|
opts->bound = false;
|
||||||
|
|
||||||
hrtimer_cancel(&ncm->task_timer);
|
hrtimer_cancel(&ncm->task_timer);
|
||||||
|
|
||||||
ncm_string_defs[0].id = 0;
|
ncm_string_defs[0].id = 0;
|
||||||
@@ -1691,7 +1693,6 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
usb_ep_free_request(ncm->notify, ncm->notify_req);
|
usb_ep_free_request(ncm->notify, ncm->notify_req);
|
||||||
|
|
||||||
gether_cleanup(netdev_priv(opts->net));
|
gether_cleanup(netdev_priv(opts->net));
|
||||||
opts->bound = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
|
static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
|
||||||
|
|||||||
@@ -32,6 +32,11 @@
|
|||||||
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
int result; \
|
int result; \
|
||||||
\
|
\
|
||||||
|
if (opts->bound == false) { \
|
||||||
|
pr_err("Gadget function do not bind yet.\n"); \
|
||||||
|
return -ENODEV; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
mutex_lock(&opts->lock); \
|
mutex_lock(&opts->lock); \
|
||||||
result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \
|
result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \
|
||||||
mutex_unlock(&opts->lock); \
|
mutex_unlock(&opts->lock); \
|
||||||
@@ -45,6 +50,11 @@
|
|||||||
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
int ret; \
|
int ret; \
|
||||||
\
|
\
|
||||||
|
if (opts->bound == false) { \
|
||||||
|
pr_err("Gadget function do not bind yet.\n"); \
|
||||||
|
return -ENODEV; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
mutex_lock(&opts->lock); \
|
mutex_lock(&opts->lock); \
|
||||||
if (opts->refcnt) { \
|
if (opts->refcnt) { \
|
||||||
mutex_unlock(&opts->lock); \
|
mutex_unlock(&opts->lock); \
|
||||||
@@ -67,6 +77,11 @@
|
|||||||
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
int result; \
|
int result; \
|
||||||
\
|
\
|
||||||
|
if (opts->bound == false) { \
|
||||||
|
pr_err("Gadget function do not bind yet.\n"); \
|
||||||
|
return -ENODEV; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
mutex_lock(&opts->lock); \
|
mutex_lock(&opts->lock); \
|
||||||
result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \
|
result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \
|
||||||
mutex_unlock(&opts->lock); \
|
mutex_unlock(&opts->lock); \
|
||||||
@@ -80,6 +95,11 @@
|
|||||||
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
int ret; \
|
int ret; \
|
||||||
\
|
\
|
||||||
|
if (opts->bound == false) { \
|
||||||
|
pr_err("Gadget function do not bind yet.\n"); \
|
||||||
|
return -ENODEV; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
mutex_lock(&opts->lock); \
|
mutex_lock(&opts->lock); \
|
||||||
if (opts->refcnt) { \
|
if (opts->refcnt) { \
|
||||||
mutex_unlock(&opts->lock); \
|
mutex_unlock(&opts->lock); \
|
||||||
@@ -102,6 +122,11 @@
|
|||||||
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
unsigned qmult; \
|
unsigned qmult; \
|
||||||
\
|
\
|
||||||
|
if (opts->bound == false) { \
|
||||||
|
pr_err("Gadget function do not bind yet.\n"); \
|
||||||
|
return -ENODEV; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
mutex_lock(&opts->lock); \
|
mutex_lock(&opts->lock); \
|
||||||
qmult = gether_get_qmult(opts->net); \
|
qmult = gether_get_qmult(opts->net); \
|
||||||
mutex_unlock(&opts->lock); \
|
mutex_unlock(&opts->lock); \
|
||||||
@@ -115,6 +140,11 @@
|
|||||||
u8 val; \
|
u8 val; \
|
||||||
int ret; \
|
int ret; \
|
||||||
\
|
\
|
||||||
|
if (opts->bound == false) { \
|
||||||
|
pr_err("Gadget function do not bind yet.\n"); \
|
||||||
|
return -ENODEV; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
mutex_lock(&opts->lock); \
|
mutex_lock(&opts->lock); \
|
||||||
if (opts->refcnt) { \
|
if (opts->refcnt) { \
|
||||||
ret = -EBUSY; \
|
ret = -EBUSY; \
|
||||||
@@ -141,6 +171,11 @@ out: \
|
|||||||
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
int ret; \
|
int ret; \
|
||||||
\
|
\
|
||||||
|
if (opts->bound == false) { \
|
||||||
|
pr_err("Gadget function do not bind yet.\n"); \
|
||||||
|
return -ENODEV; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
mutex_lock(&opts->lock); \
|
mutex_lock(&opts->lock); \
|
||||||
ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \
|
ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \
|
||||||
mutex_unlock(&opts->lock); \
|
mutex_unlock(&opts->lock); \
|
||||||
|
|||||||
Reference in New Issue
Block a user