From f15e0b84972b3a99ea6e02814f9cbe2b734c7c68 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 4 Jul 2020 12:29:57 -0400 Subject: [PATCH] Fixes for 4.14 Signed-off-by: Sasha Levin --- ...b-avoid-suspicious-rcu-usage-warning.patch | 109 +++++++++++++++++ ...b-fix-stack-overruns-with-slub_stats.patch | 90 ++++++++++++++ ...rrupted-freechain-in-deactivate_slab.patch | 115 ++++++++++++++++++ queue-4.14/series | 5 + ...missing-kfree-dev-buf-in-usbtest_dis.patch | 69 +++++++++++ ...5xx-fix-use-after-free-after-removal.patch | 49 ++++++++ 6 files changed, 437 insertions(+) create mode 100644 queue-4.14/kgdb-avoid-suspicious-rcu-usage-warning.patch create mode 100644 queue-4.14/mm-slub-fix-stack-overruns-with-slub_stats.patch create mode 100644 queue-4.14/mm-slub.c-fix-corrupted-freechain-in-deactivate_slab.patch create mode 100644 queue-4.14/usb-usbtest-fix-missing-kfree-dev-buf-in-usbtest_dis.patch create mode 100644 queue-4.14/usbnet-smsc95xx-fix-use-after-free-after-removal.patch diff --git a/queue-4.14/kgdb-avoid-suspicious-rcu-usage-warning.patch b/queue-4.14/kgdb-avoid-suspicious-rcu-usage-warning.patch new file mode 100644 index 00000000000..7f78a7b5a6d --- /dev/null +++ b/queue-4.14/kgdb-avoid-suspicious-rcu-usage-warning.patch @@ -0,0 +1,109 @@ +From 9274e0bfa24de83ccd7fc7f4ab5349be9dd39d62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Jun 2020 15:47:39 -0700 +Subject: kgdb: Avoid suspicious RCU usage warning + +From: Douglas Anderson + +[ Upstream commit 440ab9e10e2e6e5fd677473ee6f9e3af0f6904d6 ] + +At times when I'm using kgdb I see a splat on my console about +suspicious RCU usage. I managed to come up with a case that could +reproduce this that looked like this: + + WARNING: suspicious RCU usage + 5.7.0-rc4+ #609 Not tainted + ----------------------------- + kernel/pid.c:395 find_task_by_pid_ns() needs rcu_read_lock() protection! + + other info that might help us debug this: + + rcu_scheduler_active = 2, debug_locks = 1 + 3 locks held by swapper/0/1: + #0: ffffff81b6b8e988 (&dev->mutex){....}-{3:3}, at: __device_attach+0x40/0x13c + #1: ffffffd01109e9e8 (dbg_master_lock){....}-{2:2}, at: kgdb_cpu_enter+0x20c/0x7ac + #2: ffffffd01109ea90 (dbg_slave_lock){....}-{2:2}, at: kgdb_cpu_enter+0x3ec/0x7ac + + stack backtrace: + CPU: 7 PID: 1 Comm: swapper/0 Not tainted 5.7.0-rc4+ #609 + Hardware name: Google Cheza (rev3+) (DT) + Call trace: + dump_backtrace+0x0/0x1b8 + show_stack+0x1c/0x24 + dump_stack+0xd4/0x134 + lockdep_rcu_suspicious+0xf0/0x100 + find_task_by_pid_ns+0x5c/0x80 + getthread+0x8c/0xb0 + gdb_serial_stub+0x9d4/0xd04 + kgdb_cpu_enter+0x284/0x7ac + kgdb_handle_exception+0x174/0x20c + kgdb_brk_fn+0x24/0x30 + call_break_hook+0x6c/0x7c + brk_handler+0x20/0x5c + do_debug_exception+0x1c8/0x22c + el1_sync_handler+0x3c/0xe4 + el1_sync+0x7c/0x100 + rpmh_rsc_probe+0x38/0x420 + platform_drv_probe+0x94/0xb4 + really_probe+0x134/0x300 + driver_probe_device+0x68/0x100 + __device_attach_driver+0x90/0xa8 + bus_for_each_drv+0x84/0xcc + __device_attach+0xb4/0x13c + device_initial_probe+0x18/0x20 + bus_probe_device+0x38/0x98 + device_add+0x38c/0x420 + +If I understand properly we should just be able to blanket kgdb under +one big RCU read lock and the problem should go away. We'll add it to +the beast-of-a-function known as kgdb_cpu_enter(). + +With this I no longer get any splats and things seem to work fine. + +Signed-off-by: Douglas Anderson +Link: https://lore.kernel.org/r/20200602154729.v2.1.I70e0d4fd46d5ed2aaf0c98a355e8e1b7a5bb7e4e@changeid +Signed-off-by: Daniel Thompson +Signed-off-by: Sasha Levin +--- + kernel/debug/debug_core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c +index 159a53ff27162..694fcd0492827 100644 +--- a/kernel/debug/debug_core.c ++++ b/kernel/debug/debug_core.c +@@ -489,6 +489,7 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs, + arch_kgdb_ops.disable_hw_break(regs); + + acquirelock: ++ rcu_read_lock(); + /* + * Interrupts will be restored by the 'trap return' code, except when + * single stepping. +@@ -545,6 +546,7 @@ return_normal: + atomic_dec(&slaves_in_kgdb); + dbg_touch_watchdogs(); + local_irq_restore(flags); ++ rcu_read_unlock(); + return 0; + } + cpu_relax(); +@@ -563,6 +565,7 @@ return_normal: + raw_spin_unlock(&dbg_master_lock); + dbg_touch_watchdogs(); + local_irq_restore(flags); ++ rcu_read_unlock(); + + goto acquirelock; + } +@@ -682,6 +685,7 @@ kgdb_restore: + raw_spin_unlock(&dbg_master_lock); + dbg_touch_watchdogs(); + local_irq_restore(flags); ++ rcu_read_unlock(); + + return kgdb_info[cpu].ret_state; + } +-- +2.25.1 + diff --git a/queue-4.14/mm-slub-fix-stack-overruns-with-slub_stats.patch b/queue-4.14/mm-slub-fix-stack-overruns-with-slub_stats.patch new file mode 100644 index 00000000000..7b648273ef9 --- /dev/null +++ b/queue-4.14/mm-slub-fix-stack-overruns-with-slub_stats.patch @@ -0,0 +1,90 @@ +From df8b4708b18129dde2c37f021b813db9f14cd639 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Jun 2020 21:45:57 -0700 +Subject: mm/slub: fix stack overruns with SLUB_STATS + +From: Qian Cai + +[ Upstream commit a68ee0573991e90af2f1785db309206408bad3e5 ] + +There is no need to copy SLUB_STATS items from root memcg cache to new +memcg cache copies. Doing so could result in stack overruns because the +store function only accepts 0 to clear the stat and returns an error for +everything else while the show method would print out the whole stat. + +Then, the mismatch of the lengths returns from show and store methods +happens in memcg_propagate_slab_attrs(): + + else if (root_cache->max_attr_size < ARRAY_SIZE(mbuf)) + buf = mbuf; + +max_attr_size is only 2 from slab_attr_store(), then, it uses mbuf[64] +in show_stat() later where a bounch of sprintf() would overrun the stack +variable. Fix it by always allocating a page of buffer to be used in +show_stat() if SLUB_STATS=y which should only be used for debug purpose. + + # echo 1 > /sys/kernel/slab/fs_cache/shrink + BUG: KASAN: stack-out-of-bounds in number+0x421/0x6e0 + Write of size 1 at addr ffffc900256cfde0 by task kworker/76:0/53251 + + Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40 07/10/2019 + Workqueue: memcg_kmem_cache memcg_kmem_cache_create_func + Call Trace: + number+0x421/0x6e0 + vsnprintf+0x451/0x8e0 + sprintf+0x9e/0xd0 + show_stat+0x124/0x1d0 + alloc_slowpath_show+0x13/0x20 + __kmem_cache_create+0x47a/0x6b0 + + addr ffffc900256cfde0 is located in stack of task kworker/76:0/53251 at offset 0 in frame: + process_one_work+0x0/0xb90 + + this frame has 1 object: + [32, 72) 'lockdep_map' + + Memory state around the buggy address: + ffffc900256cfc80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffffc900256cfd00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + >ffffc900256cfd80: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 + ^ + ffffc900256cfe00: 00 00 00 00 00 f2 f2 f2 00 00 00 00 00 00 00 00 + ffffc900256cfe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ================================================================== + Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: __kmem_cache_create+0x6ac/0x6b0 + Workqueue: memcg_kmem_cache memcg_kmem_cache_create_func + Call Trace: + __kmem_cache_create+0x6ac/0x6b0 + +Fixes: 107dab5c92d5 ("slub: slub-specific propagation changes") +Signed-off-by: Qian Cai +Signed-off-by: Andrew Morton +Cc: Glauber Costa +Cc: Christoph Lameter +Cc: Pekka Enberg +Cc: David Rientjes +Cc: Joonsoo Kim +Link: http://lkml.kernel.org/r/20200429222356.4322-1-cai@lca.pw +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/slub.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/mm/slub.c b/mm/slub.c +index 66b7987129337..09d4cc4391bb2 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -5601,7 +5601,8 @@ static void memcg_propagate_slab_attrs(struct kmem_cache *s) + */ + if (buffer) + buf = buffer; +- else if (root_cache->max_attr_size < ARRAY_SIZE(mbuf)) ++ else if (root_cache->max_attr_size < ARRAY_SIZE(mbuf) && ++ !IS_ENABLED(CONFIG_SLUB_STATS)) + buf = mbuf; + else { + buffer = (char *) get_zeroed_page(GFP_KERNEL); +-- +2.25.1 + diff --git a/queue-4.14/mm-slub.c-fix-corrupted-freechain-in-deactivate_slab.patch b/queue-4.14/mm-slub.c-fix-corrupted-freechain-in-deactivate_slab.patch new file mode 100644 index 00000000000..1b984b681e6 --- /dev/null +++ b/queue-4.14/mm-slub.c-fix-corrupted-freechain-in-deactivate_slab.patch @@ -0,0 +1,115 @@ +From bab3a1510ccad5e948c394d1ebf8f315081bed50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Jun 2020 21:45:47 -0700 +Subject: mm/slub.c: fix corrupted freechain in deactivate_slab() + +From: Dongli Zhang + +[ Upstream commit 52f23478081ae0dcdb95d1650ea1e7d52d586829 ] + +The slub_debug is able to fix the corrupted slab freelist/page. +However, alloc_debug_processing() only checks the validity of current +and next freepointer during allocation path. As a result, once some +objects have their freepointers corrupted, deactivate_slab() may lead to +page fault. + +Below is from a test kernel module when 'slub_debug=PUF,kmalloc-128 +slub_nomerge'. The test kernel corrupts the freepointer of one free +object on purpose. Unfortunately, deactivate_slab() does not detect it +when iterating the freechain. + + BUG: unable to handle page fault for address: 00000000123456f8 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 0 P4D 0 + Oops: 0000 [#1] SMP PTI + ... ... + RIP: 0010:deactivate_slab.isra.92+0xed/0x490 + ... ... + Call Trace: + ___slab_alloc+0x536/0x570 + __slab_alloc+0x17/0x30 + __kmalloc+0x1d9/0x200 + ext4_htree_store_dirent+0x30/0xf0 + htree_dirblock_to_tree+0xcb/0x1c0 + ext4_htree_fill_tree+0x1bc/0x2d0 + ext4_readdir+0x54f/0x920 + iterate_dir+0x88/0x190 + __x64_sys_getdents+0xa6/0x140 + do_syscall_64+0x49/0x170 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Therefore, this patch adds extra consistency check in deactivate_slab(). +Once an object's freepointer is corrupted, all following objects +starting at this object are isolated. + +[akpm@linux-foundation.org: fix build with CONFIG_SLAB_DEBUG=n] +Signed-off-by: Dongli Zhang +Signed-off-by: Andrew Morton +Cc: Joe Jin +Cc: Christoph Lameter +Cc: Pekka Enberg +Cc: David Rientjes +Cc: Joonsoo Kim +Link: http://lkml.kernel.org/r/20200331031450.12182-1-dongli.zhang@oracle.com +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/slub.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/mm/slub.c b/mm/slub.c +index 8807a0c98a675..66b7987129337 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -658,6 +658,20 @@ static void slab_fix(struct kmem_cache *s, char *fmt, ...) + va_end(args); + } + ++static bool freelist_corrupted(struct kmem_cache *s, struct page *page, ++ void *freelist, void *nextfree) ++{ ++ if ((s->flags & SLAB_CONSISTENCY_CHECKS) && ++ !check_valid_pointer(s, page, nextfree)) { ++ object_err(s, page, freelist, "Freechain corrupt"); ++ freelist = NULL; ++ slab_fix(s, "Isolate corrupted freechain"); ++ return true; ++ } ++ ++ return false; ++} ++ + static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p) + { + unsigned int off; /* Offset of last byte */ +@@ -1339,6 +1353,11 @@ static inline void inc_slabs_node(struct kmem_cache *s, int node, + static inline void dec_slabs_node(struct kmem_cache *s, int node, + int objects) {} + ++static bool freelist_corrupted(struct kmem_cache *s, struct page *page, ++ void *freelist, void *nextfree) ++{ ++ return false; ++} + #endif /* CONFIG_SLUB_DEBUG */ + + /* +@@ -2029,6 +2048,14 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page, + void *prior; + unsigned long counters; + ++ /* ++ * If 'nextfree' is invalid, it is possible that the object at ++ * 'freelist' is already corrupted. So isolate all objects ++ * starting at 'freelist'. ++ */ ++ if (freelist_corrupted(s, page, freelist, nextfree)) ++ break; ++ + do { + prior = page->freelist; + counters = page->counters; +-- +2.25.1 + diff --git a/queue-4.14/series b/queue-4.14/series index 5b2b3c753ef..261715fe049 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -3,3 +3,8 @@ btrfs-cow_file_range-num_bytes-and-disk_num_bytes-ar.patch btrfs-fix-data-block-group-relocation-failure-due-to.patch mm-fix-swap-cache-node-allocation-mask.patch edac-amd64-read-back-the-scrub-rate-pci-register-on-.patch +usbnet-smsc95xx-fix-use-after-free-after-removal.patch +mm-slub.c-fix-corrupted-freechain-in-deactivate_slab.patch +mm-slub-fix-stack-overruns-with-slub_stats.patch +usb-usbtest-fix-missing-kfree-dev-buf-in-usbtest_dis.patch +kgdb-avoid-suspicious-rcu-usage-warning.patch diff --git a/queue-4.14/usb-usbtest-fix-missing-kfree-dev-buf-in-usbtest_dis.patch b/queue-4.14/usb-usbtest-fix-missing-kfree-dev-buf-in-usbtest_dis.patch new file mode 100644 index 00000000000..f1020d92134 --- /dev/null +++ b/queue-4.14/usb-usbtest-fix-missing-kfree-dev-buf-in-usbtest_dis.patch @@ -0,0 +1,69 @@ +From f5376eacf4e0be670ba2ed17a22aa575a1e24ce0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2020 11:52:10 +0800 +Subject: usb: usbtest: fix missing kfree(dev->buf) in usbtest_disconnect + +From: Zqiang + +[ Upstream commit 28ebeb8db77035e058a510ce9bd17c2b9a009dba ] + +BUG: memory leak +unreferenced object 0xffff888055046e00 (size 256): + comm "kworker/2:9", pid 2570, jiffies 4294942129 (age 1095.500s) + hex dump (first 32 bytes): + 00 70 04 55 80 88 ff ff 18 bb 5a 81 ff ff ff ff .p.U......Z..... + f5 96 78 81 ff ff ff ff 37 de 8e 81 ff ff ff ff ..x.....7....... + backtrace: + [<00000000d121dccf>] kmemleak_alloc_recursive +include/linux/kmemleak.h:43 [inline] + [<00000000d121dccf>] slab_post_alloc_hook mm/slab.h:586 [inline] + [<00000000d121dccf>] slab_alloc_node mm/slub.c:2786 [inline] + [<00000000d121dccf>] slab_alloc mm/slub.c:2794 [inline] + [<00000000d121dccf>] kmem_cache_alloc_trace+0x15e/0x2d0 mm/slub.c:2811 + [<000000005c3c3381>] kmalloc include/linux/slab.h:555 [inline] + [<000000005c3c3381>] usbtest_probe+0x286/0x19d0 +drivers/usb/misc/usbtest.c:2790 + [<000000001cec6910>] usb_probe_interface+0x2bd/0x870 +drivers/usb/core/driver.c:361 + [<000000007806c118>] really_probe+0x48d/0x8f0 drivers/base/dd.c:551 + [<00000000a3308c3e>] driver_probe_device+0xfc/0x2a0 drivers/base/dd.c:724 + [<000000003ef66004>] __device_attach_driver+0x1b6/0x240 +drivers/base/dd.c:831 + [<00000000eee53e97>] bus_for_each_drv+0x14e/0x1e0 drivers/base/bus.c:431 + [<00000000bb0648d0>] __device_attach+0x1f9/0x350 drivers/base/dd.c:897 + [<00000000838b324a>] device_initial_probe+0x1a/0x20 drivers/base/dd.c:944 + [<0000000030d501c1>] bus_probe_device+0x1e1/0x280 drivers/base/bus.c:491 + [<000000005bd7adef>] device_add+0x131d/0x1c40 drivers/base/core.c:2504 + [<00000000a0937814>] usb_set_configuration+0xe84/0x1ab0 +drivers/usb/core/message.c:2030 + [<00000000e3934741>] generic_probe+0x6a/0xe0 drivers/usb/core/generic.c:210 + [<0000000098ade0f1>] usb_probe_device+0x90/0xd0 +drivers/usb/core/driver.c:266 + [<000000007806c118>] really_probe+0x48d/0x8f0 drivers/base/dd.c:551 + [<00000000a3308c3e>] driver_probe_device+0xfc/0x2a0 drivers/base/dd.c:724 + +Acked-by: Alan Stern +Reported-by: Kyungtae Kim +Signed-off-by: Zqiang +Link: https://lore.kernel.org/r/20200612035210.20494-1-qiang.zhang@windriver.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/misc/usbtest.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c +index b3fc602b2e247..49476c0304b27 100644 +--- a/drivers/usb/misc/usbtest.c ++++ b/drivers/usb/misc/usbtest.c +@@ -2769,6 +2769,7 @@ static void usbtest_disconnect(struct usb_interface *intf) + + usb_set_intfdata(intf, NULL); + dev_dbg(&intf->dev, "disconnect\n"); ++ kfree(dev->buf); + kfree(dev); + } + +-- +2.25.1 + diff --git a/queue-4.14/usbnet-smsc95xx-fix-use-after-free-after-removal.patch b/queue-4.14/usbnet-smsc95xx-fix-use-after-free-after-removal.patch new file mode 100644 index 00000000000..9b93ec81681 --- /dev/null +++ b/queue-4.14/usbnet-smsc95xx-fix-use-after-free-after-removal.patch @@ -0,0 +1,49 @@ +From 4fc9dff44514e3c00807366b41bae2e285b0e3bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2020 13:43:26 +0300 +Subject: usbnet: smsc95xx: Fix use-after-free after removal + +From: Tuomas Tynkkynen + +[ Upstream commit b835a71ef64a61383c414d6bf2896d2c0161deca ] + +Syzbot reports an use-after-free in workqueue context: + +BUG: KASAN: use-after-free in mutex_unlock+0x19/0x40 kernel/locking/mutex.c:737 + mutex_unlock+0x19/0x40 kernel/locking/mutex.c:737 + __smsc95xx_mdio_read drivers/net/usb/smsc95xx.c:217 [inline] + smsc95xx_mdio_read+0x583/0x870 drivers/net/usb/smsc95xx.c:278 + check_carrier+0xd1/0x2e0 drivers/net/usb/smsc95xx.c:644 + process_one_work+0x777/0xf90 kernel/workqueue.c:2274 + worker_thread+0xa8f/0x1430 kernel/workqueue.c:2420 + kthread+0x2df/0x300 kernel/kthread.c:255 + +It looks like that smsc95xx_unbind() is freeing the structures that are +still in use by the concurrently running workqueue callback. Thus switch +to using cancel_delayed_work_sync() to ensure the work callback really +is no longer active. + +Reported-by: syzbot+29dc7d4ae19b703ff947@syzkaller.appspotmail.com +Signed-off-by: Tuomas Tynkkynen +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/usb/smsc95xx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index fc48da1c702d7..bcb99bee450a5 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -1338,7 +1338,7 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) + struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); + + if (pdata) { +- cancel_delayed_work(&pdata->carrier_check); ++ cancel_delayed_work_sync(&pdata->carrier_check); + netif_dbg(dev, ifdown, dev->net, "free pdata\n"); + kfree(pdata); + pdata = NULL; +-- +2.25.1 + -- 2.47.3