
This is a backport of a collection of 12 upstream patches. The main one being the switch to use a rwsem instead. The next important one being the switch of the rwsem to be a per filesystem lock instead of global. See the individual patches for details. They did not require much work or wiggling to get them applied. They all come from Linus' tree and are easily located. As such I have not modified their individual headers with upstream commit ids. Verification: - two scripts, the concept behind them supplied by Vefa Bicakci. The first one causes a lot of concurrent contention in sysfs. The second script highlights how well systemd is also contending. Run Script1 followed by Script2 Without this change, Script2 has timeouts and fails. Script1: for i in `seq 20`; do (while :; do find /sys/fs/cgroup/ -type f -readable -print0 \ 2>/dev/null | xargs -0 -n 20 -r cat >&/dev/null ; done) & done for i in `seq 10`; do (while :; do systemd-run --scope -q sleep 0.5 >/dev/null; done) & done Script2: while true; do date -Is /usr/bin/time -f %e systemctl enable -q lighttpd.service || break /usr/bin/time -f %e systemctl disable -q lighttpd.service || break /usr/bin/time -f %e systemctl restart -q lighttpd.service || break sleep 0.5 || break done - also soak testing to ensure that these patches don't introduce issues Partial-Bug: 2016028 Signed-off-by: Jim Somerville <jim.somerville@windriver.com> Change-Id: I6ad64cd7c90f756c6eb904065febfeb516e73009
96 lines
3.8 KiB
Diff
96 lines
3.8 KiB
Diff
From debf41dbf2a2ba28155cdeb1aea102e16faa0745 Mon Sep 17 00:00:00 2001
|
|
From: Minchan Kim <minchan@kernel.org>
|
|
Date: Wed, 27 Apr 2022 10:21:51 -0700
|
|
Subject: [PATCH] kernfs: fix NULL dereferencing in kernfs_remove
|
|
|
|
kernfs_remove supported NULL kernfs_node param to bail out but revent
|
|
per-fs lock change introduced regression that dereferencing the
|
|
param without NULL check so kernel goes crash.
|
|
|
|
This patch checks the NULL kernfs_node in kernfs_remove and if so,
|
|
just return.
|
|
|
|
Quote from bug report by Jirka
|
|
|
|
```
|
|
The bug is triggered by running NAS Parallel benchmark suite on
|
|
SuperMicro servers with 2x Xeon(R) Gold 6126 CPU. Here is the error
|
|
log:
|
|
|
|
[ 247.035564] BUG: kernel NULL pointer dereference, address: 0000000000000008
|
|
[ 247.036009] #PF: supervisor read access in kernel mode
|
|
[ 247.036009] #PF: error_code(0x0000) - not-present page
|
|
[ 247.036009] PGD 0 P4D 0
|
|
[ 247.036009] Oops: 0000 [#1] PREEMPT SMP PTI
|
|
[ 247.058060] CPU: 1 PID: 6546 Comm: umount Not tainted
|
|
5.16.0393c3714081a53795bbff0e985d24146def6f57f+ #16
|
|
[ 247.058060] Hardware name: Supermicro Super Server/X11DDW-L, BIOS
|
|
2.0b 03/07/2018
|
|
[ 247.058060] RIP: 0010:kernfs_remove+0x8/0x50
|
|
[ 247.058060] Code: 4c 89 e0 5b 5d 41 5c 41 5d 41 5e c3 49 c7 c4 f4
|
|
ff ff ff eb b2 66 66 2e 0f 1f 84 00 00 00 00 00 66 90 0f 1f 44 00 00
|
|
41 54 55 <48> 8b 47 08 48 89 fd 48 85 c0 48 0f 44 c7 4c 8b 60 50 49 83
|
|
c4 60
|
|
[ 247.058060] RSP: 0018:ffffbbfa48a27e48 EFLAGS: 00010246
|
|
[ 247.058060] RAX: 0000000000000001 RBX: ffffffff89e31f98 RCX: 0000000080200018
|
|
[ 247.058060] RDX: 0000000080200019 RSI: fffff6760786c900 RDI: 0000000000000000
|
|
[ 247.058060] RBP: ffffffff89e31f98 R08: ffff926b61b24d00 R09: 0000000080200018
|
|
[ 247.122048] R10: ffff926b61b24d00 R11: ffff926a8040c000 R12: ffff927bd09a2000
|
|
[ 247.122048] R13: ffffffff89e31fa0 R14: dead000000000122 R15: dead000000000100
|
|
[ 247.122048] FS: 00007f01be0a8c40(0000) GS:ffff926fa8e40000(0000)
|
|
knlGS:0000000000000000
|
|
[ 247.122048] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
|
|
[ 247.122048] CR2: 0000000000000008 CR3: 00000001145c6003 CR4: 00000000007706e0
|
|
[ 247.122048] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
|
|
[ 247.122048] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
|
|
[ 247.122048] PKRU: 55555554
|
|
[ 247.122048] Call Trace:
|
|
[ 247.122048] <TASK>
|
|
[ 247.122048] rdt_kill_sb+0x29d/0x350
|
|
[ 247.122048] deactivate_locked_super+0x36/0xa0
|
|
[ 247.122048] cleanup_mnt+0x131/0x190
|
|
[ 247.122048] task_work_run+0x5c/0x90
|
|
[ 247.122048] exit_to_user_mode_prepare+0x229/0x230
|
|
[ 247.122048] syscall_exit_to_user_mode+0x18/0x40
|
|
[ 247.122048] do_syscall_64+0x48/0x90
|
|
[ 247.122048] entry_SYSCALL_64_after_hwframe+0x44/0xae
|
|
[ 247.122048] RIP: 0033:0x7f01be2d735b
|
|
```
|
|
|
|
Link: https://bugzilla.kernel.org/show_bug.cgi?id=215696
|
|
Link: https://lore.kernel.org/lkml/CAE4VaGDZr_4wzRn2___eDYRtmdPaGGJdzu_LCSkJYuY9BEO3cw@mail.gmail.com/
|
|
Fixes: 393c3714081a (kernfs: switch global kernfs_rwsem lock to per-fs lock)
|
|
Cc: stable@vger.kernel.org
|
|
Reported-by: Jirka Hladky <jhladky@redhat.com>
|
|
Tested-by: Jirka Hladky <jhladky@redhat.com>
|
|
Acked-by: Tejun Heo <tj@kernel.org>
|
|
Signed-off-by: Minchan Kim <minchan@kernel.org>
|
|
Link: https://lore.kernel.org/r/20220427172152.3505364-1-minchan@kernel.org
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
Signed-off-by: Jim Somerville <jim.somerville@windriver.com>
|
|
---
|
|
fs/kernfs/dir.c | 7 ++++++-
|
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
|
|
index 21ff2d9376fb..61df2ce1a5d9 100644
|
|
--- a/fs/kernfs/dir.c
|
|
+++ b/fs/kernfs/dir.c
|
|
@@ -1403,7 +1403,12 @@ static void __kernfs_remove(struct kernfs_node *kn)
|
|
*/
|
|
void kernfs_remove(struct kernfs_node *kn)
|
|
{
|
|
- struct kernfs_root *root = kernfs_root(kn);
|
|
+ struct kernfs_root *root;
|
|
+
|
|
+ if (!kn)
|
|
+ return;
|
|
+
|
|
+ root = kernfs_root(kn);
|
|
|
|
down_write(&root->kernfs_rwsem);
|
|
__kernfs_remove(kn);
|
|
--
|
|
2.25.1
|
|
|