* [syzbot] [gfs2?] WARNING in chown_common
@ 2025-10-12 5:45 syzbot
2025-10-17 8:57 ` Forwarded: [PATCH] fs: fix stale inode access in chown_common() retry path syzbot
` (10 more replies)
0 siblings, 11 replies; 26+ messages in thread
From: syzbot @ 2025-10-12 5:45 UTC (permalink / raw)
To: brauner, gfs2, jack, linux-fsdevel, linux-kernel, syzkaller-bugs,
viro
Hello,
syzbot found the following issue on:
HEAD commit: 98906f9d850e Merge tag 'rtc-6.18' of git://git.kernel.org/..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=10e10c58580000
kernel config: https://syzkaller.appspot.com/x/.config?x=c2d7b4143707d3a0
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=11ab9b34580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=14e10c58580000
Downloadable assets:
disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-98906f9d.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/d82186923244/vmlinux-98906f9d.xz
kernel image: https://storage.googleapis.com/syzbot-assets/a23e980d2d8e/bzImage-98906f9d.xz
mounted in repro #1: https://storage.googleapis.com/syzbot-assets/b2d6dc77aff3/mount_2.gz
fsck result: OK (log: https://syzkaller.appspot.com/x/fsck.log?x=13e03892580000)
mounted in repro #2: https://storage.googleapis.com/syzbot-assets/96cd0ec46a20/mount_8.gz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff888036665058, owner = 0x0, curr 0xffff88803e332480, list empty
WARNING: CPU: 0 PID: 5699 at kernel/locking/rwsem.c:1381 __up_write kernel/locking/rwsem.c:1380 [inline]
WARNING: CPU: 0 PID: 5699 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Modules linked in:
CPU: 0 UID: 0 PID: 5699 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:__up_write kernel/locking/rwsem.c:1380 [inline]
RIP: 0010:up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Code: d0 48 c7 c7 20 ff 6a 8b 48 c7 c6 40 01 6b 8b 48 8b 14 24 4c 89 f1 4d 89 e0 4c 8b 4c 24 08 41 52 e8 b3 36 e6 ff 48 83 c4 08 90 <0f> 0b 90 90 e9 6d fd ff ff 48 c7 c1 94 61 9e 8f 80 e1 07 80 c1 03
RSP: 0018:ffffc9000d4b7c30 EFLAGS: 00010296
RAX: e0ff97a6af656400 RBX: ffff888036665058 RCX: ffff88803e332480
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000002
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffffbfff1bfa650 R12: 0000000000000000
R13: ffff8880366650b0 R14: ffff888036665058 R15: 1ffff11006ccca0c
FS: 00007f2b1bd9b6c0(0000) GS:ffff88808d301000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f63d120f000 CR3: 000000004fe06000 CR4: 0000000000352ef0
Call Trace:
<TASK>
inode_unlock include/linux/fs.h:990 [inline]
chown_common+0x418/0x5c0 fs/open.c:793
do_fchownat+0x161/0x270 fs/open.c:822
__do_sys_lchown fs/open.c:847 [inline]
__se_sys_lchown fs/open.c:845 [inline]
__x64_sys_lchown+0x85/0xa0 fs/open.c:845
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f2b1c78eec9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007f2b1bd9b038 EFLAGS: 00000246 ORIG_RAX: 000000000000005e
RAX: ffffffffffffffda RBX: 00007f2b1c9e6360 RCX: 00007f2b1c78eec9
RDX: 000000000000ee01 RSI: 0000000000000000 RDI: 00002000000006c0
RBP: 00007f2b1c811f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f2b1c9e63f8 R14: 00007f2b1c9e6360 R15: 00007ffe60c7e2c8
</TASK>
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix stale inode access in chown_common() retry path
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
2025-10-17 8:57 ` Forwarded: [PATCH] fs: fix stale inode access in chown_common() retry path syzbot
@ 2025-10-17 8:57 ` syzbot
2025-10-29 8:23 ` Forwarded: Test patch for [syzbot] [gfs2?] WARNING in chown_common syzbot
` (8 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-10-17 8:57 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix stale inode access in chown_common() retry path
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
When chown_common() retries due to delegation, it reuses the inode
pointer fetched before the retry_deleg label. However, break_deleg_wait()
can cause the dentry to be updated, making path->dentry->d_inode point
to a different inode. The stale inode pointer leads to locking/unlocking
an invalid or freed inode, triggering a rwsem warning.
The issue manifests as:
WARNING: CPU: 0 PID: 5699 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) &&
!rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)):
count = 0x0, owner = 0x0
Fix by refreshing both the inode pointer and its associated filesystem
user namespace on each retry iteration, ensuring operations are always
performed on the current, valid inode.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..8672072fb4c1 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -755,7 +755,7 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
{
struct mnt_idmap *idmap;
struct user_namespace *fs_userns;
- struct inode *inode = path->dentry->d_inode;
+ struct inode *inode;
struct inode *delegated_inode = NULL;
int error;
struct iattr newattrs;
@@ -766,9 +766,10 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
gid = make_kgid(current_user_ns(), group);
idmap = mnt_idmap(path->mnt);
- fs_userns = i_user_ns(inode);
retry_deleg:
+ inode = path->dentry->d_inode;
+ fs_userns = i_user_ns(inode);
newattrs.ia_vfsuid = INVALID_VFSUID;
newattrs.ia_vfsgid = INVALID_VFSGID;
newattrs.ia_valid = ATTR_CTIME;
--
2.34.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix stale inode access in chown_common() retry path
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
@ 2025-10-17 8:57 ` syzbot
2025-10-17 8:57 ` syzbot
` (9 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-10-17 8:57 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix stale inode access in chown_common() retry path
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
When chown_common() retries due to delegation, it reuses the inode
pointer fetched before the retry_deleg label. However, break_deleg_wait()
can cause the dentry to be updated, making path->dentry->d_inode point
to a different inode. The stale inode pointer leads to locking/unlocking
an invalid or freed inode, triggering a rwsem warning.
The issue manifests as:
WARNING: CPU: 0 PID: 5699 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) &&
!rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)):
count = 0x0, owner = 0x0
Fix by refreshing both the inode pointer and its associated filesystem
user namespace on each retry iteration, ensuring operations are always
performed on the current, valid inode.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..8672072fb4c1 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -755,7 +755,7 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
{
struct mnt_idmap *idmap;
struct user_namespace *fs_userns;
- struct inode *inode = path->dentry->d_inode;
+ struct inode *inode;
struct inode *delegated_inode = NULL;
int error;
struct iattr newattrs;
@@ -766,9 +766,10 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
gid = make_kgid(current_user_ns(), group);
idmap = mnt_idmap(path->mnt);
- fs_userns = i_user_ns(inode);
retry_deleg:
+ inode = path->dentry->d_inode;
+ fs_userns = i_user_ns(inode);
newattrs.ia_vfsuid = INVALID_VFSUID;
newattrs.ia_vfsgid = INVALID_VFSGID;
newattrs.ia_valid = ATTR_CTIME;
--
2.34.1
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251017085719.821125-1-kartikey406@gmail.com>
@ 2025-10-17 9:20 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-10-17 9:20 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs, yzbot
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
WARNING in chown_common
WARNING: CPU: 0 PID: 5970 at kernel/locking/rwsem.c:1381 __up_write kernel/locking/rwsem.c:1380 [inline]
WARNING: CPU: 0 PID: 5970 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Modules linked in:
CPU: 0 UID: 0 PID: 5970 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:__up_write kernel/locking/rwsem.c:1380 [inline]
RIP: 0010:up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Code: d0 48 c7 c7 20 ff 6a 8b 48 c7 c6 40 01 6b 8b 48 8b 14 24 4c 89 f1 4d 89 e0 4c 8b 4c 24 08 41 52 e8 b3 36 e6 ff 48 83 c4 08 90 <0f> 0b 90 90 e9 6d fd ff ff 48 c7 c1 94 6e 9e 8f 80 e1 07 80 c1 03
RSP: 0018:ffffc9000d497c50 EFLAGS: 00010296
RAX: 29f4d5975a11a300 RBX: ffff888043da5058 RCX: ffff888034730000
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000002
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffffbfff1bfa650 R12: 0000000000000000
R13: ffff888043da50b0 R14: ffff888043da5058 R15: 1ffff110087b4a0c
FS: 00007f49f65fe6c0(0000) GS:ffff88808d300000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000c005567000 CR3: 0000000058d8f000 CR4: 0000000000352ef0
Call Trace:
<TASK>
inode_unlock include/linux/fs.h:990 [inline]
chown_common+0x3fb/0x580 fs/open.c:794
do_fchownat+0x161/0x270 fs/open.c:823
__do_sys_lchown fs/open.c:848 [inline]
__se_sys_lchown fs/open.c:846 [inline]
__x64_sys_lchown+0x85/0xa0 fs/open.c:846
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f49f6f8eec9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007f49f65fe038 EFLAGS: 00000246 ORIG_RAX: 000000000000005e
RAX: ffffffffffffffda RBX: 00007f49f71e6270 RCX: 00007f49f6f8eec9
RDX: 000000000000ee01 RSI: 0000000000000000 RDI: 00002000000006c0
RBP: 00007f49f7011f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f49f71e6308 R14: 00007f49f71e6270 R15: 00007fff9d14f498
</TASK>
Tested on:
commit: 98ac9cc4 Merge tag 'f2fs-fix-6.18-rc2' of git://git.ke..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=171475e2580000
kernel config: https://syzkaller.appspot.com/x/.config?x=c2d7b4143707d3a0
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=1448b67c580000
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: Test patch for [syzbot] [gfs2?] WARNING in chown_common
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
2025-10-17 8:57 ` Forwarded: [PATCH] fs: fix stale inode access in chown_common() retry path syzbot
2025-10-17 8:57 ` syzbot
@ 2025-10-29 8:23 ` syzbot
2025-11-09 5:02 ` Forwarded: [PATCH] fs: fix inode reference leak in chown_common delegation retry path syzbot
` (7 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-10-29 8:23 UTC (permalink / raw)
To: linux-kernel
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org.
***
Subject: Test patch for [syzbot] [gfs2?] WARNING in chown_common
Author: vnranganath.20@gmail.com
#syz test
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <CAMz+-CPDh3FF3Fso8UjYyd0=uyV2hJvYQLTVracNyo896rsF1A@mail.gmail.com>
@ 2025-10-29 10:53 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-10-29 10:53 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs, vnranganath.20
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
WARNING in chown_common
------------[ cut here ]------------
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff888040e85058, owner = 0x0, curr 0xffff888000f0a480, list empty
WARNING: CPU: 0 PID: 5805 at kernel/locking/rwsem.c:1381 __up_write kernel/locking/rwsem.c:1380 [inline]
WARNING: CPU: 0 PID: 5805 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Modules linked in:
CPU: 0 UID: 0 PID: 5805 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:__up_write kernel/locking/rwsem.c:1380 [inline]
RIP: 0010:up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Code: d0 48 c7 c7 20 ff 6a 8b 48 c7 c6 40 01 6b 8b 48 8b 14 24 4c 89 f1 4d 89 e0 4c 8b 4c 24 08 41 52 e8 f3 35 e6 ff 48 83 c4 08 90 <0f> 0b 90 90 e9 6d fd ff ff 48 c7 c1 94 24 7d 8f 80 e1 07 80 c1 03
RSP: 0018:ffffc9000cd5fc10 EFLAGS: 00010292
RAX: 137f67c4e7e18000 RBX: ffff888040e85058 RCX: ffff888000f0a480
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000002
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffffbfff1bba650 R12: 0000000000000000
R13: ffff888040e850b0 R14: ffff888040e85058 R15: 1ffff110081d0a0c
FS: 00007f716bd5d6c0(0000) GS:ffff88808d733000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000041ac2000 CR4: 0000000000352ef0
Call Trace:
<TASK>
inode_unlock include/linux/fs.h:990 [inline]
chown_common+0x406/0x5b0 fs/open.c:-1
do_fchownat+0x161/0x270 fs/open.c:825
__do_sys_fchownat fs/open.c:840 [inline]
__se_sys_fchownat fs/open.c:837 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:837
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f716af8efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007f716bd5d038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007f716b1e6090 RCX: 00007f716af8efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007f716b011f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f716b1e6128 R14: 00007f716b1e6090 R15: 00007fff5b24d448
</TASK>
Tested on:
commit: e53642b8 Merge tag 'v6.18-rc3-smb-server-fixes' of git..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=13031258580000
kernel config: https://syzkaller.appspot.com/x/.config?x=929790bc044e87d7
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=12051258580000
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix inode reference leak in chown_common delegation retry path
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
` (2 preceding siblings ...)
2025-10-29 8:23 ` Forwarded: Test patch for [syzbot] [gfs2?] WARNING in chown_common syzbot
@ 2025-11-09 5:02 ` syzbot
2025-11-09 9:08 ` Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry syzbot
` (6 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 5:02 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix inode reference leak in chown_common delegation retry path
Author: kartikey406@gmail.com
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The chown_common() function can trigger a use-after-free when retrying
after breaking a file delegation. The issue occurs because break_deleg_wait()
calls iput() on the delegated inode, potentially freeing it if this was the
last reference. However, chown_common() continues to use the stale inode
pointer on retry, leading to operations on a freed or reused inode.
This manifests as a rwsem warning:
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) &&
!rwsem_test_oflags(sem, RWSEM_NONSPINNABLE))
owner = 0x0
The warning occurs because the inode's rwsem is in an invalid state after
the inode has been freed or reused by another thread.
The bug is particularly reproducible on GFS2 filesystem where delegations
are more common due to its clustered nature, and can be triggered by
concurrent fchownat() calls on the same file.
Fix this by:
1. Re-fetching the inode pointer from path->dentry->d_inode on each
iteration at the retry_deleg label
2. Holding an explicit reference with ihold() at the start of each iteration
3. Releasing the reference with iput() on all exit paths, including before
the retry
This ensures the inode remains valid throughout the delegation break and
retry sequence, preventing use-after-free.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..a564f05c0c91 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -755,7 +755,7 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
{
struct mnt_idmap *idmap;
struct user_namespace *fs_userns;
- struct inode *inode = path->dentry->d_inode;
+ struct inode *inode;
struct inode *delegated_inode = NULL;
int error;
struct iattr newattrs;
@@ -766,19 +766,27 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
gid = make_kgid(current_user_ns(), group);
idmap = mnt_idmap(path->mnt);
- fs_userns = i_user_ns(inode);
retry_deleg:
+ inode = path->dentry->d_inode;
+ ihold(inode);
+ fs_userns = i_user_ns(inode);
newattrs.ia_vfsuid = INVALID_VFSUID;
newattrs.ia_vfsgid = INVALID_VFSGID;
newattrs.ia_valid = ATTR_CTIME;
- if ((user != (uid_t)-1) && !setattr_vfsuid(&newattrs, uid))
+ if ((user != (uid_t)-1) && !setattr_vfsuid(&newattrs, uid)) {
+ iput(inode);
return -EINVAL;
- if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid))
+ }
+ if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid)) {
+ iput(inode);
return -EINVAL;
+ }
error = inode_lock_killable(inode);
- if (error)
+ if (error) {
+ iput(inode);
return error;
+ }
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV |
setattr_should_drop_sgid(idmap, inode);
@@ -793,9 +801,12 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
inode_unlock(inode);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
- if (!error)
+ if (!error) {
+ iput(inode);
goto retry_deleg;
+ }
}
+ iput(inode);
return error;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251109050218.648149-1-kartikey406@gmail.com>
@ 2025-11-09 5:17 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 5:17 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
WARNING in chown_common
------------[ cut here ]------------
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff88804066a898, owner = 0x0, curr 0xffff88803347c900, list empty
WARNING: CPU: 0 PID: 5867 at kernel/locking/rwsem.c:1381 __up_write kernel/locking/rwsem.c:1380 [inline]
WARNING: CPU: 0 PID: 5867 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Modules linked in:
CPU: 0 UID: 0 PID: 5867 Comm: syz.0.21 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:__up_write kernel/locking/rwsem.c:1380 [inline]
RIP: 0010:up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Code: d0 48 c7 c7 20 ff 6a 8b 48 c7 c6 40 01 6b 8b 48 8b 14 24 4c 89 f1 4d 89 e0 4c 8b 4c 24 08 41 52 e8 c3 35 e6 ff 48 83 c4 08 90 <0f> 0b 90 90 e9 6d fd ff ff 48 c7 c1 94 33 7d 8f 80 e1 07 80 c1 03
RSP: 0018:ffffc9000ceafc30 EFLAGS: 00010296
RAX: a13d96110bebcb00 RBX: ffff88804066a898 RCX: ffff88803347c900
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000002
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffffbfff1bba684 R12: 0000000000000000
R13: ffff88804066a8f0 R14: ffff88804066a898 R15: 1ffff110080cd514
FS: 00007f07520966c0(0000) GS:ffff88808d730000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 000000004e9f3000 CR4: 0000000000352ef0
Call Trace:
<TASK>
inode_unlock include/linux/fs.h:990 [inline]
chown_common+0x3f1/0x5b0 fs/open.c:801
do_fchownat+0x161/0x270 fs/open.c:833
__do_sys_fchownat fs/open.c:848 [inline]
__se_sys_fchownat fs/open.c:845 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:845
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f075118efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007f0752096038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007f07513e6090 RCX: 00007f075118efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007f0751211f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f07513e6128 R14: 00007f07513e6090 R15: 00007ffd9054c3d8
</TASK>
Tested on:
commit: 439fc29d Merge tag 'drm-fixes-2025-11-09' of https://g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=133c6a92580000
kernel config: https://syzkaller.appspot.com/x/.config?x=929790bc044e87d7
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=140c8412580000
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
` (3 preceding siblings ...)
2025-11-09 5:02 ` Forwarded: [PATCH] fs: fix inode reference leak in chown_common delegation retry path syzbot
@ 2025-11-09 9:08 ` syzbot
2025-11-09 11:05 ` kernel test robot
2025-11-09 12:17 ` kernel test robot
2025-11-09 11:40 ` syzbot
` (5 subsequent siblings)
10 siblings, 2 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 9:08 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
Author: kartikey406@gmail.com
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The chown_common() function has a use-after-free bug in its delegation
retry path. When break_deleg_wait() is called, it internally calls
iput() on the delegated inode, potentially freeing it if this was the
last reference. However, chown_common() continues using the stale inode
pointer on retry, leading to operations on freed memory.
This manifests as a rwsem warning where the inode's rwsem owner field
is corrupted:
DEBUG_RWSEMS_WARN_ON: owner = 0x0
The bug is triggered by concurrent fchownat() calls and is reproducible
on GFS2 filesystems where delegations are common.
Fix by:
1. Re-fetching inode from path->dentry->d_inode on each retry iteration
2. Holding an explicit inode reference with ihold() at iteration start
3. Releasing the reference with iput() on all exit paths
This ensures the inode remains valid throughout delegation break and retry.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..bbd73984292d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -769,6 +769,9 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
fs_userns = i_user_ns(inode);
retry_deleg:
+ printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
+ current->comm, inode, atomic_read(&inode->i_count),
+ atomic_long_read(&inode->i_rwsem.owner));
newattrs.ia_vfsuid = INVALID_VFSUID;
newattrs.ia_vfsgid = INVALID_VFSGID;
newattrs.ia_valid = ATTR_CTIME;
@@ -776,9 +779,13 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
return -EINVAL;
if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid))
return -EINVAL;
+ printk("DEBUG: [%s] before inode_lock: inode=%p, i_count=%d\n",
+ current->comm, inode, atomic_read(&inode->i_count));
error = inode_lock_killable(inode);
if (error)
return error;
+ printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
+ current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
if (!S_ISDIR(inode->i_mode))
newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV |
setattr_should_drop_sgid(idmap, inode);
@@ -790,9 +797,17 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
if (!error)
error = notify_change(idmap, path->dentry, &newattrs,
&delegated_inode);
+ printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
+ current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
inode_unlock(inode);
+ printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
+ current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
if (delegated_inode) {
+ printk("DEBUG: [%s] calling break_deleg_wait: inode=%p, i_count=%d, delegated_inode=%p\n",
+ current->comm, inode, atomic_read(&inode->i_count), delegated_inode);
error = break_deleg_wait(&delegated_inode);
+ printk("DEBUG: [%s] after break_deleg_wait: inode=%p, i_count=%d, error=%d\n",
+ current->comm, inode, atomic_read(&inode->i_count), error);
if (!error)
goto retry_deleg;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251109090808.839886-1-kartikey406@gmail.com>
@ 2025-11-09 9:30 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 9:30 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs
Hello,
syzbot has tested the proposed patch and the reproducer did not trigger any issue:
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Tested-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Tested on:
commit: 439fc29d Merge tag 'drm-fixes-2025-11-09' of https://g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=16684b42580000
kernel config: https://syzkaller.appspot.com/x/.config?x=929790bc044e87d7
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=13418412580000
Note: testing is done by a robot and is best-effort only.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-11-09 9:08 ` Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry syzbot
@ 2025-11-09 11:05 ` kernel test robot
2025-11-09 12:26 ` Philip Li
2025-11-09 12:17 ` kernel test robot
1 sibling, 1 reply; 26+ messages in thread
From: kernel test robot @ 2025-11-09 11:05 UTC (permalink / raw)
To: syzbot, linux-kernel, syzkaller-bugs; +Cc: llvm, oe-kbuild-all
Hi syzbot,
kernel test robot noticed the following build warnings:
[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.18-rc4 next-20251107]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/syzbot/Forwarded-PATCH-fs-fix-inode-use-after-free-in-chown_common-delegation-retry/20251109-171000
base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link: https://lore.kernel.org/r/691059ff.a70a0220.22f260.00a6.GAE%40google.com
patch subject: Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
config: arm-allnoconfig (https://download.01.org/0day-ci/archive/20251109/202511091815.6q5WUuzH-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project b9ea93cd5c37fb6d606502fd01208dd48330549d)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251109/202511091815.6q5WUuzH-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511091815.6q5WUuzH-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> fs/open.c:771:9: warning: format specifies type 'void *' but the argument has type 'long' [-Wformat]
769 | printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
| ~~
| %ld
770 | current->comm, inode, atomic_read(&inode->i_count),
771 | atomic_long_read(&inode->i_rwsem.owner));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:512:60: note: expanded from macro 'printk'
512 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/printk.h:484:19: note: expanded from macro 'printk_index_wrap'
484 | _p_func(_fmt, ##__VA_ARGS__); \
| ~~~~ ^~~~~~~~~~~
fs/open.c:785:31: warning: format specifies type 'void *' but the argument has type 'long' [-Wformat]
784 | printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
| ~~
| %ld
785 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:512:60: note: expanded from macro 'printk'
512 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/printk.h:484:19: note: expanded from macro 'printk_index_wrap'
484 | _p_func(_fmt, ##__VA_ARGS__); \
| ~~~~ ^~~~~~~~~~~
fs/open.c:798:31: warning: format specifies type 'void *' but the argument has type 'long' [-Wformat]
797 | printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
| ~~
| %ld
798 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:512:60: note: expanded from macro 'printk'
512 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/printk.h:484:19: note: expanded from macro 'printk_index_wrap'
484 | _p_func(_fmt, ##__VA_ARGS__); \
| ~~~~ ^~~~~~~~~~~
fs/open.c:801:31: warning: format specifies type 'void *' but the argument has type 'long' [-Wformat]
800 | printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
| ~~
| %ld
801 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/printk.h:512:60: note: expanded from macro 'printk'
512 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
| ~~~ ^~~~~~~~~~~
include/linux/printk.h:484:19: note: expanded from macro 'printk_index_wrap'
484 | _p_func(_fmt, ##__VA_ARGS__); \
| ~~~~ ^~~~~~~~~~~
4 warnings generated.
vim +771 fs/open.c
750
751 int chown_common(const struct path *path, uid_t user, gid_t group)
752 {
753 struct mnt_idmap *idmap;
754 struct user_namespace *fs_userns;
755 struct inode *inode = path->dentry->d_inode;
756 struct inode *delegated_inode = NULL;
757 int error;
758 struct iattr newattrs;
759 kuid_t uid;
760 kgid_t gid;
761
762 uid = make_kuid(current_user_ns(), user);
763 gid = make_kgid(current_user_ns(), group);
764
765 idmap = mnt_idmap(path->mnt);
766 fs_userns = i_user_ns(inode);
767
768 retry_deleg:
769 printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
770 current->comm, inode, atomic_read(&inode->i_count),
> 771 atomic_long_read(&inode->i_rwsem.owner));
772 newattrs.ia_vfsuid = INVALID_VFSUID;
773 newattrs.ia_vfsgid = INVALID_VFSGID;
774 newattrs.ia_valid = ATTR_CTIME;
775 if ((user != (uid_t)-1) && !setattr_vfsuid(&newattrs, uid))
776 return -EINVAL;
777 if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid))
778 return -EINVAL;
779 printk("DEBUG: [%s] before inode_lock: inode=%p, i_count=%d\n",
780 current->comm, inode, atomic_read(&inode->i_count));
781 error = inode_lock_killable(inode);
782 if (error)
783 return error;
784 printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
785 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
786 if (!S_ISDIR(inode->i_mode))
787 newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV |
788 setattr_should_drop_sgid(idmap, inode);
789 /* Continue to send actual fs values, not the mount values. */
790 error = security_path_chown(
791 path,
792 from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid),
793 from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid));
794 if (!error)
795 error = notify_change(idmap, path->dentry, &newattrs,
796 &delegated_inode);
797 printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
798 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
799 inode_unlock(inode);
800 printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
801 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
802 if (delegated_inode) {
803 printk("DEBUG: [%s] calling break_deleg_wait: inode=%p, i_count=%d, delegated_inode=%p\n",
804 current->comm, inode, atomic_read(&inode->i_count), delegated_inode);
805 error = break_deleg_wait(&delegated_inode);
806 printk("DEBUG: [%s] after break_deleg_wait: inode=%p, i_count=%d, error=%d\n",
807 current->comm, inode, atomic_read(&inode->i_count), error);
808 if (!error)
809 goto retry_deleg;
810 }
811 return error;
812 }
813
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
` (4 preceding siblings ...)
2025-11-09 9:08 ` Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry syzbot
@ 2025-11-09 11:40 ` syzbot
2025-11-09 11:57 ` syzbot
` (4 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 11:40 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
The chown_common() function has a use-after-free bug in its delegation
retry path. When break_deleg_wait() is called, it internally calls
iput() on the delegated inode, potentially freeing it if this was the
last reference. However, chown_common() continues using the stale inode
pointer on retry, leading to operations on freed memory.
This manifests as a rwsem warning where the inode's rwsem owner field
is corrupted:
DEBUG_RWSEMS_WARN_ON: owner = 0x0
The bug is triggered by concurrent fchownat() calls and is reproducible
on GFS2 filesystems where delegations are common.
Fix by:
1. Re-fetching inode from path->dentry->d_inode on each retry iteration
2. Holding an explicit inode reference with ihold() at iteration start
3. Releasing the reference with iput() on all exit paths
This ensures the inode remains valid throughout delegation break and
retry.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..9d0f88ce56f9 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -790,6 +790,14 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
if (!error)
error = notify_change(idmap, path->dentry, &newattrs,
&delegated_inode);
+ if (atomic_long_read(&inode->i_rwsem.owner) != (long)current) {
+ printk(KERN_ERR "BUG: About to unlock rwsem we don't own!\n");
+ printk(KERN_ERR " inode=%p\n", inode);
+ printk(KERN_ERR " i_rwsem.owner=%lx\n", atomic_long_read(&inode->i_rwsem.owner));
+ printk(KERN_ERR " current=%p\n", current);
+ printk(KERN_ERR " delegated_inode=%p\n", delegated_inode);
+ dump_stack();
+ }
inode_unlock(inode);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
--
2.43.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251109114011.1100867-1-kartikey406@gmail.com>
@ 2025-11-09 11:56 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 11:56 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
WARNING in swap_cache_get_folio
------------[ cut here ]------------
WARNING: mm/swap.h:87 at __swap_offset_to_cluster mm/swap.h:87 [inline], CPU#0: syz-executor/5541
WARNING: mm/swap.h:87 at __swap_entry_to_cluster mm/swap.h:93 [inline], CPU#0: syz-executor/5541
WARNING: mm/swap.h:87 at swap_cache_get_folio+0x365/0x530 mm/swap_state.c:94, CPU#0: syz-executor/5541
Modules linked in:
CPU: 0 UID: 0 PID: 5541 Comm: syz-executor Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:__swap_offset_to_cluster mm/swap.h:87 [inline]
RIP: 0010:__swap_entry_to_cluster mm/swap.h:93 [inline]
RIP: 0010:swap_cache_get_folio+0x365/0x530 mm/swap_state.c:94
Code: ff 31 ed e9 2a ff ff ff e8 98 22 a1 ff 90 0f 0b 90 e9 3d fd ff ff e8 8a 22 a1 ff 90 0f 0b 90 e9 44 fd ff ff e8 7c 22 a1 ff 90 <0f> 0b 90 e9 6b fd ff ff 44 89 f1 80 e1 07 80 c1 03 38 c1 0f 8c 3e
RSP: 0018:ffffc9000cb6fa40 EFLAGS: 00010293
RAX: ffffffff82206d54 RBX: 00000000000001ff RCX: ffff8880003da4c0
RDX: 0000000000000000 RSI: 0000000000007a12 RDI: 0003ffffffffffff
RBP: ffffffff99a78920 R08: 0000000000000000 R09: ffffffff82158099
R10: dffffc0000000000 R11: fffff9400023d3cf R12: ffff88801a839800
R13: dffffc0000000000 R14: 0000000000007a12 R15: 0003ffffffffffff
FS: 0000555569d2f500(0000) GS:ffff88808d2b8000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000555569d49300 CR3: 000000004ffac000 CR4: 0000000000352ef0
Call Trace:
<TASK>
unuse_pte_range mm/swapfile.c:2282 [inline]
unuse_pmd_range mm/swapfile.c:2332 [inline]
unuse_pud_range mm/swapfile.c:2352 [inline]
unuse_p4d_range mm/swapfile.c:2372 [inline]
unuse_vma mm/swapfile.c:2393 [inline]
unuse_mm mm/swapfile.c:2411 [inline]
try_to_unuse+0xd6f/0x2ce0 mm/swapfile.c:2488
__do_sys_swapoff mm/swapfile.c:2884 [inline]
__se_sys_swapoff+0x431/0xa10 mm/swapfile.c:2824
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f728438eeb7
Code: 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 b8 a8 00 00 00 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:00007ffc54ebd478 EFLAGS: 00000202 ORIG_RAX: 00000000000000a8
RAX: ffffffffffffffda RBX: 0000555569d492c0 RCX: 00007f728438eeb7
RDX: 000000000000002f RSI: 00007f728442e70b RDI: 00007f7284412bc1
RBP: 00007f7284412bc1 R08: 00007f72845b7d20 R09: 0000000000000060
R10: 0000000000000000 R11: 0000000000000202 R12: 00007f72845b1270
R13: 00007f72843ec1a0 R14: 00007f72845b1240 R15: 00007f728442e698
</TASK>
Tested on:
commit: 9c0826a5 Add linux-next specific files for 20251107
git tree: linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=11fe3084580000
kernel config: https://syzkaller.appspot.com/x/.config?x=3983c6ffb8f8b6b5
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=15356a92580000
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
` (5 preceding siblings ...)
2025-11-09 11:40 ` syzbot
@ 2025-11-09 11:57 ` syzbot
2025-11-09 12:25 ` syzbot
` (3 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 11:57 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
Author: kartikey406@gmail.com
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The chown_common() function has a use-after-free bug in its delegation
retry path. When break_deleg_wait() is called, it internally calls
iput() on the delegated inode, potentially freeing it if this was the
last reference. However, chown_common() continues using the stale inode
pointer on retry, leading to operations on freed memory.
This manifests as a rwsem warning where the inode's rwsem owner field
is corrupted:
DEBUG_RWSEMS_WARN_ON: owner = 0x0
The bug is triggered by concurrent fchownat() calls and is reproducible
on GFS2 filesystems where delegations are common.
Fix by:
1. Re-fetching inode from path->dentry->d_inode on each retry iteration
2. Holding an explicit inode reference with ihold() at iteration start
3. Releasing the reference with iput() on all exit paths
This ensures the inode remains valid throughout delegation break and
retry.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..9d0f88ce56f9 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -790,6 +790,14 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
if (!error)
error = notify_change(idmap, path->dentry, &newattrs,
&delegated_inode);
+ if (atomic_long_read(&inode->i_rwsem.owner) != (long)current) {
+ printk(KERN_ERR "BUG: About to unlock rwsem we don't own!\n");
+ printk(KERN_ERR " inode=%p\n", inode);
+ printk(KERN_ERR " i_rwsem.owner=%lx\n", atomic_long_read(&inode->i_rwsem.owner));
+ printk(KERN_ERR " current=%p\n", current);
+ printk(KERN_ERR " delegated_inode=%p\n", delegated_inode);
+ dump_stack();
+ }
inode_unlock(inode);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
--
2.43.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251109115742.1138274-1-kartikey406@gmail.com>
@ 2025-11-09 12:14 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 12:14 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
BUG: About to unlock rwsem we don't own!
BUG: About to unlock rwsem we don't own!
inode=ffff888042108000
i_rwsem.owner=0
current=ffff888000424900
delegated_inode=0000000000000000
CPU: 0 UID: 0 PID: 5833 Comm: syz.0.19 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
chown_common+0x66f/0x720 fs/open.c:799
do_fchownat+0x161/0x270 fs/open.c:830
__do_sys_fchownat fs/open.c:845 [inline]
__se_sys_fchownat fs/open.c:842 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:842
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fa47538efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007fa476279038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007fa4755e6090 RCX: 00007fa47538efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007fa475411f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fa4755e6128 R14: 00007fa4755e6090 R15: 00007ffc415c5d88
</TASK>
------------[ cut here ]------------
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff8880421080d8, owner = 0x0, curr 0xffff888000424900, list empty
WARNING: CPU: 0 PID: 5833 at kernel/locking/rwsem.c:1381 __up_write kernel/locking/rwsem.c:1380 [inline]
WARNING: CPU: 0 PID: 5833 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Modules linked in:
CPU: 0 UID: 0 PID: 5833 Comm: syz.0.19 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:__up_write kernel/locking/rwsem.c:1380 [inline]
RIP: 0010:up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Code: d0 48 c7 c7 20 ff 6a 8b 48 c7 c6 40 01 6b 8b 48 8b 14 24 4c 89 f1 4d 89 e0 4c 8b 4c 24 08 41 52 e8 c3 35 e6 ff 48 83 c4 08 90 <0f> 0b 90 90 e9 6d fd ff ff 48 c7 c1 94 34 7d 8f 80 e1 07 80 c1 03
RSP: 0018:ffffc9000cdcfbf0 EFLAGS: 00010296
RAX: 5957612cb528b400 RBX: ffff8880421080d8 RCX: ffff888000424900
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000002
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffffbfff1bba684 R12: 0000000000000000
R13: ffff888042108130 R14: ffff8880421080d8 R15: 1ffff1100842101c
FS: 00007fa4762796c0(0000) GS:ffff88808d730000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 000000004a36b000 CR4: 0000000000352ef0
Call Trace:
<TASK>
inode_unlock include/linux/fs.h:990 [inline]
chown_common+0x4db/0x720 fs/open.c:801
do_fchownat+0x161/0x270 fs/open.c:830
__do_sys_fchownat fs/open.c:845 [inline]
__se_sys_fchownat fs/open.c:842 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:842
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fa47538efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007fa476279038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007fa4755e6090 RCX: 00007fa47538efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007fa475411f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fa4755e6128 R14: 00007fa4755e6090 R15: 00007ffc415c5d88
</TASK>
Tested on:
commit: 439fc29d Merge tag 'drm-fixes-2025-11-09' of https://g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=13ff50b4580000
kernel config: https://syzkaller.appspot.com/x/.config?x=929790bc044e87d7
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=17bc4b42580000
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-11-09 9:08 ` Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry syzbot
2025-11-09 11:05 ` kernel test robot
@ 2025-11-09 12:17 ` kernel test robot
2025-11-09 12:26 ` Philip Li
1 sibling, 1 reply; 26+ messages in thread
From: kernel test robot @ 2025-11-09 12:17 UTC (permalink / raw)
To: syzbot, linux-kernel, syzkaller-bugs; +Cc: oe-kbuild-all
Hi syzbot,
kernel test robot noticed the following build warnings:
[auto build test WARNING on brauner-vfs/vfs.all]
[also build test WARNING on linus/master v6.18-rc4 next-20251107]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/syzbot/Forwarded-PATCH-fs-fix-inode-use-after-free-in-chown_common-delegation-retry/20251109-171000
base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
patch link: https://lore.kernel.org/r/691059ff.a70a0220.22f260.00a6.GAE%40google.com
patch subject: Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
config: i386-allnoconfig (https://download.01.org/0day-ci/archive/20251109/202511091831.tPcsumuB-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251109/202511091831.tPcsumuB-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511091831.tPcsumuB-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from include/asm-generic/bug.h:22,
from arch/x86/include/asm/bug.h:108,
from include/linux/bug.h:5,
from include/linux/mmdebug.h:5,
from include/linux/mm.h:6,
from fs/open.c:9:
fs/open.c: In function 'chown_common':
>> fs/open.c:769:16: warning: format '%p' expects argument of type 'void *', but argument 5 has type 'long int' [-Wformat=]
769 | printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
770 | current->comm, inode, atomic_read(&inode->i_count),
771 | atomic_long_read(&inode->i_rwsem.owner));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| long int
include/linux/printk.h:484:25: note: in definition of macro 'printk_index_wrap'
484 | _p_func(_fmt, ##__VA_ARGS__); \
| ^~~~
fs/open.c:769:9: note: in expansion of macro 'printk'
769 | printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
| ^~~~~~
fs/open.c:769:79: note: format string is defined here
769 | printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
| ~^
| |
| void *
| %ld
fs/open.c:784:16: warning: format '%p' expects argument of type 'void *', but argument 4 has type 'long int' [-Wformat=]
784 | printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
785 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| long int
include/linux/printk.h:484:25: note: in definition of macro 'printk_index_wrap'
484 | _p_func(_fmt, ##__VA_ARGS__); \
| ^~~~
fs/open.c:784:9: note: in expansion of macro 'printk'
784 | printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
| ^~~~~~
fs/open.c:784:72: note: format string is defined here
784 | printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
| ~^
| |
| void *
| %ld
fs/open.c:797:16: warning: format '%p' expects argument of type 'void *', but argument 4 has type 'long int' [-Wformat=]
797 | printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
798 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| long int
include/linux/printk.h:484:25: note: in definition of macro 'printk_index_wrap'
484 | _p_func(_fmt, ##__VA_ARGS__); \
| ^~~~
fs/open.c:797:9: note: in expansion of macro 'printk'
797 | printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
| ^~~~~~
fs/open.c:797:75: note: format string is defined here
797 | printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
| ~^
| |
| void *
| %ld
fs/open.c:800:16: warning: format '%p' expects argument of type 'void *', but argument 4 has type 'long int' [-Wformat=]
800 | printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
801 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| long int
include/linux/printk.h:484:25: note: in definition of macro 'printk_index_wrap'
484 | _p_func(_fmt, ##__VA_ARGS__); \
| ^~~~
fs/open.c:800:9: note: in expansion of macro 'printk'
800 | printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
| ^~~~~~
fs/open.c:800:74: note: format string is defined here
800 | printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
| ~^
| |
| void *
| %ld
vim +769 fs/open.c
750
751 int chown_common(const struct path *path, uid_t user, gid_t group)
752 {
753 struct mnt_idmap *idmap;
754 struct user_namespace *fs_userns;
755 struct inode *inode = path->dentry->d_inode;
756 struct inode *delegated_inode = NULL;
757 int error;
758 struct iattr newattrs;
759 kuid_t uid;
760 kgid_t gid;
761
762 uid = make_kuid(current_user_ns(), user);
763 gid = make_kgid(current_user_ns(), group);
764
765 idmap = mnt_idmap(path->mnt);
766 fs_userns = i_user_ns(inode);
767
768 retry_deleg:
> 769 printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
770 current->comm, inode, atomic_read(&inode->i_count),
771 atomic_long_read(&inode->i_rwsem.owner));
772 newattrs.ia_vfsuid = INVALID_VFSUID;
773 newattrs.ia_vfsgid = INVALID_VFSGID;
774 newattrs.ia_valid = ATTR_CTIME;
775 if ((user != (uid_t)-1) && !setattr_vfsuid(&newattrs, uid))
776 return -EINVAL;
777 if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid))
778 return -EINVAL;
779 printk("DEBUG: [%s] before inode_lock: inode=%p, i_count=%d\n",
780 current->comm, inode, atomic_read(&inode->i_count));
781 error = inode_lock_killable(inode);
782 if (error)
783 return error;
784 printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
785 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
786 if (!S_ISDIR(inode->i_mode))
787 newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV |
788 setattr_should_drop_sgid(idmap, inode);
789 /* Continue to send actual fs values, not the mount values. */
790 error = security_path_chown(
791 path,
792 from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid),
793 from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid));
794 if (!error)
795 error = notify_change(idmap, path->dentry, &newattrs,
796 &delegated_inode);
797 printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
798 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
799 inode_unlock(inode);
800 printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
801 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
802 if (delegated_inode) {
803 printk("DEBUG: [%s] calling break_deleg_wait: inode=%p, i_count=%d, delegated_inode=%p\n",
804 current->comm, inode, atomic_read(&inode->i_count), delegated_inode);
805 error = break_deleg_wait(&delegated_inode);
806 printk("DEBUG: [%s] after break_deleg_wait: inode=%p, i_count=%d, error=%d\n",
807 current->comm, inode, atomic_read(&inode->i_count), error);
808 if (!error)
809 goto retry_deleg;
810 }
811 return error;
812 }
813
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
` (6 preceding siblings ...)
2025-11-09 11:57 ` syzbot
@ 2025-11-09 12:25 ` syzbot
2025-11-09 13:27 ` syzbot
` (2 subsequent siblings)
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 12:25 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
Author: kartikey406@gmail.com
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The chown_common() function has a use-after-free bug in its delegation
retry path. When break_deleg_wait() is called, it internally calls
iput() on the delegated inode, potentially freeing it if this was the
last reference. However, chown_common() continues using the stale inode
pointer on retry, leading to operations on freed memory.
This manifests as a rwsem warning where the inode's rwsem owner field
is corrupted:
DEBUG_RWSEMS_WARN_ON: owner = 0x0
The bug is triggered by concurrent fchownat() calls and is reproducible
on GFS2 filesystems where delegations are common.
Fix by:
1. Re-fetching inode from path->dentry->d_inode on each retry iteration
2. Holding an explicit inode reference with ihold() at iteration start
3. Releasing the reference with iput() on all exit paths
This ensures the inode remains valid throughout delegation break and
retry.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..e5ff4d052f80 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -787,9 +787,21 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
path,
from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid),
from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid));
+ printk(KERN_INFO "After security_path_chown: owner=%lx\n",
+ atomic_long_read(&inode->i_rwsem.owner));
if (!error)
error = notify_change(idmap, path->dentry, &newattrs,
&delegated_inode);
+ printk(KERN_INFO "After notify_change: owner=%lx, error=%d\n",
+ atomic_long_read(&inode->i_rwsem.owner), error);
+ if (atomic_long_read(&inode->i_rwsem.owner) != (long)current) {
+ printk(KERN_ERR "BUG: About to unlock rwsem we don't own!\n");
+ printk(KERN_ERR " inode=%p\n", inode);
+ printk(KERN_ERR " i_rwsem.owner=%lx\n", atomic_long_read(&inode->i_rwsem.owner));
+ printk(KERN_ERR " current=%p\n", current);
+ printk(KERN_ERR " delegated_inode=%p\n", delegated_inode);
+ dump_stack();
+ }
inode_unlock(inode);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
--
2.43.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-11-09 11:05 ` kernel test robot
@ 2025-11-09 12:26 ` Philip Li
0 siblings, 0 replies; 26+ messages in thread
From: Philip Li @ 2025-11-09 12:26 UTC (permalink / raw)
To: kernel test robot
Cc: syzbot, linux-kernel, syzkaller-bugs, llvm, oe-kbuild-all
On Sun, Nov 09, 2025 at 07:05:11PM +0800, kernel test robot wrote:
> Hi syzbot,
>
> kernel test robot noticed the following build warnings:
Sorry, kindly ignore this report.
>
> [auto build test WARNING on brauner-vfs/vfs.all]
> [also build test WARNING on linus/master v6.18-rc4 next-20251107]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url: https://github.com/intel-lab-lkp/linux/commits/syzbot/Forwarded-PATCH-fs-fix-inode-use-after-free-in-chown_common-delegation-retry/20251109-171000
> base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
> patch link: https://lore.kernel.org/r/691059ff.a70a0220.22f260.00a6.GAE%40google.com
> patch subject: Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
> config: arm-allnoconfig (https://download.01.org/0day-ci/archive/20251109/202511091815.6q5WUuzH-lkp@intel.com/config)
> compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project b9ea93cd5c37fb6d606502fd01208dd48330549d)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251109/202511091815.6q5WUuzH-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202511091815.6q5WUuzH-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> >> fs/open.c:771:9: warning: format specifies type 'void *' but the argument has type 'long' [-Wformat]
> 769 | printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
> | ~~
> | %ld
> 770 | current->comm, inode, atomic_read(&inode->i_count),
> 771 | atomic_long_read(&inode->i_rwsem.owner));
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> include/linux/printk.h:512:60: note: expanded from macro 'printk'
> 512 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
> | ~~~ ^~~~~~~~~~~
> include/linux/printk.h:484:19: note: expanded from macro 'printk_index_wrap'
> 484 | _p_func(_fmt, ##__VA_ARGS__); \
> | ~~~~ ^~~~~~~~~~~
> fs/open.c:785:31: warning: format specifies type 'void *' but the argument has type 'long' [-Wformat]
> 784 | printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
> | ~~
> | %ld
> 785 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> include/linux/printk.h:512:60: note: expanded from macro 'printk'
> 512 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
> | ~~~ ^~~~~~~~~~~
> include/linux/printk.h:484:19: note: expanded from macro 'printk_index_wrap'
> 484 | _p_func(_fmt, ##__VA_ARGS__); \
> | ~~~~ ^~~~~~~~~~~
> fs/open.c:798:31: warning: format specifies type 'void *' but the argument has type 'long' [-Wformat]
> 797 | printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
> | ~~
> | %ld
> 798 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> include/linux/printk.h:512:60: note: expanded from macro 'printk'
> 512 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
> | ~~~ ^~~~~~~~~~~
> include/linux/printk.h:484:19: note: expanded from macro 'printk_index_wrap'
> 484 | _p_func(_fmt, ##__VA_ARGS__); \
> | ~~~~ ^~~~~~~~~~~
> fs/open.c:801:31: warning: format specifies type 'void *' but the argument has type 'long' [-Wformat]
> 800 | printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
> | ~~
> | %ld
> 801 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> include/linux/printk.h:512:60: note: expanded from macro 'printk'
> 512 | #define printk(fmt, ...) printk_index_wrap(_printk, fmt, ##__VA_ARGS__)
> | ~~~ ^~~~~~~~~~~
> include/linux/printk.h:484:19: note: expanded from macro 'printk_index_wrap'
> 484 | _p_func(_fmt, ##__VA_ARGS__); \
> | ~~~~ ^~~~~~~~~~~
> 4 warnings generated.
>
>
> vim +771 fs/open.c
>
> 750
> 751 int chown_common(const struct path *path, uid_t user, gid_t group)
> 752 {
> 753 struct mnt_idmap *idmap;
> 754 struct user_namespace *fs_userns;
> 755 struct inode *inode = path->dentry->d_inode;
> 756 struct inode *delegated_inode = NULL;
> 757 int error;
> 758 struct iattr newattrs;
> 759 kuid_t uid;
> 760 kgid_t gid;
> 761
> 762 uid = make_kuid(current_user_ns(), user);
> 763 gid = make_kgid(current_user_ns(), group);
> 764
> 765 idmap = mnt_idmap(path->mnt);
> 766 fs_userns = i_user_ns(inode);
> 767
> 768 retry_deleg:
> 769 printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
> 770 current->comm, inode, atomic_read(&inode->i_count),
> > 771 atomic_long_read(&inode->i_rwsem.owner));
> 772 newattrs.ia_vfsuid = INVALID_VFSUID;
> 773 newattrs.ia_vfsgid = INVALID_VFSGID;
> 774 newattrs.ia_valid = ATTR_CTIME;
> 775 if ((user != (uid_t)-1) && !setattr_vfsuid(&newattrs, uid))
> 776 return -EINVAL;
> 777 if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid))
> 778 return -EINVAL;
> 779 printk("DEBUG: [%s] before inode_lock: inode=%p, i_count=%d\n",
> 780 current->comm, inode, atomic_read(&inode->i_count));
> 781 error = inode_lock_killable(inode);
> 782 if (error)
> 783 return error;
> 784 printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
> 785 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
> 786 if (!S_ISDIR(inode->i_mode))
> 787 newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV |
> 788 setattr_should_drop_sgid(idmap, inode);
> 789 /* Continue to send actual fs values, not the mount values. */
> 790 error = security_path_chown(
> 791 path,
> 792 from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid),
> 793 from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid));
> 794 if (!error)
> 795 error = notify_change(idmap, path->dentry, &newattrs,
> 796 &delegated_inode);
> 797 printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
> 798 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
> 799 inode_unlock(inode);
> 800 printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
> 801 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
> 802 if (delegated_inode) {
> 803 printk("DEBUG: [%s] calling break_deleg_wait: inode=%p, i_count=%d, delegated_inode=%p\n",
> 804 current->comm, inode, atomic_read(&inode->i_count), delegated_inode);
> 805 error = break_deleg_wait(&delegated_inode);
> 806 printk("DEBUG: [%s] after break_deleg_wait: inode=%p, i_count=%d, error=%d\n",
> 807 current->comm, inode, atomic_read(&inode->i_count), error);
> 808 if (!error)
> 809 goto retry_deleg;
> 810 }
> 811 return error;
> 812 }
> 813
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-11-09 12:17 ` kernel test robot
@ 2025-11-09 12:26 ` Philip Li
0 siblings, 0 replies; 26+ messages in thread
From: Philip Li @ 2025-11-09 12:26 UTC (permalink / raw)
To: kernel test robot; +Cc: syzbot, linux-kernel, syzkaller-bugs, oe-kbuild-all
On Sun, Nov 09, 2025 at 08:17:42PM +0800, kernel test robot wrote:
> Hi syzbot,
Sorry, kindly ignore this report.
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on brauner-vfs/vfs.all]
> [also build test WARNING on linus/master v6.18-rc4 next-20251107]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url: https://github.com/intel-lab-lkp/linux/commits/syzbot/Forwarded-PATCH-fs-fix-inode-use-after-free-in-chown_common-delegation-retry/20251109-171000
> base: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git vfs.all
> patch link: https://lore.kernel.org/r/691059ff.a70a0220.22f260.00a6.GAE%40google.com
> patch subject: Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
> config: i386-allnoconfig (https://download.01.org/0day-ci/archive/20251109/202511091831.tPcsumuB-lkp@intel.com/config)
> compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251109/202511091831.tPcsumuB-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202511091831.tPcsumuB-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> In file included from include/asm-generic/bug.h:22,
> from arch/x86/include/asm/bug.h:108,
> from include/linux/bug.h:5,
> from include/linux/mmdebug.h:5,
> from include/linux/mm.h:6,
> from fs/open.c:9:
> fs/open.c: In function 'chown_common':
> >> fs/open.c:769:16: warning: format '%p' expects argument of type 'void *', but argument 5 has type 'long int' [-Wformat=]
> 769 | printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 770 | current->comm, inode, atomic_read(&inode->i_count),
> 771 | atomic_long_read(&inode->i_rwsem.owner));
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> | |
> | long int
> include/linux/printk.h:484:25: note: in definition of macro 'printk_index_wrap'
> 484 | _p_func(_fmt, ##__VA_ARGS__); \
> | ^~~~
> fs/open.c:769:9: note: in expansion of macro 'printk'
> 769 | printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
> | ^~~~~~
> fs/open.c:769:79: note: format string is defined here
> 769 | printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
> | ~^
> | |
> | void *
> | %ld
> fs/open.c:784:16: warning: format '%p' expects argument of type 'void *', but argument 4 has type 'long int' [-Wformat=]
> 784 | printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 785 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> | |
> | long int
> include/linux/printk.h:484:25: note: in definition of macro 'printk_index_wrap'
> 484 | _p_func(_fmt, ##__VA_ARGS__); \
> | ^~~~
> fs/open.c:784:9: note: in expansion of macro 'printk'
> 784 | printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
> | ^~~~~~
> fs/open.c:784:72: note: format string is defined here
> 784 | printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
> | ~^
> | |
> | void *
> | %ld
> fs/open.c:797:16: warning: format '%p' expects argument of type 'void *', but argument 4 has type 'long int' [-Wformat=]
> 797 | printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 798 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> | |
> | long int
> include/linux/printk.h:484:25: note: in definition of macro 'printk_index_wrap'
> 484 | _p_func(_fmt, ##__VA_ARGS__); \
> | ^~~~
> fs/open.c:797:9: note: in expansion of macro 'printk'
> 797 | printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
> | ^~~~~~
> fs/open.c:797:75: note: format string is defined here
> 797 | printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
> | ~^
> | |
> | void *
> | %ld
> fs/open.c:800:16: warning: format '%p' expects argument of type 'void *', but argument 4 has type 'long int' [-Wformat=]
> 800 | printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 801 | current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> | |
> | long int
> include/linux/printk.h:484:25: note: in definition of macro 'printk_index_wrap'
> 484 | _p_func(_fmt, ##__VA_ARGS__); \
> | ^~~~
> fs/open.c:800:9: note: in expansion of macro 'printk'
> 800 | printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
> | ^~~~~~
> fs/open.c:800:74: note: format string is defined here
> 800 | printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
> | ~^
> | |
> | void *
> | %ld
>
>
> vim +769 fs/open.c
>
> 750
> 751 int chown_common(const struct path *path, uid_t user, gid_t group)
> 752 {
> 753 struct mnt_idmap *idmap;
> 754 struct user_namespace *fs_userns;
> 755 struct inode *inode = path->dentry->d_inode;
> 756 struct inode *delegated_inode = NULL;
> 757 int error;
> 758 struct iattr newattrs;
> 759 kuid_t uid;
> 760 kgid_t gid;
> 761
> 762 uid = make_kuid(current_user_ns(), user);
> 763 gid = make_kgid(current_user_ns(), group);
> 764
> 765 idmap = mnt_idmap(path->mnt);
> 766 fs_userns = i_user_ns(inode);
> 767
> 768 retry_deleg:
> > 769 printk("DEBUG: [%s] retry_deleg: inode=%p, i_count=%d, i_rwsem.owner=%px\n",
> 770 current->comm, inode, atomic_read(&inode->i_count),
> 771 atomic_long_read(&inode->i_rwsem.owner));
> 772 newattrs.ia_vfsuid = INVALID_VFSUID;
> 773 newattrs.ia_vfsgid = INVALID_VFSGID;
> 774 newattrs.ia_valid = ATTR_CTIME;
> 775 if ((user != (uid_t)-1) && !setattr_vfsuid(&newattrs, uid))
> 776 return -EINVAL;
> 777 if ((group != (gid_t)-1) && !setattr_vfsgid(&newattrs, gid))
> 778 return -EINVAL;
> 779 printk("DEBUG: [%s] before inode_lock: inode=%p, i_count=%d\n",
> 780 current->comm, inode, atomic_read(&inode->i_count));
> 781 error = inode_lock_killable(inode);
> 782 if (error)
> 783 return error;
> 784 printk("DEBUG: [%s] after inode_lock: inode=%p, i_rwsem.owner=%px (current=%px)\n",
> 785 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), current);
> 786 if (!S_ISDIR(inode->i_mode))
> 787 newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV |
> 788 setattr_should_drop_sgid(idmap, inode);
> 789 /* Continue to send actual fs values, not the mount values. */
> 790 error = security_path_chown(
> 791 path,
> 792 from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid),
> 793 from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid));
> 794 if (!error)
> 795 error = notify_change(idmap, path->dentry, &newattrs,
> 796 &delegated_inode);
> 797 printk("DEBUG: [%s] before inode_unlock: inode=%p, i_rwsem.owner=%px, delegated_inode=%p\n",
> 798 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner), delegated_inode);
> 799 inode_unlock(inode);
> 800 printk("DEBUG: [%s] after inode_unlock: inode=%p, i_rwsem.owner=%px\n",
> 801 current->comm, inode, atomic_long_read(&inode->i_rwsem.owner));
> 802 if (delegated_inode) {
> 803 printk("DEBUG: [%s] calling break_deleg_wait: inode=%p, i_count=%d, delegated_inode=%p\n",
> 804 current->comm, inode, atomic_read(&inode->i_count), delegated_inode);
> 805 error = break_deleg_wait(&delegated_inode);
> 806 printk("DEBUG: [%s] after break_deleg_wait: inode=%p, i_count=%d, error=%d\n",
> 807 current->comm, inode, atomic_read(&inode->i_count), error);
> 808 if (!error)
> 809 goto retry_deleg;
> 810 }
> 811 return error;
> 812 }
> 813
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests/wiki
>
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251109122513.1139397-1-kartikey406@gmail.com>
@ 2025-11-09 13:02 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 13:02 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
BUG: About to unlock rwsem we don't own!
After security_path_chown: owner=ffff888033982480
After notify_change: owner=0, error=0
BUG: About to unlock rwsem we don't own!
inode=ffff8880112b4f80
i_rwsem.owner=0
current=ffff888033982480
delegated_inode=0000000000000000
CPU: 0 UID: 0 PID: 5838 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
chown_common+0x659/0x700 fs/open.c:803
do_fchownat+0x161/0x270 fs/open.c:834
__do_sys_fchownat fs/open.c:849 [inline]
__se_sys_fchownat fs/open.c:846 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:846
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fd235d8efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007fd236c11038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007fd235fe6090 RCX: 00007fd235d8efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007fd235e11f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fd235fe6128 R14: 00007fd235fe6090 R15: 00007ffe7f7950f8
</TASK>
------------[ cut here ]------------
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff8880112b5058, owner = 0x0, curr 0xffff888033982480, list empty
WARNING: CPU: 0 PID: 5838 at kernel/locking/rwsem.c:1381 __up_write kernel/locking/rwsem.c:1380 [inline]
WARNING: CPU: 0 PID: 5838 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Modules linked in:
CPU: 0 UID: 0 PID: 5838 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:__up_write kernel/locking/rwsem.c:1380 [inline]
RIP: 0010:up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Code: d0 48 c7 c7 20 ff 6a 8b 48 c7 c6 40 01 6b 8b 48 8b 14 24 4c 89 f1 4d 89 e0 4c 8b 4c 24 08 41 52 e8 c3 35 e6 ff 48 83 c4 08 90 <0f> 0b 90 90 e9 6d fd ff ff 48 c7 c1 94 34 7d 8f 80 e1 07 80 c1 03
RSP: 0018:ffffc90002a3fbf0 EFLAGS: 00010296
RAX: 9a6f5dfb05cd2e00 RBX: ffff8880112b5058 RCX: ffff888033982480
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000002
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffffbfff1bba684 R12: 0000000000000000
R13: ffff8880112b50b0 R14: ffff8880112b5058 R15: 1ffff11002256a0c
FS: 00007fd236c116c0(0000) GS:ffff88808d730000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007faf3f3f7f50 CR3: 0000000059dc8000 CR4: 0000000000352ef0
Call Trace:
<TASK>
inode_unlock include/linux/fs.h:990 [inline]
chown_common+0x4e3/0x700 fs/open.c:805
do_fchownat+0x161/0x270 fs/open.c:834
__do_sys_fchownat fs/open.c:849 [inline]
__se_sys_fchownat fs/open.c:846 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:846
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fd235d8efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007fd236c11038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007fd235fe6090 RCX: 00007fd235d8efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007fd235e11f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fd235fe6128 R14: 00007fd235fe6090 R15: 00007ffe7f7950f8
</TASK>
Tested on:
commit: 439fc29d Merge tag 'drm-fixes-2025-11-09' of https://g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=168e517c580000
kernel config: https://syzkaller.appspot.com/x/.config?x=929790bc044e87d7
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=1126517c580000
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
` (7 preceding siblings ...)
2025-11-09 12:25 ` syzbot
@ 2025-11-09 13:27 ` syzbot
2025-11-09 14:29 ` syzbot
2025-11-09 15:16 ` syzbot
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 13:27 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
Author: kartikey406@gmail.com
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The chown_common() function has a use-after-free bug in its delegation
retry path. When break_deleg_wait() is called, it internally calls
iput() on the delegated inode, potentially freeing it if this was the
last reference. However, chown_common() continues using the stale inode
pointer on retry, leading to operations on freed memory.
This manifests as a rwsem warning where the inode's rwsem owner field
is corrupted:
DEBUG_RWSEMS_WARN_ON: owner = 0x0
The bug is triggered by concurrent fchownat() calls and is reproducible
on GFS2 filesystems where delegations are common.
Fix by:
1. Re-fetching inode from path->dentry->d_inode on each retry iteration
2. Holding an explicit inode reference with ihold() at iteration start
3. Releasing the reference with iput() on all exit paths
This ensures the inode remains valid throughout delegation break and
retry.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 12 ++++++++++++
include/linux/fs.h | 5 +++++
2 files changed, 17 insertions(+)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..e5ff4d052f80 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -787,9 +787,21 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
path,
from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid),
from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid));
+ printk(KERN_INFO "After security_path_chown: owner=%lx\n",
+ atomic_long_read(&inode->i_rwsem.owner));
if (!error)
error = notify_change(idmap, path->dentry, &newattrs,
&delegated_inode);
+ printk(KERN_INFO "After notify_change: owner=%lx, error=%d\n",
+ atomic_long_read(&inode->i_rwsem.owner), error);
+ if (atomic_long_read(&inode->i_rwsem.owner) != (long)current) {
+ printk(KERN_ERR "BUG: About to unlock rwsem we don't own!\n");
+ printk(KERN_ERR " inode=%p\n", inode);
+ printk(KERN_ERR " i_rwsem.owner=%lx\n", atomic_long_read(&inode->i_rwsem.owner));
+ printk(KERN_ERR " current=%p\n", current);
+ printk(KERN_ERR " delegated_inode=%p\n", delegated_inode);
+ dump_stack();
+ }
inode_unlock(inode);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c895146c1444..84f7267aac3d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -987,6 +987,11 @@ static inline __must_check int inode_lock_killable(struct inode *inode)
static inline void inode_unlock(struct inode *inode)
{
+ printk(KERN_INFO "[%d] inode_unlock: inode=%p, owner=%lx, current=%p (%s:%d)\n",
+ count, inode,
+ atomic_long_read(&inode->i_rwsem.owner),
+ current, current->comm, current->pid);
+ dump_stack();
up_write(&inode->i_rwsem);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251109132736.1141174-1-kartikey406@gmail.com>
@ 2025-11-09 13:29 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 13:29 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs
Hello,
syzbot tried to test the proposed patch but the build/boot failed:
./include/linux/fs.h:991:9: error: use of undeclared identifier 'count'
Tested on:
commit: 439fc29d Merge tag 'drm-fixes-2025-11-09' of https://g..
git tree: upstream
kernel config: https://syzkaller.appspot.com/x/.config?x=df98b4d1d5944c56
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=10eb8412580000
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
` (8 preceding siblings ...)
2025-11-09 13:27 ` syzbot
@ 2025-11-09 14:29 ` syzbot
2025-11-09 15:16 ` syzbot
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 14:29 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
Author: kartikey406@gmail.com
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The chown_common() function has a use-after-free bug in its delegation
retry path. When break_deleg_wait() is called, it internally calls
iput() on the delegated inode, potentially freeing it if this was the
last reference. However, chown_common() continues using the stale inode
pointer on retry, leading to operations on freed memory.
This manifests as a rwsem warning where the inode's rwsem owner field
is corrupted:
DEBUG_RWSEMS_WARN_ON: owner = 0x0
The bug is triggered by concurrent fchownat() calls and is reproducible
on GFS2 filesystems where delegations are common.
Fix by:
1. Re-fetching inode from path->dentry->d_inode on each retry iteration
2. Holding an explicit inode reference with ihold() at iteration start
3. Releasing the reference with iput() on all exit paths
This ensures the inode remains valid throughout delegation break and
retry.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/open.c | 12 ++++++++++++
include/linux/fs.h | 5 +++++
2 files changed, 17 insertions(+)
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..e5ff4d052f80 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -787,9 +787,21 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
path,
from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid),
from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid));
+ printk(KERN_INFO "After security_path_chown: owner=%lx\n",
+ atomic_long_read(&inode->i_rwsem.owner));
if (!error)
error = notify_change(idmap, path->dentry, &newattrs,
&delegated_inode);
+ printk(KERN_INFO "After notify_change: owner=%lx, error=%d\n",
+ atomic_long_read(&inode->i_rwsem.owner), error);
+ if (atomic_long_read(&inode->i_rwsem.owner) != (long)current) {
+ printk(KERN_ERR "BUG: About to unlock rwsem we don't own!\n");
+ printk(KERN_ERR " inode=%p\n", inode);
+ printk(KERN_ERR " i_rwsem.owner=%lx\n", atomic_long_read(&inode->i_rwsem.owner));
+ printk(KERN_ERR " current=%p\n", current);
+ printk(KERN_ERR " delegated_inode=%p\n", delegated_inode);
+ dump_stack();
+ }
inode_unlock(inode);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c895146c1444..005586e26688 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -987,6 +987,11 @@ static inline __must_check int inode_lock_killable(struct inode *inode)
static inline void inode_unlock(struct inode *inode)
{
+ printk(KERN_INFO "inode_unlock: inode=%p, owner=%lx, current=%p (%s:%d)\n",
+ inode,
+ atomic_long_read(&inode->i_rwsem.owner),
+ current, current->comm, current->pid);
+ dump_stack();
up_write(&inode->i_rwsem);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251109142934.1142273-1-kartikey406@gmail.com>
@ 2025-11-09 15:05 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 15:05 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
BUG: About to unlock rwsem we don't own!
After notify_change: owner=0, error=0
BUG: About to unlock rwsem we don't own!
inode=ffff888043102e60
i_rwsem.owner=0
current=ffff88801fbd8000
delegated_inode=0000000000000000
CPU: 0 UID: 0 PID: 5829 Comm: syz.0.21 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
chown_common+0x555/0x6f0 fs/open.c:803
do_fchownat+0x161/0x270 fs/open.c:834
__do_sys_fchownat fs/open.c:849 [inline]
__se_sys_fchownat fs/open.c:846 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:846
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f7f3658efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007f7f373a1038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007f7f367e6090 RCX: 00007f7f3658efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007f7f36611f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f7f367e6128 R14: 00007f7f367e6090 R15: 00007fff1e869178
</TASK>
inode_unlock: inode=ffff888043102e60, owner=0, current=ffff88801fbd8000 (syz.0.21:5829)
CPU: 0 UID: 0 PID: 5829 Comm: syz.0.21 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
inode_unlock+0x92/0xd0 include/linux/fs.h:994
chown_common+0x55f/0x6f0 fs/open.c:805
do_fchownat+0x161/0x270 fs/open.c:834
__do_sys_fchownat fs/open.c:849 [inline]
__se_sys_fchownat fs/open.c:846 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:846
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f7f3658efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007f7f373a1038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007f7f367e6090 RCX: 00007f7f3658efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007f7f36611f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f7f367e6128 R14: 00007f7f367e6090 R15: 00007fff1e869178
</TASK>
------------[ cut here ]------------
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff888043102f38, owner = 0x0, curr 0xffff88801fbd8000, list empty
WARNING: CPU: 0 PID: 5829 at kernel/locking/rwsem.c:1381 __up_write kernel/locking/rwsem.c:1380 [inline]
WARNING: CPU: 0 PID: 5829 at kernel/locking/rwsem.c:1381 up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Modules linked in:
CPU: 0 UID: 0 PID: 5829 Comm: syz.0.21 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:__up_write kernel/locking/rwsem.c:1380 [inline]
RIP: 0010:up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Code: d0 48 c7 c7 80 ff 6a 8b 48 c7 c6 a0 01 6b 8b 48 8b 14 24 4c 89 f1 4d 89 e0 4c 8b 4c 24 08 41 52 e8 b3 35 e6 ff 48 83 c4 08 90 <0f> 0b 90 90 e9 6d fd ff ff 48 c7 c1 94 55 7d 8f 80 e1 07 80 c1 03
RSP: 0018:ffffc90002e77bf0 EFLAGS: 00010296
RAX: 59e03a60efe32100 RBX: ffff888043102f38 RCX: ffff88801fbd8000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000002
RBP: dffffc0000000000 R08: ffffffff8f7d2577 R09: 1ffffffff1efa4ae
R10: dffffc0000000000 R11: fffffbfff1efa4af R12: 0000000000000000
R13: ffff888043102f90 R14: ffff888043102f38 R15: 1ffff110086205e8
FS: 00007f7f373a16c0(0000) GS:ffff88808d729000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000043752000 CR4: 0000000000352ef0
Call Trace:
<TASK>
chown_common+0x55f/0x6f0 fs/open.c:805
do_fchownat+0x161/0x270 fs/open.c:834
__do_sys_fchownat fs/open.c:849 [inline]
__se_sys_fchownat fs/open.c:846 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:846
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f7f3658efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007f7f373a1038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007f7f367e6090 RCX: 00007f7f3658efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007f7f36611f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f7f367e6128 R14: 00007f7f367e6090 R15: 00007fff1e869178
</TASK>
Tested on:
commit: 439fc29d Merge tag 'drm-fixes-2025-11-09' of https://g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=15f21a58580000
kernel config: https://syzkaller.appspot.com/x/.config?x=929790bc044e87d7
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=1624d0b4580000
^ permalink raw reply [flat|nested] 26+ messages in thread
* Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
` (9 preceding siblings ...)
2025-11-09 14:29 ` syzbot
@ 2025-11-09 15:16 ` syzbot
10 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 15:16 UTC (permalink / raw)
To: linux-kernel, syzkaller-bugs
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] fs: fix inode use-after-free in chown_common delegation retry
Author: kartikey406@gmail.com
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
The chown_common() function has a use-after-free bug in its delegation
retry path. When break_deleg_wait() is called, it internally calls
iput() on the delegated inode, potentially freeing it if this was the
last reference. However, chown_common() continues using the stale inode
pointer on retry, leading to operations on freed memory.
This manifests as a rwsem warning where the inode's rwsem owner field
is corrupted:
DEBUG_RWSEMS_WARN_ON: owner = 0x0
The bug is triggered by concurrent fchownat() calls and is reproducible
on GFS2 filesystems where delegations are common.
Fix by:
1. Re-fetching inode from path->dentry->d_inode on each retry iteration
2. Holding an explicit inode reference with ihold() at iteration start
3. Releasing the reference with iput() on all exit paths
This ensures the inode remains valid throughout delegation break and
retry.
Reported-by: syzbot+04c2672c56fbb9401640@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
fs/attr.c | 5 ++++-
fs/open.c | 12 ++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/fs/attr.c b/fs/attr.c
index 795f231d00e8..a45d29032283 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -418,6 +418,8 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
struct iattr *attr, struct inode **delegated_inode)
{
struct inode *inode = dentry->d_inode;
+ printk(KERN_INFO "notify_change START: inode=%p, owner=%lx\n",
+ inode, atomic_long_read(&inode->i_rwsem.owner));
umode_t mode = inode->i_mode;
int error;
struct timespec64 now;
@@ -551,7 +553,8 @@ int notify_change(struct mnt_idmap *idmap, struct dentry *dentry,
fsnotify_change(dentry, ia_valid);
security_inode_post_setattr(idmap, dentry, ia_valid);
}
-
+ printk(KERN_INFO "notify_change END: inode=%p, owner=%lx, error=%d\n",
+ inode, atomic_long_read(&inode->i_rwsem.owner), error);
return error;
}
EXPORT_SYMBOL(notify_change);
diff --git a/fs/open.c b/fs/open.c
index 3d64372ecc67..e5ff4d052f80 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -787,9 +787,21 @@ int chown_common(const struct path *path, uid_t user, gid_t group)
path,
from_vfsuid(idmap, fs_userns, newattrs.ia_vfsuid),
from_vfsgid(idmap, fs_userns, newattrs.ia_vfsgid));
+ printk(KERN_INFO "After security_path_chown: owner=%lx\n",
+ atomic_long_read(&inode->i_rwsem.owner));
if (!error)
error = notify_change(idmap, path->dentry, &newattrs,
&delegated_inode);
+ printk(KERN_INFO "After notify_change: owner=%lx, error=%d\n",
+ atomic_long_read(&inode->i_rwsem.owner), error);
+ if (atomic_long_read(&inode->i_rwsem.owner) != (long)current) {
+ printk(KERN_ERR "BUG: About to unlock rwsem we don't own!\n");
+ printk(KERN_ERR " inode=%p\n", inode);
+ printk(KERN_ERR " i_rwsem.owner=%lx\n", atomic_long_read(&inode->i_rwsem.owner));
+ printk(KERN_ERR " current=%p\n", current);
+ printk(KERN_ERR " delegated_inode=%p\n", delegated_inode);
+ dump_stack();
+ }
inode_unlock(inode);
if (delegated_inode) {
error = break_deleg_wait(&delegated_inode);
--
2.43.0
^ permalink raw reply related [flat|nested] 26+ messages in thread
* Re: [syzbot] [gfs2?] WARNING in chown_common
[not found] <20251109151559.1145822-1-kartikey406@gmail.com>
@ 2025-11-09 15:32 ` syzbot
0 siblings, 0 replies; 26+ messages in thread
From: syzbot @ 2025-11-09 15:32 UTC (permalink / raw)
To: kartikey406, linux-kernel, syzkaller-bugs
Hello,
syzbot has tested the proposed patch but the reproducer is still triggering an issue:
WARNING in notify_change
After security_path_chown: owner=ffff88801c36c900
notify_change START: inode=ffff8880411c5620, owner=ffff88801c36c900
------------[ cut here ]------------
WARNING: CPU: 0 PID: 5846 at fs/attr.c:428 notify_change+0xc5e/0xef0 fs/attr.c:428
Modules linked in:
CPU: 0 UID: 0 PID: 5846 Comm: syz.0.20 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:notify_change+0xc5e/0xef0 fs/attr.c:428
Code: ff e8 26 41 ff 00 48 8b 93 e0 00 00 00 48 c7 c7 20 ae 79 8b 48 89 de 44 89 f1 e8 3d 5f ff ff e9 e5 fe ff ff e8 93 00 98 00 90 <0f> 0b 90 e9 b0 f4 ff ff 44 89 e9 80 e1 07 fe c1 38 c1 0f 8c 34 f4
RSP: 0018:ffffc9000cfbfba8 EFLAGS: 00010293
RAX: ffffffff812832dd RBX: 0000000000000046 RCX: ffff88801c36c900
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: dffffc0000000000 R08: ffff8880411c56ff R09: 1ffff11008238adf
R10: dffffc0000000000 R11: ffffed1008238ae0 R12: ffff88800043eeb0
R13: ffff8880411c5620 R14: 0000000000000000 R15: ffff8880411c5700
FS: 00007f1d976436c0(0000) GS:ffff88808d730000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f1d968a6e60 CR3: 000000004de5d000 CR4: 0000000000352ef0
Call Trace:
<TASK>
chown_common+0x44a/0x700 fs/open.c:793
do_fchownat+0x161/0x270 fs/open.c:834
__do_sys_fchownat fs/open.c:849 [inline]
__se_sys_fchownat fs/open.c:846 [inline]
__x64_sys_fchownat+0xb5/0xd0 fs/open.c:846
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f1d9678efc9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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:00007f1d97643038 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
RAX: ffffffffffffffda RBX: 00007f1d969e6090 RCX: 00007f1d9678efc9
RDX: 0000000000000000 RSI: 0000200000000000 RDI: ffffffffffffff9c
RBP: 00007f1d96811f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f1d969e6128 R14: 00007f1d969e6090 R15: 00007ffc482e6f78
</TASK>
Tested on:
commit: 439fc29d Merge tag 'drm-fixes-2025-11-09' of https://g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1679517c580000
kernel config: https://syzkaller.appspot.com/x/.config?x=929790bc044e87d7
dashboard link: https://syzkaller.appspot.com/bug?extid=04c2672c56fbb9401640
compiler: Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
patch: https://syzkaller.appspot.com/x/patch.diff?x=17309412580000
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2025-11-09 15:32 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-12 5:45 [syzbot] [gfs2?] WARNING in chown_common syzbot
2025-10-17 8:57 ` Forwarded: [PATCH] fs: fix stale inode access in chown_common() retry path syzbot
2025-10-17 8:57 ` syzbot
2025-10-29 8:23 ` Forwarded: Test patch for [syzbot] [gfs2?] WARNING in chown_common syzbot
2025-11-09 5:02 ` Forwarded: [PATCH] fs: fix inode reference leak in chown_common delegation retry path syzbot
2025-11-09 9:08 ` Forwarded: [PATCH] fs: fix inode use-after-free in chown_common delegation retry syzbot
2025-11-09 11:05 ` kernel test robot
2025-11-09 12:26 ` Philip Li
2025-11-09 12:17 ` kernel test robot
2025-11-09 12:26 ` Philip Li
2025-11-09 11:40 ` syzbot
2025-11-09 11:57 ` syzbot
2025-11-09 12:25 ` syzbot
2025-11-09 13:27 ` syzbot
2025-11-09 14:29 ` syzbot
2025-11-09 15:16 ` syzbot
[not found] <20251017085719.821125-1-kartikey406@gmail.com>
2025-10-17 9:20 ` [syzbot] [gfs2?] WARNING in chown_common syzbot
[not found] <CAMz+-CPDh3FF3Fso8UjYyd0=uyV2hJvYQLTVracNyo896rsF1A@mail.gmail.com>
2025-10-29 10:53 ` syzbot
[not found] <20251109050218.648149-1-kartikey406@gmail.com>
2025-11-09 5:17 ` syzbot
[not found] <20251109090808.839886-1-kartikey406@gmail.com>
2025-11-09 9:30 ` syzbot
[not found] <20251109114011.1100867-1-kartikey406@gmail.com>
2025-11-09 11:56 ` syzbot
[not found] <20251109115742.1138274-1-kartikey406@gmail.com>
2025-11-09 12:14 ` syzbot
[not found] <20251109122513.1139397-1-kartikey406@gmail.com>
2025-11-09 13:02 ` syzbot
[not found] <20251109132736.1141174-1-kartikey406@gmail.com>
2025-11-09 13:29 ` syzbot
[not found] <20251109142934.1142273-1-kartikey406@gmail.com>
2025-11-09 15:05 ` syzbot
[not found] <20251109151559.1145822-1-kartikey406@gmail.com>
2025-11-09 15:32 ` syzbot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox