* [PATCH] ocfs2: fix NULL deref in ocfs2_wait_for_recovery after recovery_exit
@ 2026-05-19 1:36 Jiakai Xu
2026-05-19 1:38 ` Jiakai Xu
2026-05-19 11:41 ` Joseph Qi
0 siblings, 2 replies; 3+ messages in thread
From: Jiakai Xu @ 2026-05-19 1:36 UTC (permalink / raw)
To: linux-kernel, ocfs2-devel; +Cc: Joel Becker, Joseph Qi, Mark Fasheh, Jiakai Xu
In ocfs2_recovery_exit(), the recovery_map is freed via kfree() but
osb->recovery_map is not set to NULL afterward. If ocfs2_wait_for_recovery()
is called subsequently (e.g. during inode eviction in the dismount path or
via a racing stat() syscall), ocfs2_recovery_completed() dereferences the
stale pointer, leading to a NULL pointer dereference at rm->rm_used.
Fix this by:
1. Setting osb->recovery_map = NULL after kfree() in ocfs2_recovery_exit()
2. Adding a NULL guard in ocfs2_recovery_completed() so that it safely
returns "recovery completed" when the map has been freed
Fixes: 553abd046af6 ("ocfs2: Change the recovery map to an array of node numbers.")
Signed-off-by: Jiakai Xu <xujiakai24@mails.ucas.ac.cn>
---
fs/ocfs2/journal.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index f9bf3bac085d..5529a177f90e 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -243,6 +243,7 @@ void ocfs2_recovery_exit(struct ocfs2_super *osb)
/* XXX: Should we bug if there are dirty entries? */
kfree(rm);
+ osb->recovery_map = NULL;
}
static int __ocfs2_recovery_map_test(struct ocfs2_super *osb,
@@ -1225,6 +1226,9 @@ static int ocfs2_recovery_completed(struct ocfs2_super *osb)
int empty;
struct ocfs2_recovery_map *rm = osb->recovery_map;
+ if (!rm)
+ return 1;
+
spin_lock(&osb->osb_lock);
empty = (rm->rm_used == 0);
spin_unlock(&osb->osb_lock);
--
2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] ocfs2: fix NULL deref in ocfs2_wait_for_recovery after recovery_exit
2026-05-19 1:36 [PATCH] ocfs2: fix NULL deref in ocfs2_wait_for_recovery after recovery_exit Jiakai Xu
@ 2026-05-19 1:38 ` Jiakai Xu
2026-05-19 11:41 ` Joseph Qi
1 sibling, 0 replies; 3+ messages in thread
From: Jiakai Xu @ 2026-05-19 1:38 UTC (permalink / raw)
To: xujiakai24; +Cc: jlbec, joseph.qi, linux-kernel, mark, ocfs2-devel
This was found by fuzzing. Here is the report:
BUG: kernel NULL pointer dereference, address: 0000000000000000
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 28fdd067 P4D 51bb2067 PUD 0
Oops: Oops: 0000 [#1] SMP NOPTI
CPU: 0 UID: 0 PID: 216737 Comm: syz.2.26512 Not tainted 6.18.5 #1 PREEMPT(full)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
RIP: 0010:ocfs2_recovery_completed home/zzzrrll/tmp/linux/fs/ocfs2/journal.c:1234 [inline]
RIP: 0010:ocfs2_wait_for_recovery+0x45/0x180 home/zzzrrll/tmp/linux/fs/ocfs2/journal.c:1242
Code: 07 65 49 8b 07 48 89 44 24 28 e8 96 23 28 ff 2e 2e 2e 31 c0 49 8b ae 38 01 00 00 49 8d 9e c8 00 00 00 48 89 df e8 cb 45 41 03 <8b> 6d 00 31 ff 89 ee e8 af 27 28 ff 48 89 df e8 37 47 41 03 85 ed
RSP: 0018:ffa000000e1bbb58 EFLAGS: 00010202
RAX: 0000000000000000 RBX: ff1100002ac9a4c8 RCX: 0000000000000001
RDX: ffa000001873b000 RSI: 0000000000000000 RDI: ff1100002ac9a4c8
RBP: 0000000000000000 R08: ffffffff823b5a33 R09: ffa000000e1bbd70
R10: 0000000000000002 R11: ffffffff823c6940 R12: 0000000000000000
R13: ff1100002ac9a400 R14: ff1100002ac9a400 R15: ffffffff896a4020
FS: 00007f74f0df8640(0000) GS:ff110000f4370000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 000000005177e000 CR4: 0000000000751ef0
PKRU: 80000000
Call Trace:
<TASK>
ocfs2_inode_lock_full_nested+0xec/0xca0 home/zzzrrll/tmp/linux/fs/ocfs2/dlmglue.c:2457
ocfs2_inode_revalidate+0x90/0x300 home/zzzrrll/tmp/linux/fs/ocfs2/inode.c:1352
ocfs2_getattr+0x49/0x180 home/zzzrrll/tmp/linux/fs/ocfs2/file.c:1316
vfs_getattr_nosec+0x120/0x1b0 home/zzzrrll/tmp/linux/fs/stat.c:213
vfs_getattr home/zzzrrll/tmp/linux/fs/stat.c:262 [inline]
vfs_statx_path home/zzzrrll/tmp/linux/fs/stat.c:299 [inline]
vfs_statx+0x116/0x240 home/zzzrrll/tmp/linux/fs/stat.c:356
vfs_fstatat home/zzzrrll/tmp/linux/fs/stat.c:375 [inline]
vfs_stat home/zzzrrll/tmp/linux/include/linux/fs.h:3593 [inline]
__do_sys_newstat home/zzzrrll/tmp/linux/fs/stat.c:515 [inline]
__se_sys_newstat+0x6a/0x240 home/zzzrrll/tmp/linux/fs/stat.c:509
do_syscall_x64 home/zzzrrll/tmp/linux/arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xc6/0xfa0 home/zzzrrll/tmp/linux/arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f74effae16d
Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 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 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f74f0df7f98 EFLAGS: 00000246 ORIG_RAX: 0000000000000004
RAX: ffffffffffffffda RBX: 00007f74f01f5fa0 RCX: 00007f74effae16d
RDX: 0000000000000000 RSI: 0000200000002200 RDI: 00002000000021c0
RBP: 00007f74f00480f0 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f74f01f6038 R14: 00007f74f01f5fa0 R15: 00007f74f0dd8000
</TASK>
Modules linked in:
CR2: 0000000000000000
---[ end trace 0000000000000000 ]---
RIP: 0010:ocfs2_recovery_completed home/zzzrrll/tmp/linux/fs/ocfs2/journal.c:1234 [inline]
RIP: 0010:ocfs2_wait_for_recovery+0x45/0x180 home/zzzrrll/tmp/linux/fs/ocfs2/journal.c:1242
Code: 07 65 49 8b 07 48 89 44 24 28 e8 96 23 28 ff 2e 2e 2e 31 c0 49 8b ae 38 01 00 00 49 8d 9e c8 00 00 00 48 89 df e8 cb 45 41 03 <8b> 6d 00 31 ff 89 ee e8 af 27 28 ff 48 89 df e8 37 47 41 03 85 ed
RSP: 0018:ffa000000e1bbb58 EFLAGS: 00010202
RAX: 0000000000000000 RBX: ff1100002ac9a4c8 RCX: 0000000000000001
RDX: ffa000001873b000 RSI: 0000000000000000 RDI: ff1100002ac9a4c8
RBP: 0000000000000000 R08: ffffffff823b5a33 R09: ffa000000e1bbd70
R10: 0000000000000002 R11: ffffffff823c6940 R12: 0000000000000000
R13: ff1100002ac9a400 R14: ff1100002ac9a400 R15: ffffffff896a4020
FS: 00007f74f0df8640(0000) GS:ff110000f4370000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 000000005177e000 CR4: 0000000000751ef0
PKRU: 80000000
----------------
Code disassembly (best guess), 1 bytes skipped:
0: 65 49 8b 07 mov %gs:(%r15),%rax
4: 48 89 44 24 28 mov %rax,0x28(%rsp)
9: e8 96 23 28 ff call 0xff2823a4
e: 2e 2e 2e 31 c0 cs cs cs xor %eax,%eax
13: 49 8b ae 38 01 00 00 mov 0x138(%r14),%rbp
1a: 49 8d 9e c8 00 00 00 lea 0xc8(%r14),%rbx
21: 48 89 df mov %rbx,%rdi
24: e8 cb 45 41 03 call 0x34145f4
* 29: 8b 6d 00 mov 0x0(%rbp),%ebp <-- trapping instruction
2c: 31 ff xor %edi,%edi
2e: 89 ee mov %ebp,%esi
30: e8 af 27 28 ff call 0xff2827e4
35: 48 89 df mov %rbx,%rdi
38: e8 37 47 41 03 call 0x3414774
3d: 85 ed test %ebp,%ebp
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] ocfs2: fix NULL deref in ocfs2_wait_for_recovery after recovery_exit
2026-05-19 1:36 [PATCH] ocfs2: fix NULL deref in ocfs2_wait_for_recovery after recovery_exit Jiakai Xu
2026-05-19 1:38 ` Jiakai Xu
@ 2026-05-19 11:41 ` Joseph Qi
1 sibling, 0 replies; 3+ messages in thread
From: Joseph Qi @ 2026-05-19 11:41 UTC (permalink / raw)
To: Jiakai Xu; +Cc: Joel Becker, Mark Fasheh, linux-kernel, ocfs2-devel
On 5/19/26 9:36 AM, Jiakai Xu wrote:
> In ocfs2_recovery_exit(), the recovery_map is freed via kfree() but
> osb->recovery_map is not set to NULL afterward. If ocfs2_wait_for_recovery()
> is called subsequently (e.g. during inode eviction in the dismount path or
evict_inodes() runs before ocfs2_recovery_exit(), which is called through put_super.
> via a racing stat() syscall), ocfs2_recovery_completed() dereferences the
> stale pointer, leading to a NULL pointer dereference at rm->rm_used.
>
> Fix this by:
> 1. Setting osb->recovery_map = NULL after kfree() in ocfs2_recovery_exit()
> 2. Adding a NULL guard in ocfs2_recovery_completed() so that it safely
> returns "recovery completed" when the map has been freed
>
> Fixes: 553abd046af6 ("ocfs2: Change the recovery map to an array of node numbers.")
> Signed-off-by: Jiakai Xu <xujiakai24@mails.ucas.ac.cn>
> ---
> fs/ocfs2/journal.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
> index f9bf3bac085d..5529a177f90e 100644
> --- a/fs/ocfs2/journal.c
> +++ b/fs/ocfs2/journal.c
> @@ -243,6 +243,7 @@ void ocfs2_recovery_exit(struct ocfs2_super *osb)
> /* XXX: Should we bug if there are dirty entries? */
>
> kfree(rm);
> + osb->recovery_map = NULL;
> }
>
> static int __ocfs2_recovery_map_test(struct ocfs2_super *osb,
> @@ -1225,6 +1226,9 @@ static int ocfs2_recovery_completed(struct ocfs2_super *osb)
> int empty;
> struct ocfs2_recovery_map *rm = osb->recovery_map;
>
Seems still cannot fully close the race?
Thanks,
Joseph
> + if (!rm)
> + return 1;
> +
> spin_lock(&osb->osb_lock);
> empty = (rm->rm_used == 0);
> spin_unlock(&osb->osb_lock);
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-19 11:41 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-19 1:36 [PATCH] ocfs2: fix NULL deref in ocfs2_wait_for_recovery after recovery_exit Jiakai Xu
2026-05-19 1:38 ` Jiakai Xu
2026-05-19 11:41 ` Joseph Qi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®