Commit d15e4b0
ext4: fix use-after-free in update_super_work when racing with umount
Commit b98535d ("ext4: fix bug_on in start_this_handle during umount
filesystem") moved ext4_unregister_sysfs() before flushing s_sb_upd_work
to prevent new error work from being queued via /proc/fs/ext4/xx/mb_groups
reads during unmount. However, this introduced a use-after-free because
update_super_work calls ext4_notify_error_sysfs() -> sysfs_notify() which
accesses the kobject's kernfs_node after it has been freed by kobject_del()
in ext4_unregister_sysfs():
update_super_work ext4_put_super
----------------- --------------
ext4_unregister_sysfs(sb)
kobject_del(&sbi->s_kobj)
__kobject_del()
sysfs_remove_dir()
kobj->sd = NULL
sysfs_put(sd)
kernfs_put() // RCU free
ext4_notify_error_sysfs(sbi)
sysfs_notify(&sbi->s_kobj)
kn = kobj->sd // stale pointer
kernfs_get(kn) // UAF on freed kernfs_node
ext4_journal_destroy()
flush_work(&sbi->s_sb_upd_work)
Instead of reordering the teardown sequence, fix this by making
ext4_notify_error_sysfs() detect that sysfs has already been torn down
by checking s_kobj.state_in_sysfs, and skipping the sysfs_notify() call
in that case. A dedicated mutex (s_error_notify_mutex) serializes
ext4_notify_error_sysfs() against kobject_del() in ext4_unregister_sysfs()
to prevent TOCTOU races where the kobject could be deleted between the
state_in_sysfs check and the sysfs_notify() call.
Fixes: b98535d ("ext4: fix bug_on in start_this_handle during umount filesystem")
Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
Suggested-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260319120336.157873-1-jiayuan.chen@linux.dev
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org1 parent 496bb99 commit d15e4b0
3 files changed
Lines changed: 11 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1570 | 1570 | | |
1571 | 1571 | | |
1572 | 1572 | | |
| 1573 | + | |
1573 | 1574 | | |
1574 | 1575 | | |
1575 | 1576 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5406 | 5406 | | |
5407 | 5407 | | |
5408 | 5408 | | |
| 5409 | + | |
5409 | 5410 | | |
5410 | 5411 | | |
5411 | 5412 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
597 | 597 | | |
598 | 598 | | |
599 | 599 | | |
600 | | - | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
601 | 604 | | |
602 | 605 | | |
603 | 606 | | |
| |||
610 | 613 | | |
611 | 614 | | |
612 | 615 | | |
| 616 | + | |
613 | 617 | | |
614 | 618 | | |
| 619 | + | |
615 | 620 | | |
616 | 621 | | |
617 | 622 | | |
| |||
644 | 649 | | |
645 | 650 | | |
646 | 651 | | |
| 652 | + | |
| 653 | + | |
647 | 654 | | |
| 655 | + | |
648 | 656 | | |
649 | 657 | | |
650 | 658 | | |
| |||
0 commit comments