diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2019-12-07 21:50:59 +0000 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2019-12-07 21:50:59 +0000 |
commit | 474887d9d5a4c4892973d9cbffccb9fdba3d6d64 (patch) | |
tree | 7bf2d1632034d4744b28d40ca907fede5acef15b | |
parent | ac7258a5fc2e11d0b8d256021e332bcd05653d9a (diff) | |
download | linux-stable-queue-474887d9d5a4c4892973d9cbffccb9fdba3d6d64.tar.gz |
Add various security fixes
25 files changed, 1636 insertions, 0 deletions
diff --git a/queue-3.16/android-binder-remove-waitqueue-when-thread-exits.patch b/queue-3.16/android-binder-remove-waitqueue-when-thread-exits.patch new file mode 100644 index 00000000..4fa2c1f1 --- /dev/null +++ b/queue-3.16/android-binder-remove-waitqueue-when-thread-exits.patch @@ -0,0 +1,68 @@ +From: Martijn Coenen <maco@android.com> +Date: Fri, 5 Jan 2018 11:27:07 +0100 +Subject: ANDROID: binder: remove waitqueue when thread exits. + +commit f5cb779ba16334b45ba8946d6bfa6d9834d1527f upstream. + +binder_poll() passes the thread->wait waitqueue that +can be slept on for work. When a thread that uses +epoll explicitly exits using BINDER_THREAD_EXIT, +the waitqueue is freed, but it is never removed +from the corresponding epoll data structure. When +the process subsequently exits, the epoll cleanup +code tries to access the waitlist, which results in +a use-after-free. + +Prevent this by using POLLFREE when the thread exits. + +Signed-off-by: Martijn Coenen <maco@android.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +[backport BINDER_LOOPER_STATE_POLL logic as well] +Signed-off-by: Mattias Nissler <mnissler@chromium.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/staging/android/binder.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +--- a/drivers/staging/android/binder.c ++++ b/drivers/staging/android/binder.c +@@ -329,7 +329,8 @@ enum { + BINDER_LOOPER_STATE_EXITED = 0x04, + BINDER_LOOPER_STATE_INVALID = 0x08, + BINDER_LOOPER_STATE_WAITING = 0x10, +- BINDER_LOOPER_STATE_NEED_RETURN = 0x20 ++ BINDER_LOOPER_STATE_NEED_RETURN = 0x20, ++ BINDER_LOOPER_STATE_POLL = 0x40, + }; + + struct binder_thread { +@@ -2554,6 +2555,18 @@ static int binder_free_thread(struct bin + } else + BUG(); + } ++ ++ /* ++ * If this thread used poll, make sure we remove the waitqueue ++ * from any epoll data structures holding it with POLLFREE. ++ * waitqueue_active() is safe to use here because we're holding ++ * the global lock. ++ */ ++ if ((thread->looper & BINDER_LOOPER_STATE_POLL) && ++ waitqueue_active(&thread->wait)) { ++ wake_up_poll(&thread->wait, POLLHUP | POLLFREE); ++ } ++ + if (send_reply) + binder_send_failed_reply(send_reply, BR_DEAD_REPLY); + binder_release_work(&thread->todo); +@@ -2577,6 +2590,8 @@ static unsigned int binder_poll(struct f + return POLLERR; + } + ++ thread->looper |= BINDER_LOOPER_STATE_POLL; ++ + wait_for_proc_work = thread->transaction_stack == NULL && + list_empty(&thread->todo) && thread->return_error == BR_OK; + diff --git a/queue-3.16/appletalk-fix-potential-null-pointer-dereference-in.patch b/queue-3.16/appletalk-fix-potential-null-pointer-dereference-in.patch new file mode 100644 index 00000000..4f70cc87 --- /dev/null +++ b/queue-3.16/appletalk-fix-potential-null-pointer-dereference-in.patch @@ -0,0 +1,120 @@ +From: YueHaibing <yuehaibing@huawei.com> +Date: Thu, 14 Mar 2019 13:47:59 +0800 +Subject: appletalk: Fix potential NULL pointer dereference in + unregister_snap_client + +commit 9804501fa1228048857910a6bf23e085aade37cc upstream. + +register_snap_client may return NULL, all the callers +check it, but only print a warning. This will result in +NULL pointer dereference in unregister_snap_client and other +places. + +It has always been used like this since v2.6 + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: YueHaibing <yuehaibing@huawei.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/linux/atalk.h | 2 +- + net/appletalk/aarp.c | 15 ++++++++++++--- + net/appletalk/ddp.c | 20 ++++++++++++-------- + 3 files changed, 25 insertions(+), 12 deletions(-) + +--- a/include/linux/atalk.h ++++ b/include/linux/atalk.h +@@ -107,7 +107,7 @@ static __inline__ struct elapaarp *aarp_ + #define AARP_RESOLVE_TIME (10 * HZ) + + extern struct datalink_proto *ddp_dl, *aarp_dl; +-extern void aarp_proto_init(void); ++extern int aarp_proto_init(void); + + /* Inter module exports */ + +--- a/net/appletalk/aarp.c ++++ b/net/appletalk/aarp.c +@@ -879,15 +879,24 @@ static struct notifier_block aarp_notifi + + static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; + +-void __init aarp_proto_init(void) ++int __init aarp_proto_init(void) + { ++ int rc; ++ + aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); +- if (!aarp_dl) ++ if (!aarp_dl) { + printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); ++ return -ENOMEM; ++ } + setup_timer(&aarp_timer, aarp_expire_timeout, 0); + aarp_timer.expires = jiffies + sysctl_aarp_expiry_time; + add_timer(&aarp_timer); +- register_netdevice_notifier(&aarp_notifier); ++ rc = register_netdevice_notifier(&aarp_notifier); ++ if (rc) { ++ del_timer_sync(&aarp_timer); ++ unregister_snap_client(aarp_dl); ++ } ++ return rc; + } + + /* Remove the AARP entries associated with a device. */ +--- a/net/appletalk/ddp.c ++++ b/net/appletalk/ddp.c +@@ -1912,9 +1912,6 @@ static unsigned char ddp_snap_id[] = { 0 + EXPORT_SYMBOL(atrtr_get_dev); + EXPORT_SYMBOL(atalk_find_dev_addr); + +-static const char atalk_err_snap[] __initconst = +- KERN_CRIT "Unable to register DDP with SNAP.\n"; +- + /* Called by proto.c on kernel start up */ + static int __init atalk_init(void) + { +@@ -1929,17 +1926,22 @@ static int __init atalk_init(void) + goto out_proto; + + ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); +- if (!ddp_dl) +- printk(atalk_err_snap); ++ if (!ddp_dl) { ++ pr_crit("Unable to register DDP with SNAP.\n"); ++ goto out_sock; ++ } + + dev_add_pack(<alk_packet_type); + dev_add_pack(&ppptalk_packet_type); + + rc = register_netdevice_notifier(&ddp_notifier); + if (rc) +- goto out_sock; ++ goto out_snap; ++ ++ rc = aarp_proto_init(); ++ if (rc) ++ goto out_dev; + +- aarp_proto_init(); + rc = atalk_proc_init(); + if (rc) + goto out_aarp; +@@ -1953,11 +1955,13 @@ out_proc: + atalk_proc_exit(); + out_aarp: + aarp_cleanup_module(); ++out_dev: + unregister_netdevice_notifier(&ddp_notifier); +-out_sock: ++out_snap: + dev_remove_pack(&ppptalk_packet_type); + dev_remove_pack(<alk_packet_type); + unregister_snap_client(ddp_dl); ++out_sock: + sock_unregister(PF_APPLETALK); + out_proto: + proto_unregister(&ddp_proto); diff --git a/queue-3.16/can-gs_usb-gs_can_open-prevent-memory-leak.patch b/queue-3.16/can-gs_usb-gs_can_open-prevent-memory-leak.patch new file mode 100644 index 00000000..b6cdad0c --- /dev/null +++ b/queue-3.16/can-gs_usb-gs_can_open-prevent-memory-leak.patch @@ -0,0 +1,27 @@ +From: Navid Emamdoost <navid.emamdoost@gmail.com> +Date: Thu, 19 Sep 2019 21:44:38 -0500 +Subject: can: gs_usb: gs_can_open(): prevent memory leak + +commit fb5be6a7b4863ecc44963bb80ca614584b6c7817 upstream. + +In gs_can_open() if usb_submit_urb() fails the allocated urb should be +released. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> +Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/can/usb/gs_usb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -617,6 +617,7 @@ static int gs_can_open(struct net_device + rc); + + usb_unanchor_urb(urb); ++ usb_free_urb(urb); + break; + } + diff --git a/queue-3.16/can-peak_usb-fix-slab-info-leak.patch b/queue-3.16/can-peak_usb-fix-slab-info-leak.patch new file mode 100644 index 00000000..73168d46 --- /dev/null +++ b/queue-3.16/can-peak_usb-fix-slab-info-leak.patch @@ -0,0 +1,34 @@ +From: Johan Hovold <johan@kernel.org> +Date: Wed, 23 Oct 2019 10:27:05 +0200 +Subject: can: peak_usb: fix slab info leak + +commit f7a1337f0d29b98733c8824e165fca3371d7d4fd upstream. + +Fix a small slab info leak due to a failure to clear the command buffer +at allocation. + +The first 16 bytes of the command buffer are always sent to the device +in pcan_usb_send_cmd() even though only the first two may have been +initialised in case no argument payload is provided (e.g. when waiting +for a response). + +Fixes: bb4785551f64 ("can: usb: PEAK-System Technik USB adapters driver core") +Reported-by: syzbot+863724e7128e14b26732@syzkaller.appspotmail.com +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/can/usb/peak_usb/pcan_usb_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +@@ -732,7 +732,7 @@ static int peak_usb_create_dev(struct pe + dev = netdev_priv(netdev); + + /* allocate a buffer large enough to send commands */ +- dev->cmd_buf = kmalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL); ++ dev->cmd_buf = kzalloc(PCAN_USB_MAX_CMD_LEN, GFP_KERNEL); + if (!dev->cmd_buf) { + err = -ENOMEM; + goto lbl_free_candev; diff --git a/queue-3.16/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch b/queue-3.16/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch new file mode 100644 index 00000000..325c0afa --- /dev/null +++ b/queue-3.16/cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch @@ -0,0 +1,100 @@ +From: Johannes Berg <johannes.berg@intel.com> +Date: Thu, 7 Feb 2019 21:44:41 +0100 +Subject: cfg80211: add and use strongly typed element iteration macros + +commit 0f3b07f027f87a38ebe5c436490095df762819be upstream. + +Rather than always iterating elements from frames with pure +u8 pointers, add a type "struct element" that encapsulates +the id/datalen/data format of them. + +Then, add the element iteration macros + * for_each_element + * for_each_element_id + * for_each_element_extid + +which take, as their first 'argument', such a structure and +iterate through a given u8 array interpreting it as elements. + +While at it and since we'll need it, also add + * for_each_subelement + * for_each_subelement_id + * for_each_subelement_extid + +which instead of taking data/length just take an outer element +and use its data/datalen. + +Also add for_each_element_completed() to determine if any of +the loops above completed, i.e. it was able to parse all of +the elements successfully and no data remained. + +Use for_each_element_id() in cfg80211_find_ie_match() as the +first user of this. + +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/linux/ieee80211.h | 53 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + +--- a/include/linux/ieee80211.h ++++ b/include/linux/ieee80211.h +@@ -2358,4 +2358,57 @@ static inline bool ieee80211_check_tim(c + #define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) + #define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) + ++struct element { ++ u8 id; ++ u8 datalen; ++ u8 data[]; ++}; ++ ++/* element iteration helpers */ ++#define for_each_element(element, _data, _datalen) \ ++ for (element = (void *)(_data); \ ++ (u8 *)(_data) + (_datalen) - (u8 *)element >= \ ++ sizeof(*element) && \ ++ (u8 *)(_data) + (_datalen) - (u8 *)element >= \ ++ sizeof(*element) + element->datalen; \ ++ element = (void *)(element->data + element->datalen)) ++ ++#define for_each_element_id(element, _id, data, datalen) \ ++ for_each_element(element, data, datalen) \ ++ if (element->id == (_id)) ++ ++#define for_each_element_extid(element, extid, data, datalen) \ ++ for_each_element(element, data, datalen) \ ++ if (element->id == WLAN_EID_EXTENSION && \ ++ element->datalen > 0 && \ ++ element->data[0] == (extid)) ++ ++#define for_each_subelement(sub, element) \ ++ for_each_element(sub, (element)->data, (element)->datalen) ++ ++#define for_each_subelement_id(sub, id, element) \ ++ for_each_element_id(sub, id, (element)->data, (element)->datalen) ++ ++#define for_each_subelement_extid(sub, extid, element) \ ++ for_each_element_extid(sub, extid, (element)->data, (element)->datalen) ++ ++/** ++ * for_each_element_completed - determine if element parsing consumed all data ++ * @element: element pointer after for_each_element() or friends ++ * @data: same data pointer as passed to for_each_element() or friends ++ * @datalen: same data length as passed to for_each_element() or friends ++ * ++ * This function returns %true if all the data was parsed or considered ++ * while walking the elements. Only use this if your for_each_element() ++ * loop cannot be broken out of, otherwise it always returns %false. ++ * ++ * If some data was malformed, this returns %false since the last parsed ++ * element will not fill the whole remaining data. ++ */ ++static inline bool for_each_element_completed(const struct element *element, ++ const void *data, size_t datalen) ++{ ++ return (u8 *)element == (u8 *)data + datalen; ++} ++ + #endif /* LINUX_IEEE80211_H */ diff --git a/queue-3.16/crypto-user-fix-crypto_alg_match-race.patch b/queue-3.16/crypto-user-fix-crypto_alg_match-race.patch new file mode 100644 index 00000000..58e7e67d --- /dev/null +++ b/queue-3.16/crypto-user-fix-crypto_alg_match-race.patch @@ -0,0 +1,116 @@ +From: Herbert Xu <herbert@gondor.apana.org.au> +Date: Tue, 7 Apr 2015 21:27:01 +0800 +Subject: crypto: user - Fix crypto_alg_match race + +commit 016baaa1183bb0c5fb2a7de42413bba8a51c1bc8 upstream. + +The function crypto_alg_match returns an algorithm without taking +any references on it. This means that the algorithm can be freed +at any time, therefore all users of crypto_alg_match are buggy. + +This patch fixes this by taking a reference count on the algorithm +to prevent such races. + +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + crypto/crypto_user.c | 39 +++++++++++++++++++++++++++++---------- + 1 file changed, 29 insertions(+), 10 deletions(-) + +--- a/crypto/crypto_user.c ++++ b/crypto/crypto_user.c +@@ -65,10 +65,14 @@ static struct crypto_alg *crypto_alg_mat + else if (!exact) + match = !strcmp(q->cra_name, p->cru_name); + +- if (match) { +- alg = q; +- break; +- } ++ if (!match) ++ continue; ++ ++ if (unlikely(!crypto_mod_get(q))) ++ continue; ++ ++ alg = q; ++ break; + } + + up_read(&crypto_alg_sem); +@@ -211,9 +215,10 @@ static int crypto_report(struct sk_buff + if (!alg) + return -ENOENT; + ++ err = -ENOMEM; + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); + if (!skb) +- return -ENOMEM; ++ goto drop_alg; + + info.in_skb = in_skb; + info.out_skb = skb; +@@ -221,6 +226,10 @@ static int crypto_report(struct sk_buff + info.nlmsg_flags = 0; + + err = crypto_report_alg(alg, &info); ++ ++drop_alg: ++ crypto_mod_put(alg); ++ + if (err) + return err; + +@@ -293,6 +302,7 @@ static int crypto_update_alg(struct sk_b + + up_write(&crypto_alg_sem); + ++ crypto_mod_put(alg); + crypto_remove_final(&list); + + return 0; +@@ -303,6 +313,7 @@ static int crypto_del_alg(struct sk_buff + { + struct crypto_alg *alg; + struct crypto_user_alg *p = nlmsg_data(nlh); ++ int err; + + if (!netlink_capable(skb, CAP_NET_ADMIN)) + return -EPERM; +@@ -319,13 +330,19 @@ static int crypto_del_alg(struct sk_buff + * if we try to unregister. Unregistering such an algorithm without + * removing the module is not possible, so we restrict to crypto + * instances that are build from templates. */ ++ err = -EINVAL; + if (!(alg->cra_flags & CRYPTO_ALG_INSTANCE)) +- return -EINVAL; ++ goto drop_alg; + +- if (atomic_read(&alg->cra_refcnt) != 1) +- return -EBUSY; ++ err = -EBUSY; ++ if (atomic_read(&alg->cra_refcnt) > 2) ++ goto drop_alg; + +- return crypto_unregister_instance(alg); ++ err = crypto_unregister_instance(alg); ++ ++drop_alg: ++ crypto_mod_put(alg); ++ return err; + } + + static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type, +@@ -404,8 +421,10 @@ static int crypto_add_alg(struct sk_buff + return -EINVAL; + + alg = crypto_alg_match(p, exact); +- if (alg) ++ if (alg) { ++ crypto_mod_put(alg); + return -EEXIST; ++ } + + if (strlen(p->cru_driver_name)) + name = p->cru_driver_name; diff --git a/queue-3.16/crypto-user-fix-memory-leak-in-crypto_report.patch b/queue-3.16/crypto-user-fix-memory-leak-in-crypto_report.patch new file mode 100644 index 00000000..40ce80c0 --- /dev/null +++ b/queue-3.16/crypto-user-fix-memory-leak-in-crypto_report.patch @@ -0,0 +1,32 @@ +From: Navid Emamdoost <navid.emamdoost@gmail.com> +Date: Fri, 4 Oct 2019 14:29:16 -0500 +Subject: crypto: user - fix memory leak in crypto_report + +commit ffdde5932042600c6807d46c1550b28b0db6a3bc upstream. + +In crypto_report, a new skb is created via nlmsg_new(). This skb should +be released if crypto_report_alg() fails. + +Fixes: a38f7907b926 ("crypto: Add userspace configuration API") +Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + crypto/crypto_user.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/crypto/crypto_user.c ++++ b/crypto/crypto_user.c +@@ -230,8 +230,10 @@ static int crypto_report(struct sk_buff + drop_alg: + crypto_mod_put(alg); + +- if (err) ++ if (err) { ++ kfree_skb(skb); + return err; ++ } + + return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid); + } diff --git a/queue-3.16/hid-fix-assumption-that-devices-have-inputs.patch b/queue-3.16/hid-fix-assumption-that-devices-have-inputs.patch new file mode 100644 index 00000000..efbcc378 --- /dev/null +++ b/queue-3.16/hid-fix-assumption-that-devices-have-inputs.patch @@ -0,0 +1,315 @@ +From: Alan Stern <stern@rowland.harvard.edu> +Date: Thu, 3 Oct 2019 14:53:59 -0400 +Subject: HID: Fix assumption that devices have inputs + +commit d9d4b1e46d9543a82c23f6df03f4ad697dab361b upstream. + +The syzbot fuzzer found a slab-out-of-bounds write bug in the hid-gaff +driver. The problem is caused by the driver's assumption that the +device must have an input report. While this will be true for all +normal HID input devices, a suitably malicious device can violate the +assumption. + +The same assumption is present in over a dozen other HID drivers. +This patch fixes them by checking that the list of hid_inputs for the +hid_device is nonempty before allowing it to be used. + +Reported-and-tested-by: syzbot+403741a091bf41d4ae79@syzkaller.appspotmail.com +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> +[bwh: Backported to 3.16: + - Drop changes in hid-logitech-hidpp, hid-microsoft + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/hid/hid-axff.c ++++ b/drivers/hid/hid-axff.c +@@ -75,13 +75,20 @@ static int axff_init(struct hid_device * + { + struct axff_device *axff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int field_count = 0; + int i, j; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +--- a/drivers/hid/hid-dr.c ++++ b/drivers/hid/hid-dr.c +@@ -87,13 +87,19 @@ static int drff_init(struct hid_device * + { + struct drff_device *drff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +--- a/drivers/hid/hid-emsff.c ++++ b/drivers/hid/hid-emsff.c +@@ -59,13 +59,19 @@ static int emsff_init(struct hid_device + { + struct emsff_device *emsff; + struct hid_report *report; +- struct hid_input *hidinput = list_first_entry(&hid->inputs, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_first_entry(&hid->inputs, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +--- a/drivers/hid/hid-gaff.c ++++ b/drivers/hid/hid-gaff.c +@@ -77,14 +77,20 @@ static int gaff_init(struct hid_device * + { + struct gaff_device *gaff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct list_head *report_ptr = report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output reports found\n"); + return -ENODEV; +--- a/drivers/hid/hid-holtekff.c ++++ b/drivers/hid/hid-holtekff.c +@@ -140,13 +140,19 @@ static int holtekff_init(struct hid_devi + { + struct holtekff_device *holtekff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); ++ struct hid_input *hidinput; + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; +- struct input_dev *dev = hidinput->input; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + if (list_empty(report_list)) { + hid_err(hid, "no output report found\n"); + return -ENODEV; +--- a/drivers/hid/hid-lg2ff.c ++++ b/drivers/hid/hid-lg2ff.c +@@ -62,11 +62,17 @@ int lg2ff_init(struct hid_device *hid) + { + struct lg2ff_device *lg2ff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + int error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); + if (!report) +--- a/drivers/hid/hid-lg3ff.c ++++ b/drivers/hid/hid-lg3ff.c +@@ -129,12 +129,19 @@ static const signed short ff3_joystick_a + + int lg3ff_init(struct hid_device *hid) + { +- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + const signed short *ff_bits = ff3_joystick_ac; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) + return -ENODEV; +--- a/drivers/hid/hid-lg4ff.c ++++ b/drivers/hid/hid-lg4ff.c +@@ -558,14 +558,21 @@ static enum led_brightness lg4ff_led_get + + int lg4ff_init(struct hid_device *hid) + { +- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + struct usb_device_descriptor *udesc; + int error, i, j; + __u16 bcdDevice, rev_maj, rev_min; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -1; +--- a/drivers/hid/hid-lgff.c ++++ b/drivers/hid/hid-lgff.c +@@ -127,12 +127,19 @@ static void hid_lgff_set_autocenter(stru + + int lgff_init(struct hid_device* hid) + { +- struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + const signed short *ff_bits = ff_joystick; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + /* Check that the report looks ok */ + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -1509,9 +1509,15 @@ static int sony_play_effect(struct input + + static int sony_init_ff(struct sony_sc *sc) + { +- struct hid_input *hidinput = list_entry(sc->hdev->inputs.next, +- struct hid_input, list); +- struct input_dev *input_dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *input_dev; ++ ++ if (list_empty(&sc->hdev->inputs)) { ++ hid_err(sc->hdev, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(sc->hdev->inputs.next, struct hid_input, list); ++ input_dev = hidinput->input; + + input_set_capability(input_dev, EV_FF, FF_RUMBLE); + return input_ff_create_memless(input_dev, NULL, sony_play_effect); +--- a/drivers/hid/hid-tmff.c ++++ b/drivers/hid/hid-tmff.c +@@ -126,12 +126,18 @@ static int tmff_init(struct hid_device * + struct tmff_device *tmff; + struct hid_report *report; + struct list_head *report_list; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *input_dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *input_dev; + int error; + int i; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ input_dev = hidinput->input; ++ + tmff = kzalloc(sizeof(struct tmff_device), GFP_KERNEL); + if (!tmff) + return -ENOMEM; +--- a/drivers/hid/hid-zpff.c ++++ b/drivers/hid/hid-zpff.c +@@ -66,11 +66,17 @@ static int zpff_init(struct hid_device * + { + struct zpff_device *zpff; + struct hid_report *report; +- struct hid_input *hidinput = list_entry(hid->inputs.next, +- struct hid_input, list); +- struct input_dev *dev = hidinput->input; ++ struct hid_input *hidinput; ++ struct input_dev *dev; + int i, error; + ++ if (list_empty(&hid->inputs)) { ++ hid_err(hid, "no inputs found\n"); ++ return -ENODEV; ++ } ++ hidinput = list_entry(hid->inputs.next, struct hid_input, list); ++ dev = hidinput->input; ++ + for (i = 0; i < 4; i++) { + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); + if (!report) diff --git a/queue-3.16/hid-hiddev-avoid-opening-a-disconnected-device.patch b/queue-3.16/hid-hiddev-avoid-opening-a-disconnected-device.patch new file mode 100644 index 00000000..2bb5d9a7 --- /dev/null +++ b/queue-3.16/hid-hiddev-avoid-opening-a-disconnected-device.patch @@ -0,0 +1,208 @@ +From: Hillf Danton <hdanton@sina.com> +Date: Tue, 6 Aug 2019 16:38:58 +0800 +Subject: HID: hiddev: avoid opening a disconnected device + +commit 9c09b214f30e3c11f9b0b03f89442df03643794d upstream. + +syzbot found the following crash on: + +HEAD commit: e96407b4 usb-fuzzer: main usb gadget fuzzer driver +git tree: https://github.com/google/kasan.git usb-fuzzer +console output: https://syzkaller.appspot.com/x/log.txt?x=147ac20c600000 +kernel config: https://syzkaller.appspot.com/x/.config?x=792eb47789f57810 +dashboard link: https://syzkaller.appspot.com/bug?extid=62a1e04fd3ec2abf099e +compiler: gcc (GCC) 9.0.0 20181231 (experimental) + +================================================================== +BUG: KASAN: use-after-free in __lock_acquire+0x302a/0x3b50 +kernel/locking/lockdep.c:3753 +Read of size 8 at addr ffff8881cf591a08 by task syz-executor.1/26260 + +CPU: 1 PID: 26260 Comm: syz-executor.1 Not tainted 5.3.0-rc2+ #24 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS +Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xca/0x13e lib/dump_stack.c:113 + print_address_description+0x6a/0x32c mm/kasan/report.c:351 + __kasan_report.cold+0x1a/0x33 mm/kasan/report.c:482 + kasan_report+0xe/0x12 mm/kasan/common.c:612 + __lock_acquire+0x302a/0x3b50 kernel/locking/lockdep.c:3753 + lock_acquire+0x127/0x320 kernel/locking/lockdep.c:4412 + __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline] + _raw_spin_lock_irqsave+0x32/0x50 kernel/locking/spinlock.c:159 + hiddev_release+0x82/0x520 drivers/hid/usbhid/hiddev.c:221 + __fput+0x2d7/0x840 fs/file_table.c:280 + task_work_run+0x13f/0x1c0 kernel/task_work.c:113 + exit_task_work include/linux/task_work.h:22 [inline] + do_exit+0x8ef/0x2c50 kernel/exit.c:878 + do_group_exit+0x125/0x340 kernel/exit.c:982 + get_signal+0x466/0x23d0 kernel/signal.c:2728 + do_signal+0x88/0x14e0 arch/x86/kernel/signal.c:815 + exit_to_usermode_loop+0x1a2/0x200 arch/x86/entry/common.c:159 + prepare_exit_to_usermode arch/x86/entry/common.c:194 [inline] + syscall_return_slowpath arch/x86/entry/common.c:274 [inline] + do_syscall_64+0x45f/0x580 arch/x86/entry/common.c:299 + entry_SYSCALL_64_after_hwframe+0x49/0xbe +RIP: 0033:0x459829 +Code: fd b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 +48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff +ff 0f 83 cb b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 +RSP: 002b:00007f75b2a6ccf8 EFLAGS: 00000246 ORIG_RAX: 00000000000000ca +RAX: fffffffffffffe00 RBX: 000000000075c078 RCX: 0000000000459829 +RDX: 0000000000000000 RSI: 0000000000000080 RDI: 000000000075c078 +RBP: 000000000075c070 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 000000000075c07c +R13: 00007ffcdfe1023f R14: 00007f75b2a6d9c0 R15: 000000000075c07c + +Allocated by task 104: + save_stack+0x1b/0x80 mm/kasan/common.c:69 + set_track mm/kasan/common.c:77 [inline] + __kasan_kmalloc mm/kasan/common.c:487 [inline] + __kasan_kmalloc.constprop.0+0xbf/0xd0 mm/kasan/common.c:460 + kmalloc include/linux/slab.h:552 [inline] + kzalloc include/linux/slab.h:748 [inline] + hiddev_connect+0x242/0x5b0 drivers/hid/usbhid/hiddev.c:900 + hid_connect+0x239/0xbb0 drivers/hid/hid-core.c:1882 + hid_hw_start drivers/hid/hid-core.c:1981 [inline] + hid_hw_start+0xa2/0x130 drivers/hid/hid-core.c:1972 + appleir_probe+0x13e/0x1a0 drivers/hid/hid-appleir.c:308 + hid_device_probe+0x2be/0x3f0 drivers/hid/hid-core.c:2209 + really_probe+0x281/0x650 drivers/base/dd.c:548 + driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709 + __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:816 + bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 + __device_attach+0x217/0x360 drivers/base/dd.c:882 + bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 + device_add+0xae6/0x16f0 drivers/base/core.c:2114 + hid_add_device+0x33c/0x990 drivers/hid/hid-core.c:2365 + usbhid_probe+0xa81/0xfa0 drivers/hid/usbhid/hid-core.c:1386 + usb_probe_interface+0x305/0x7a0 drivers/usb/core/driver.c:361 + really_probe+0x281/0x650 drivers/base/dd.c:548 + driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709 + __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:816 + bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 + __device_attach+0x217/0x360 drivers/base/dd.c:882 + bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 + device_add+0xae6/0x16f0 drivers/base/core.c:2114 + usb_set_configuration+0xdf6/0x1670 drivers/usb/core/message.c:2023 + generic_probe+0x9d/0xd5 drivers/usb/core/generic.c:210 + usb_probe_device+0x99/0x100 drivers/usb/core/driver.c:266 + really_probe+0x281/0x650 drivers/base/dd.c:548 + driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709 + __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:816 + bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 + __device_attach+0x217/0x360 drivers/base/dd.c:882 + bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 + device_add+0xae6/0x16f0 drivers/base/core.c:2114 + usb_new_device.cold+0x6a4/0xe79 drivers/usb/core/hub.c:2536 + hub_port_connect drivers/usb/core/hub.c:5098 [inline] + hub_port_connect_change drivers/usb/core/hub.c:5213 [inline] + port_event drivers/usb/core/hub.c:5359 [inline] + hub_event+0x1b5c/0x3640 drivers/usb/core/hub.c:5441 + process_one_work+0x92b/0x1530 kernel/workqueue.c:2269 + worker_thread+0x96/0xe20 kernel/workqueue.c:2415 + kthread+0x318/0x420 kernel/kthread.c:255 + ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 + +Freed by task 104: + save_stack+0x1b/0x80 mm/kasan/common.c:69 + set_track mm/kasan/common.c:77 [inline] + __kasan_slab_free+0x130/0x180 mm/kasan/common.c:449 + slab_free_hook mm/slub.c:1423 [inline] + slab_free_freelist_hook mm/slub.c:1470 [inline] + slab_free mm/slub.c:3012 [inline] + kfree+0xe4/0x2f0 mm/slub.c:3953 + hiddev_connect.cold+0x45/0x5c drivers/hid/usbhid/hiddev.c:914 + hid_connect+0x239/0xbb0 drivers/hid/hid-core.c:1882 + hid_hw_start drivers/hid/hid-core.c:1981 [inline] + hid_hw_start+0xa2/0x130 drivers/hid/hid-core.c:1972 + appleir_probe+0x13e/0x1a0 drivers/hid/hid-appleir.c:308 + hid_device_probe+0x2be/0x3f0 drivers/hid/hid-core.c:2209 + really_probe+0x281/0x650 drivers/base/dd.c:548 + driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709 + __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:816 + bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 + __device_attach+0x217/0x360 drivers/base/dd.c:882 + bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 + device_add+0xae6/0x16f0 drivers/base/core.c:2114 + hid_add_device+0x33c/0x990 drivers/hid/hid-core.c:2365 + usbhid_probe+0xa81/0xfa0 drivers/hid/usbhid/hid-core.c:1386 + usb_probe_interface+0x305/0x7a0 drivers/usb/core/driver.c:361 + really_probe+0x281/0x650 drivers/base/dd.c:548 + driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709 + __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:816 + bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 + __device_attach+0x217/0x360 drivers/base/dd.c:882 + bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 + device_add+0xae6/0x16f0 drivers/base/core.c:2114 + usb_set_configuration+0xdf6/0x1670 drivers/usb/core/message.c:2023 + generic_probe+0x9d/0xd5 drivers/usb/core/generic.c:210 + usb_probe_device+0x99/0x100 drivers/usb/core/driver.c:266 + really_probe+0x281/0x650 drivers/base/dd.c:548 + driver_probe_device+0x101/0x1b0 drivers/base/dd.c:709 + __device_attach_driver+0x1c2/0x220 drivers/base/dd.c:816 + bus_for_each_drv+0x15c/0x1e0 drivers/base/bus.c:454 + __device_attach+0x217/0x360 drivers/base/dd.c:882 + bus_probe_device+0x1e4/0x290 drivers/base/bus.c:514 + device_add+0xae6/0x16f0 drivers/base/core.c:2114 + usb_new_device.cold+0x6a4/0xe79 drivers/usb/core/hub.c:2536 + hub_port_connect drivers/usb/core/hub.c:5098 [inline] + hub_port_connect_change drivers/usb/core/hub.c:5213 [inline] + port_event drivers/usb/core/hub.c:5359 [inline] + hub_event+0x1b5c/0x3640 drivers/usb/core/hub.c:5441 + process_one_work+0x92b/0x1530 kernel/workqueue.c:2269 + worker_thread+0x96/0xe20 kernel/workqueue.c:2415 + kthread+0x318/0x420 kernel/kthread.c:255 + ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352 + +The buggy address belongs to the object at ffff8881cf591900 + which belongs to the cache kmalloc-512 of size 512 +The buggy address is located 264 bytes inside of + 512-byte region [ffff8881cf591900, ffff8881cf591b00) +The buggy address belongs to the page: +page:ffffea00073d6400 refcount:1 mapcount:0 mapping:ffff8881da002500 +index:0x0 compound_mapcount: 0 +flags: 0x200000000010200(slab|head) +raw: 0200000000010200 0000000000000000 0000000100000001 ffff8881da002500 +raw: 0000000000000000 00000000000c000c 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff8881cf591900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff8881cf591980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +> ffff8881cf591a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff8881cf591a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff8881cf591b00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +================================================================== + +In order to avoid opening a disconnected device, we need to check exist +again after acquiring the existance lock, and bail out if necessary. + +Reported-by: syzbot <syzbot+62a1e04fd3ec2abf099e@syzkaller.appspotmail.com> +Cc: Andrey Konovalov <andreyknvl@google.com> +Signed-off-by: Hillf Danton <hdanton@sina.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/usbhid/hiddev.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -308,6 +308,14 @@ static int hiddev_open(struct inode *ino + spin_unlock_irq(&list->hiddev->list_lock); + + mutex_lock(&hiddev->existancelock); ++ /* ++ * recheck exist with existance lock held to ++ * avoid opening a disconnected device ++ */ ++ if (!list->hiddev->exist) { ++ res = -ENODEV; ++ goto bail_unlock; ++ } + if (!list->hiddev->open++) + if (list->hiddev->exist) { + struct hid_device *hid = hiddev->hid; diff --git a/queue-3.16/hid-hiddev-do-cleanup-in-failure-of-opening-a-device.patch b/queue-3.16/hid-hiddev-do-cleanup-in-failure-of-opening-a-device.patch new file mode 100644 index 00000000..07530fb5 --- /dev/null +++ b/queue-3.16/hid-hiddev-do-cleanup-in-failure-of-opening-a-device.patch @@ -0,0 +1,30 @@ +From: Hillf Danton <hdanton@sina.com> +Date: Tue, 6 Aug 2019 16:40:15 +0800 +Subject: HID: hiddev: do cleanup in failure of opening a device + +commit 6d4472d7bec39917b54e4e80245784ea5d60ce49 upstream. + +Undo what we did for opening before releasing the memory slice. + +Reported-by: syzbot <syzbot+62a1e04fd3ec2abf099e@syzkaller.appspotmail.com> +Cc: Andrey Konovalov <andreyknvl@google.com> +Signed-off-by: Hillf Danton <hdanton@sina.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/usbhid/hiddev.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/hid/usbhid/hiddev.c ++++ b/drivers/hid/usbhid/hiddev.c +@@ -322,6 +322,10 @@ static int hiddev_open(struct inode *ino + return 0; + bail_unlock: + mutex_unlock(&hiddev->existancelock); ++ ++ spin_lock_irq(&list->hiddev->list_lock); ++ list_del(&list->node); ++ spin_unlock_irq(&list->hiddev->list_lock); + bail: + file->private_data = NULL; + vfree(list); diff --git a/queue-3.16/input-ff-memless-kill-timer-in-destroy.patch b/queue-3.16/input-ff-memless-kill-timer-in-destroy.patch new file mode 100644 index 00000000..5ac9a9d4 --- /dev/null +++ b/queue-3.16/input-ff-memless-kill-timer-in-destroy.patch @@ -0,0 +1,35 @@ +From: Oliver Neukum <oneukum@suse.com> +Date: Fri, 15 Nov 2019 11:35:05 -0800 +Subject: Input: ff-memless - kill timer in destroy() + +commit fa3a5a1880c91bb92594ad42dfe9eedad7996b86 upstream. + +No timer must be left running when the device goes away. + +Signed-off-by: Oliver Neukum <oneukum@suse.com> +Reported-and-tested-by: syzbot+b6c55daa701fc389e286@syzkaller.appspotmail.com +Link: https://lore.kernel.org/r/1573726121.17351.3.camel@suse.com +Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/input/ff-memless.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/input/ff-memless.c ++++ b/drivers/input/ff-memless.c +@@ -489,6 +489,15 @@ static void ml_ff_destroy(struct ff_devi + { + struct ml_device *ml = ff->private; + ++ /* ++ * Even though we stop all playing effects when tearing down ++ * an input device (via input_device_flush() that calls into ++ * input_ff_flush() that stops and erases all effects), we ++ * do not actually stop the timer, and therefore we should ++ * do it here. ++ */ ++ del_timer_sync(&ml->timer); ++ + kfree(ml->private); + } + diff --git a/queue-3.16/kvm-x86-fix-out-of-bounds-write-in-kvm_get_emulated_cpuid.patch b/queue-3.16/kvm-x86-fix-out-of-bounds-write-in-kvm_get_emulated_cpuid.patch new file mode 100644 index 00000000..646cdada --- /dev/null +++ b/queue-3.16/kvm-x86-fix-out-of-bounds-write-in-kvm_get_emulated_cpuid.patch @@ -0,0 +1,39 @@ +From: Paolo Bonzini <pbonzini@redhat.com> +Date: Wed, 4 Dec 2019 10:28:54 +0100 +Subject: KVM: x86: fix out-of-bounds write in KVM_GET_EMULATED_CPUID + (CVE-2019-19332) + +commit 433f4ba1904100da65a311033f17a9bf586b287e upstream. + +The bounds check was present in KVM_GET_SUPPORTED_CPUID but not +KVM_GET_EMULATED_CPUID. + +Reported-by: syzbot+e3f4897236c4eeb8af4f@syzkaller.appspotmail.com +Fixes: 84cffe499b94 ("kvm: Emulate MOVBE", 2013-10-29) +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kvm/cpuid.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -327,7 +327,7 @@ static inline int __do_cpuid_ent(struct + + r = -E2BIG; + +- if (*nent >= maxnent) ++ if (WARN_ON(*nent >= maxnent)) + goto out; + + do_cpuid_1_ent(entry, function, index); +@@ -599,6 +599,9 @@ out: + static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 func, + u32 idx, int *nent, int maxnent, unsigned int type) + { ++ if (*nent >= maxnent) ++ return -E2BIG; ++ + if (type == KVM_GET_EMULATED_CPUID) + return __do_cpuid_ent_emulated(entry, func, idx, nent, maxnent); + diff --git a/queue-3.16/media-b2c2-flexcop-usb-add-sanity-checking.patch b/queue-3.16/media-b2c2-flexcop-usb-add-sanity-checking.patch new file mode 100644 index 00000000..afdf878e --- /dev/null +++ b/queue-3.16/media-b2c2-flexcop-usb-add-sanity-checking.patch @@ -0,0 +1,30 @@ +From: Oliver Neukum <oneukum@suse.com> +Date: Tue, 30 Jul 2019 09:48:27 +0200 +Subject: media: b2c2-flexcop-usb: add sanity checking + +commit 1b976fc6d684e3282914cdbe7a8d68fdce19095c upstream. + +The driver needs an isochronous endpoint to be present. It will +oops in its absence. Add checking for it. + +Reported-by: syzbot+d93dff37e6a89431c158@syzkaller.appspotmail.com +Signed-off-by: Oliver Neukum <oneukum@suse.com> +Signed-off-by: Sean Young <sean@mess.org> +Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/media/usb/b2c2/flexcop-usb.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/media/usb/b2c2/flexcop-usb.c ++++ b/drivers/media/usb/b2c2/flexcop-usb.c +@@ -508,6 +508,9 @@ static int flexcop_usb_probe(struct usb_ + struct flexcop_device *fc = NULL; + int ret; + ++ if (intf->cur_altsetting->desc.bNumEndpoints < 1) ++ return -ENODEV; ++ + if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) { + err("out of memory\n"); + return -ENOMEM; diff --git a/queue-3.16/media-ttusb-dec-fix-info-leak-in-ttusb_dec_send_command.patch b/queue-3.16/media-ttusb-dec-fix-info-leak-in-ttusb_dec_send_command.patch new file mode 100644 index 00000000..75d10968 --- /dev/null +++ b/queue-3.16/media-ttusb-dec-fix-info-leak-in-ttusb_dec_send_command.patch @@ -0,0 +1,32 @@ +From: Tomas Bortoli <tomasbortoli@gmail.com> +Date: Wed, 31 Jul 2019 12:19:05 -0300 +Subject: media: ttusb-dec: Fix info-leak in ttusb_dec_send_command() + +commit a10feaf8c464c3f9cfdd3a8a7ce17e1c0d498da1 upstream. + +The function at issue does not always initialize each byte allocated +for 'b' and can therefore leak uninitialized memory to a USB device in +the call to usb_bulk_msg() + +Use kzalloc() instead of kmalloc() + +Signed-off-by: Tomas Bortoli <tomasbortoli@gmail.com> +Reported-by: syzbot+0522702e9d67142379f1@syzkaller.appspotmail.com +Signed-off-by: Sean Young <sean@mess.org> +Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/media/usb/ttusb-dec/ttusb_dec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c ++++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c +@@ -272,7 +272,7 @@ static int ttusb_dec_send_command(struct + + dprintk("%s\n", __func__); + +- b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); ++ b = kzalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL); + if (!b) + return -ENOMEM; + diff --git a/queue-3.16/mwifiex-pcie-fix-memory-leak-in-mwifiex_pcie_alloc_cmdrsp_buf.patch b/queue-3.16/mwifiex-pcie-fix-memory-leak-in-mwifiex_pcie_alloc_cmdrsp_buf.patch new file mode 100644 index 00000000..ac0fb31f --- /dev/null +++ b/queue-3.16/mwifiex-pcie-fix-memory-leak-in-mwifiex_pcie_alloc_cmdrsp_buf.patch @@ -0,0 +1,33 @@ +From: Navid Emamdoost <navid.emamdoost@gmail.com> +Date: Fri, 4 Oct 2019 15:08:52 -0500 +Subject: mwifiex: pcie: Fix memory leak in mwifiex_pcie_alloc_cmdrsp_buf + +commit db8fd2cde93227e566a412cf53173ffa227998bc upstream. + +In mwifiex_pcie_alloc_cmdrsp_buf, a new skb is allocated which should be +released if mwifiex_map_pci_memory() fails. The release is added. + +Fixes: fc3314609047 ("mwifiex: use pci_alloc/free_consistent APIs for PCIe") +Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> +Acked-by: Ganapathi Bhat <gbhat@marvell.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/wireless/mwifiex/pcie.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/mwifiex/pcie.c ++++ b/drivers/net/wireless/mwifiex/pcie.c +@@ -876,8 +876,10 @@ static int mwifiex_pcie_alloc_cmdrsp_buf + } + skb_put(skb, MWIFIEX_UPLD_SIZE); + if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, +- PCI_DMA_FROMDEVICE)) ++ PCI_DMA_FROMDEVICE)) { ++ kfree_skb(skb); + return -1; ++ } + + card->cmdrsp_buf = skb; + diff --git a/queue-3.16/mwifiex-pcie-fix-memory-leak-in-mwifiex_pcie_init_evt_ring.patch b/queue-3.16/mwifiex-pcie-fix-memory-leak-in-mwifiex_pcie_init_evt_ring.patch new file mode 100644 index 00000000..1a634d81 --- /dev/null +++ b/queue-3.16/mwifiex-pcie-fix-memory-leak-in-mwifiex_pcie_init_evt_ring.patch @@ -0,0 +1,35 @@ +From: Navid Emamdoost <navid.emamdoost@gmail.com> +Date: Fri, 4 Oct 2019 15:16:48 -0500 +Subject: mwifiex: pcie: Fix memory leak in mwifiex_pcie_init_evt_ring + +commit d10dcb615c8e29d403a24d35f8310a7a53e3050c upstream. + +In mwifiex_pcie_init_evt_ring, a new skb is allocated which should be +released if mwifiex_map_pci_memory() fails. The release for skb and +card->evtbd_ring_vbase is added. + +Fixes: 0732484b47b5 ("mwifiex: separate ring initialization and ring creation routines") +Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> +Acked-by: Ganapathi Bhat <gbhat@marvell.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/wireless/mwifiex/pcie.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/mwifiex/pcie.c ++++ b/drivers/net/wireless/mwifiex/pcie.c +@@ -539,8 +539,11 @@ static int mwifiex_pcie_init_evt_ring(st + skb_put(skb, MAX_EVENT_SIZE); + + if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, +- PCI_DMA_FROMDEVICE)) ++ PCI_DMA_FROMDEVICE)) { ++ kfree_skb(skb); ++ kfree(card->evtbd_ring_vbase); + return -1; ++ } + + buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); + diff --git a/queue-3.16/nl80211-validate-beacon-head.patch b/queue-3.16/nl80211-validate-beacon-head.patch new file mode 100644 index 00000000..7debcfa7 --- /dev/null +++ b/queue-3.16/nl80211-validate-beacon-head.patch @@ -0,0 +1,75 @@ +From: Johannes Berg <johannes.berg@intel.com> +Date: Fri, 20 Sep 2019 21:54:17 +0200 +Subject: nl80211: validate beacon head + +commit f88eb7c0d002a67ef31aeb7850b42ff69abc46dc upstream. + +We currently don't validate the beacon head, i.e. the header, +fixed part and elements that are to go in front of the TIM +element. This means that the variable elements there can be +malformed, e.g. have a length exceeding the buffer size, but +most downstream code from this assumes that this has already +been checked. + +Add the necessary checks to the netlink policy. + +Fixes: ed1b6cc7f80f ("cfg80211/nl80211: add beacon settings") +Link: https://lore.kernel.org/r/1569009255-I7ac7fbe9436e9d8733439eab8acbbd35e55c74ef@changeid +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/wireless/nl80211.c | 35 +++++++++++++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -208,6 +208,36 @@ cfg80211_get_dev_from_info(struct net *n + return __cfg80211_rdev_from_attrs(netns, info->attrs); + } + ++static int validate_beacon_head(const struct nlattr *attr) ++{ ++ const u8 *data = nla_data(attr); ++ unsigned int len = nla_len(attr); ++ const struct element *elem; ++ const struct ieee80211_mgmt *mgmt = (void *)data; ++ unsigned int fixedlen = offsetof(struct ieee80211_mgmt, ++ u.beacon.variable); ++ ++ if (len < fixedlen) ++ goto err; ++ ++ if (ieee80211_hdrlen(mgmt->frame_control) != ++ offsetof(struct ieee80211_mgmt, u.beacon)) ++ goto err; ++ ++ data += fixedlen; ++ len -= fixedlen; ++ ++ for_each_element(elem, data, len) { ++ /* nothing */ ++ } ++ ++ if (for_each_element_completed(elem, data, len)) ++ return 0; ++ ++err: ++ return -EINVAL; ++} ++ + /* policy for the attributes */ + static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { + [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, +@@ -3125,6 +3155,11 @@ static int nl80211_parse_beacon(struct n + memset(bcn, 0, sizeof(*bcn)); + + if (attrs[NL80211_ATTR_BEACON_HEAD]) { ++ int ret = validate_beacon_head(attrs[NL80211_ATTR_BEACON_HEAD]); ++ ++ if (ret) ++ return ret; ++ + bcn->head = nla_data(attrs[NL80211_ATTR_BEACON_HEAD]); + bcn->head_len = nla_len(attrs[NL80211_ATTR_BEACON_HEAD]); + if (!bcn->head_len) diff --git a/queue-3.16/scsi-bfa-release-allocated-memory-in-case-of-error.patch b/queue-3.16/scsi-bfa-release-allocated-memory-in-case-of-error.patch new file mode 100644 index 00000000..f6c6c0a2 --- /dev/null +++ b/queue-3.16/scsi-bfa-release-allocated-memory-in-case-of-error.patch @@ -0,0 +1,31 @@ +From: Navid Emamdoost <navid.emamdoost@gmail.com> +Date: Tue, 10 Sep 2019 18:44:15 -0500 +Subject: scsi: bfa: release allocated memory in case of error + +commit 0e62395da2bd5166d7c9e14cbc7503b256a34cb0 upstream. + +In bfad_im_get_stats if bfa_port_get_stats fails, allocated memory needs to +be released. + +Link: https://lore.kernel.org/r/20190910234417.22151-1-navid.emamdoost@gmail.com +Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/scsi/bfa/bfad_attr.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/bfa/bfad_attr.c ++++ b/drivers/scsi/bfa/bfad_attr.c +@@ -282,8 +282,10 @@ bfad_im_get_stats(struct Scsi_Host *shos + rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa), + fcstats, bfad_hcb_comp, &fcomp); + spin_unlock_irqrestore(&bfad->bfad_lock, flags); +- if (rc != BFA_STATUS_OK) ++ if (rc != BFA_STATUS_OK) { ++ kfree(fcstats); + return NULL; ++ } + + wait_for_completion(&fcomp.comp); + diff --git a/queue-3.16/series b/queue-3.16/series index ce298cbf..97d933b5 100644 --- a/queue-3.16/series +++ b/queue-3.16/series @@ -45,3 +45,27 @@ cifs-fix-max-ea-value-size.patch fuse-fix-missing-unlock_page-in-fuse_writepage.patch cifs-fix-oplock-handling-for-smb-2.1-protocols.patch i2c-riic-clear-nack-in-tend-isr.patch +android-binder-remove-waitqueue-when-thread-exits.patch +media-b2c2-flexcop-usb-add-sanity-checking.patch +cfg80211-add-and-use-strongly-typed-element-iteration-macros.patch +nl80211-validate-beacon-head.patch +wimax-i2400-fix-memory-leak.patch +wimax-i2400-fix-memory-leak-in-i2400m_op_rfkill_sw_toggle.patch +can-gs_usb-gs_can_open-prevent-memory-leak.patch +mwifiex-pcie-fix-memory-leak-in-mwifiex_pcie_alloc_cmdrsp_buf.patch +mwifiex-pcie-fix-memory-leak-in-mwifiex_pcie_init_evt_ring.patch +crypto-user-fix-crypto_alg_match-race.patch +crypto-user-fix-memory-leak-in-crypto_report.patch +scsi-bfa-release-allocated-memory-in-case-of-error.patch +appletalk-fix-potential-null-pointer-dereference-in.patch +kvm-x86-fix-out-of-bounds-write-in-kvm_get_emulated_cpuid.patch +usb-adutux-remove-redundant-variable-minor.patch +usb-adutux-fix-use-after-free-on-disconnect.patch +input-ff-memless-kill-timer-in-destroy.patch +hid-hiddev-do-cleanup-in-failure-of-opening-a-device.patch +hid-hiddev-avoid-opening-a-disconnected-device.patch +usb-iowarrior-fix-deadlock-on-disconnect.patch +usb-iowarrior-fix-use-after-free-on-disconnect.patch +hid-fix-assumption-that-devices-have-inputs.patch +media-ttusb-dec-fix-info-leak-in-ttusb_dec_send_command.patch +can-peak_usb-fix-slab-info-leak.patch diff --git a/queue-3.16/usb-adutux-fix-use-after-free-on-disconnect.patch b/queue-3.16/usb-adutux-fix-use-after-free-on-disconnect.patch new file mode 100644 index 00000000..188318ea --- /dev/null +++ b/queue-3.16/usb-adutux-fix-use-after-free-on-disconnect.patch @@ -0,0 +1,48 @@ +From: Johan Hovold <johan@kernel.org> +Date: Wed, 25 Sep 2019 11:29:12 +0200 +Subject: USB: adutux: fix use-after-free on disconnect + +commit 44efc269db7929f6275a1fa927ef082e533ecde0 upstream. + +The driver was clearing its struct usb_device pointer, which it used as +an inverted disconnected flag, before deregistering the character device +and without serialising against racing release(). + +This could lead to a use-after-free if a racing release() callback +observes the cleared pointer and frees the driver data before +disconnect() is finished with it. + +This could also lead to NULL-pointer dereferences in a racing open(). + +Fixes: f08812d5eb8f ("USB: FIx locks and urb->status in adutux (updated)") +Reported-by: syzbot+0243cb250a51eeefb8cc@syzkaller.appspotmail.com +Tested-by: syzbot+0243cb250a51eeefb8cc@syzkaller.appspotmail.com +Signed-off-by: Johan Hovold <johan@kernel.org> +Link: https://lore.kernel.org/r/20190925092913.8608-1-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/misc/adutux.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/usb/misc/adutux.c ++++ b/drivers/usb/misc/adutux.c +@@ -799,14 +799,15 @@ static void adu_disconnect(struct usb_in + + dev = usb_get_intfdata(interface); + +- mutex_lock(&dev->mtx); /* not interruptible */ +- dev->udev = NULL; /* poison */ + usb_deregister_dev(interface, &adu_class); +- mutex_unlock(&dev->mtx); + + mutex_lock(&adutux_mutex); + usb_set_intfdata(interface, NULL); + ++ mutex_lock(&dev->mtx); /* not interruptible */ ++ dev->udev = NULL; /* poison */ ++ mutex_unlock(&dev->mtx); ++ + /* if the device is not opened, then we clean up right now */ + if (!dev->open_count) + adu_delete(dev); diff --git a/queue-3.16/usb-adutux-remove-redundant-variable-minor.patch b/queue-3.16/usb-adutux-remove-redundant-variable-minor.patch new file mode 100644 index 00000000..dfa83cbc --- /dev/null +++ b/queue-3.16/usb-adutux-remove-redundant-variable-minor.patch @@ -0,0 +1,37 @@ +From: Colin Ian King <colin.king@canonical.com> +Date: Tue, 7 Nov 2017 11:45:27 +0000 +Subject: USB: adutux: remove redundant variable minor + +commit 8444efc4a052332d643ed5c8aebcca148c7de032 upstream. + +Variable minor is being assigned but never read, hence it is redundant +and can be removed. Cleans up clang warning: + +drivers/usb/misc/adutux.c:770:2: warning: Value stored to 'minor' is +never read + +Signed-off-by: Colin Ian King <colin.king@canonical.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16 so that commit 44efc269db79 "USB: adutux: fix + use-after-free on disconnect" applies cleanly] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/misc/adutux.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/usb/misc/adutux.c ++++ b/drivers/usb/misc/adutux.c +@@ -796,13 +796,11 @@ error: + static void adu_disconnect(struct usb_interface *interface) + { + struct adu_device *dev; +- int minor; + + dev = usb_get_intfdata(interface); + + mutex_lock(&dev->mtx); /* not interruptible */ + dev->udev = NULL; /* poison */ +- minor = dev->minor; + usb_deregister_dev(interface, &adu_class); + mutex_unlock(&dev->mtx); + diff --git a/queue-3.16/usb-iowarrior-fix-deadlock-on-disconnect.patch b/queue-3.16/usb-iowarrior-fix-deadlock-on-disconnect.patch new file mode 100644 index 00000000..5077ee19 --- /dev/null +++ b/queue-3.16/usb-iowarrior-fix-deadlock-on-disconnect.patch @@ -0,0 +1,46 @@ +From: Oliver Neukum <oneukum@suse.com> +Date: Thu, 8 Aug 2019 11:27:28 +0200 +Subject: usb: iowarrior: fix deadlock on disconnect + +commit c468a8aa790e0dfe0a7f8a39db282d39c2c00b46 upstream. + +We have to drop the mutex before we close() upon disconnect() +as close() needs the lock. This is safe to do by dropping the +mutex as intfdata is already set to NULL, so open() will fail. + +Fixes: 03f36e885fc26 ("USB: open disconnect race in iowarrior") +Reported-by: syzbot+a64a382964bf6c71a9c0@syzkaller.appspotmail.com +Signed-off-by: Oliver Neukum <oneukum@suse.com> +Link: https://lore.kernel.org/r/20190808092728.23417-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/misc/iowarrior.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -898,19 +898,20 @@ static void iowarrior_disconnect(struct + dev = usb_get_intfdata(interface); + mutex_lock(&iowarrior_open_disc_lock); + usb_set_intfdata(interface, NULL); ++ /* prevent device read, write and ioctl */ ++ dev->present = 0; + + minor = dev->minor; ++ mutex_unlock(&iowarrior_open_disc_lock); ++ /* give back our minor - this will call close() locks need to be dropped at this point*/ + +- /* give back our minor */ + usb_deregister_dev(interface, &iowarrior_class); + + mutex_lock(&dev->mutex); + + /* prevent device read, write and ioctl */ +- dev->present = 0; + + mutex_unlock(&dev->mutex); +- mutex_unlock(&iowarrior_open_disc_lock); + + if (dev->opened) { + /* There is a process that holds a filedescriptor to the device , diff --git a/queue-3.16/usb-iowarrior-fix-use-after-free-on-disconnect.patch b/queue-3.16/usb-iowarrior-fix-use-after-free-on-disconnect.patch new file mode 100644 index 00000000..c2de504f --- /dev/null +++ b/queue-3.16/usb-iowarrior-fix-use-after-free-on-disconnect.patch @@ -0,0 +1,59 @@ +From: Johan Hovold <johan@kernel.org> +Date: Wed, 9 Oct 2019 12:48:41 +0200 +Subject: USB: iowarrior: fix use-after-free on disconnect + +commit edc4746f253d907d048de680a621e121517f484b upstream. + +A recent fix addressing a deadlock on disconnect introduced a new bug +by moving the present flag out of the critical section protected by the +driver-data mutex. This could lead to a racing release() freeing the +driver data before disconnect() is done with it. + +Due to insufficient locking a related use-after-free could be triggered +also before the above mentioned commit. Specifically, the driver needs +to hold the driver-data mutex also while checking the opened flag at +disconnect(). + +Fixes: c468a8aa790e ("usb: iowarrior: fix deadlock on disconnect") +Fixes: 946b960d13c1 ("USB: add driver for iowarrior devices.") +Reported-by: syzbot+0761012cebf7bdb38137@syzkaller.appspotmail.com +Signed-off-by: Johan Hovold <johan@kernel.org> +Link: https://lore.kernel.org/r/20191009104846.5925-2-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/misc/iowarrior.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -898,8 +898,6 @@ static void iowarrior_disconnect(struct + dev = usb_get_intfdata(interface); + mutex_lock(&iowarrior_open_disc_lock); + usb_set_intfdata(interface, NULL); +- /* prevent device read, write and ioctl */ +- dev->present = 0; + + minor = dev->minor; + mutex_unlock(&iowarrior_open_disc_lock); +@@ -910,8 +908,7 @@ static void iowarrior_disconnect(struct + mutex_lock(&dev->mutex); + + /* prevent device read, write and ioctl */ +- +- mutex_unlock(&dev->mutex); ++ dev->present = 0; + + if (dev->opened) { + /* There is a process that holds a filedescriptor to the device , +@@ -921,8 +918,10 @@ static void iowarrior_disconnect(struct + usb_kill_urb(dev->int_in_urb); + wake_up_interruptible(&dev->read_wait); + wake_up_interruptible(&dev->write_wait); ++ mutex_unlock(&dev->mutex); + } else { + /* no process is using the device, cleanup now */ ++ mutex_unlock(&dev->mutex); + iowarrior_delete(dev); + } + diff --git a/queue-3.16/wimax-i2400-fix-memory-leak-in-i2400m_op_rfkill_sw_toggle.patch b/queue-3.16/wimax-i2400-fix-memory-leak-in-i2400m_op_rfkill_sw_toggle.patch new file mode 100644 index 00000000..f0e34194 --- /dev/null +++ b/queue-3.16/wimax-i2400-fix-memory-leak-in-i2400m_op_rfkill_sw_toggle.patch @@ -0,0 +1,36 @@ +From: Navid Emamdoost <navid.emamdoost@gmail.com> +Date: Fri, 25 Oct 2019 23:53:30 -0500 +Subject: wimax: i2400: Fix memory leak in i2400m_op_rfkill_sw_toggle + +commit 6f3ef5c25cc762687a7341c18cbea5af54461407 upstream. + +In the implementation of i2400m_op_rfkill_sw_toggle() the allocated +buffer for cmd should be released before returning. The +documentation for i2400m_msg_to_dev() says when it returns the buffer +can be reused. Meaning cmd should be released in either case. Move +kfree(cmd) before return to be reached by all execution paths. + +Fixes: 2507e6ab7a9a ("wimax: i2400: fix memory leak") +Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/wimax/i2400m/op-rfkill.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wimax/i2400m/op-rfkill.c ++++ b/drivers/net/wimax/i2400m/op-rfkill.c +@@ -142,12 +142,12 @@ int i2400m_op_rfkill_sw_toggle(struct wi + "%d\n", result); + result = 0; + error_cmd: +- kfree(cmd); + kfree_skb(ack_skb); + error_msg_to_dev: + error_alloc: + d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n", + wimax_dev, state, result); ++ kfree(cmd); + return result; + } + diff --git a/queue-3.16/wimax-i2400-fix-memory-leak.patch b/queue-3.16/wimax-i2400-fix-memory-leak.patch new file mode 100644 index 00000000..232e2c5e --- /dev/null +++ b/queue-3.16/wimax-i2400-fix-memory-leak.patch @@ -0,0 +1,26 @@ +From: Navid Emamdoost <navid.emamdoost@gmail.com> +Date: Tue, 10 Sep 2019 18:01:40 -0500 +Subject: wimax: i2400: fix memory leak + +commit 2507e6ab7a9a440773be476141a255934468c5ef upstream. + +In i2400m_op_rfkill_sw_toggle cmd buffer should be released along with +skb response. + +Signed-off-by: Navid Emamdoost <navid.emamdoost@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/wimax/i2400m/op-rfkill.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wimax/i2400m/op-rfkill.c ++++ b/drivers/net/wimax/i2400m/op-rfkill.c +@@ -142,6 +142,7 @@ int i2400m_op_rfkill_sw_toggle(struct wi + "%d\n", result); + result = 0; + error_cmd: ++ kfree(cmd); + kfree_skb(ack_skb); + error_msg_to_dev: + error_alloc: |