From: Andrew Morton <akpm@linux-foundation.org>
To: mm-commits@vger.kernel.org,stable@vger.kernel.org,mark@fasheh.com,joseph.qi@linux.alibaba.com,jlbec@evilplan.org,jjzuming@gmail.com,jack@suse.cz,heming.zhao@suse.com,chao@kernel.org,baijiaju1990@gmail.com,zzzccc427@gmail.com,akpm@linux-foundation.org
Subject: + ocfs2-cancel-quota-sync-work-before-freeing-quota-info.patch added to mm-nonmm-unstable branch
Date: Wed, 14 Oct 2026 14:53:43 -0700 [thread overview]
Message-ID: <20261014215343.7995B1F000C4@smtp.kernel.org> (raw)
The patch titled
Subject: ocfs2: cancel quota sync work before freeing quota info
has been added to the -mm mm-nonmm-unstable branch. Its filename is
ocfs2-cancel-quota-sync-work-before-freeing-quota-info.patch
This patch will shortly appear at
https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/ocfs2-cancel-quota-sync-work-before-freeing-quota-info.patch
This patch will later appear in the mm-nonmm-unstable branch at
git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Before you just go and hit "reply", please:
a) Consider who else should be cc'ed
b) Prefer to cc a suitable mailing list as well
c) Ideally: find the original patch on the mailing list and do a
reply-to-all to that, adding suitable additional cc's
*** Remember to use Documentation/process/submit-checklist.rst when testing your code ***
The -mm tree is included into linux-next via various
branches at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
and is updated there most days
------------------------------------------------------
From: Cen Zhang <zzzccc427@gmail.com>
Subject: ocfs2: cancel quota sync work before freeing quota info
Date: Wed, 14 Oct 2026 11:43:40 +0800
OCFS2 quota info owns dqi_sync_work and must outlive both its timer and
qsync_work_fn(). ocfs2_local_free_info() frees that owner without
cancelling the work, relying on the quota suspend/disable wrappers.
Loading quotas on a read-only to read-write remount can successfully queue
the work in ocfs2_global_read_info() and then fail while attaching a dquot
to an existing inode in add_dquot_ref(). The quota core unwinds that
failure directly through dquot_disable(), bypassing the OCFS2 wrapper:
Remount task (s_umount write) Timer/workqueue
ocfs2_global_read_info()
schedules dqi_sync_work
add_dquot_ref() returns an error
dquot_disable()
ocfs2_local_free_info()
frees oinfo
delayed-work timer expires
qsync_work_fn() reads oinfo
The timer core can then write to the freed embedded timer, or
qsync_work_fn() can read oinfo->dqi_gqinode before its s_umount trylock.
The outer ocfs2_disable_quotas() cleanup skips the failed type because
dquot_disable() has already cleared its loaded state.
Cancel dqi_sync_work synchronously at the start of
ocfs2_local_free_info(), before dropping the global inode or freeing any
owner state. The work is initialized whenever read_file_info() succeeds.
dquot_disable() holds s_umount for write, so the callback skips its quota
scan via down_read_trylock() and can finish without waiting for teardown.
The synchronous cancel also handles its self-rearm.
KASAN report as below:
BUG: KASAN: slab-use-after-free in __run_timers+0x9e9/0xa10
Write of size 8 at addr ffff888111b0aad0 by task swapper/3/0
Call Trace:
<IRQ>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? __run_timers+0x9e9/0xa10
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20e/0x420
? __run_timers+0x9e9/0xa10
kasan_report+0xe0/0x110
? __run_timers+0x9e9/0xa10
__run_timers+0x9e9/0xa10
? __pfx___run_timers+0x10/0x10
? __lock_acquire+0x5a3/0x2140
? __pfx_do_raw_spin_lock+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
timer_expire_remote+0xfa/0x160
? __pfx_timer_expire_remote+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? srso_alias_return_thunk+0x5/0xfbef5
? trace_hardirqs_on+0x18/0x160
tmigr_handle_remote_up+0x4ba/0x9d0
? __pfx_tmigr_handle_remote_up+0x10/0x10
? tmigr_handle_remote+0x21a/0x340
? srso_alias_return_thunk+0x5/0xfbef5
? lock_release+0xc8/0x290
? __pfx_tmigr_handle_remote_up+0x10/0x10
__walk_groups_from+0x5a/0x160
tmigr_handle_remote+0x24f/0x340
? __pfx_tmigr_handle_remote+0x10/0x10
? lock_acquire+0x190/0x300
? srso_alias_return_thunk+0x5/0xfbef5
? lock_release+0xc8/0x290
run_timer_softirq+0x222/0x270
? __pfx_run_timer_softirq+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? srso_alias_return_thunk+0x5/0xfbef5
? lockdep_hardirqs_on_prepare+0xb8/0x1a0
? srso_alias_return_thunk+0x5/0xfbef5
handle_softirqs+0x1fa/0x8d0
? __pfx_handle_softirqs+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? _raw_spin_unlock+0x23/0x40
? srso_alias_return_thunk+0x5/0xfbef5
? __hrtimer_rearm_deferred+0x1fb/0x5d0
__irq_exit_rcu+0x113/0x1e0
irq_exit_rcu+0xe/0x20
sysvec_apic_timer_interrupt+0x6c/0x80
</IRQ>
<TASK>
asm_sysvec_apic_timer_interrupt+0x1a/0x20
? ct_kernel_exit.constprop.0+0xc5/0xf0
? do_idle+0x3ae/0x650
default_idle+0x9/0x10
default_idle_call+0x6c/0xb0
do_idle+0x3ae/0x650
? cpuhp_online_idle+0x9c/0xb0
? __pfx_do_idle+0x10/0x10
? __entry_text_end+0x1020f6/0x1020f9
? lockdep_hardirqs_on_prepare+0xeb/0x1a0
? srso_alias_return_thunk+0x5/0xfbef5
? trace_hardirqs_on+0x18/0x160
? srso_alias_return_thunk+0x5/0xfbef5
cpu_startup_entry+0x54/0x60
start_secondary+0x223/0x2d0
? __pfx_start_secondary+0x10/0x10
common_startup_64+0x13e/0x158
</TASK>
Allocated by task 523:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x28d/0x610
ocfs2_local_read_info+0x181/0x1580
dquot_load_quota_sb+0x69e/0x11c0
dquot_load_quota_inode+0x227/0x3e0
ocfs2_enable_quotas+0x27c/0x520
ocfs2_reconfigure+0x964/0xd00
reconfigure_super+0x3ca/0xa70
path_mount+0x141e/0x1e80
__x64_sys_mount+0x24b/0x2d0
do_syscall_64+0x114/0x620
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 523:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x308/0x580
ocfs2_local_free_info+0x47b/0x800
dquot_disable+0x5d9/0x17a0
dquot_load_quota_sb+0xd3c/0x11c0
dquot_load_quota_inode+0x227/0x3e0
ocfs2_enable_quotas+0x27c/0x520
ocfs2_reconfigure+0x964/0xd00
reconfigure_super+0x3ca/0xa70
path_mount+0x141e/0x1e80
__x64_sys_mount+0x24b/0x2d0
do_syscall_64+0x114/0x620
entry_SYSCALL_64_after_hwframe+0x77/0x7f
The buggy address belongs to the object at ffff888111b0a800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 720 bytes inside of
freed 1024-byte region [ffff888111b0a800, ffff888111b0ac00)
Host details, register and page dumps omitted.
Link: https://lore.kernel.org/pm-ocfs2-objects-candidate-0052-v3-b4904bd6c85daf033adf@gmail.com
Fixes: 1a6152d36dee ("quota: propagate error from __dquot_initialize")
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Assisted-by: LLM
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Heming Zhao <heming.zhao@suse.com>
Cc: Chao Yu <chao@kernel.org>
Cc: Jia-Ju Bai <baijiaju1990@gmail.com>
Cc: <jjzuming@gmail.com>
Cc: <stable@vger.kernel.org>
---
fs/ocfs2/quota_local.c | 3 +++
1 file changed, 3 insertions(+)
--- a/fs/ocfs2/quota_local.c~ocfs2-cancel-quota-sync-work-before-freeing-quota-info
+++ a/fs/ocfs2/quota_local.c
@@ -840,6 +840,9 @@ static int ocfs2_local_free_info(struct
int mark_clean = 1, len;
int status = 0;
+ /* Quota-core error paths can bypass ocfs2_disable_quotas(). */
+ cancel_delayed_work_sync(&oinfo->dqi_sync_work);
+
iput(oinfo->dqi_gqinode);
ocfs2_simple_drop_lockres(OCFS2_SB(sb), &oinfo->dqi_gqlock);
ocfs2_lock_res_free(&oinfo->dqi_gqlock);
_
Patches currently in -mm which might be from zzzccc427@gmail.com are
ocfs2-heartbeat-unlink-live-slots-when-their-node-is-missing.patch
ocfs2-initialize-status-waiters-before-publishing-them.patch
ocfs2-publish-the-filecheck-owner-before-adding-sysfs-attributes.patch
ocfs2-dlm-hold-a-lock-reference-across-grant-ast-enqueue.patch
ocfs2-cancel-quota-sync-work-before-freeing-quota-info.patch
reply other threads:[~2026-10-14 21:53 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261014215343.7995B1F000C4@smtp.kernel.org \
--to=akpm@linux-foundation.org \
--cc=baijiaju1990@gmail.com \
--cc=chao@kernel.org \
--cc=heming.zhao@suse.com \
--cc=jack@suse.cz \
--cc=jjzuming@gmail.com \
--cc=jlbec@evilplan.org \
--cc=joseph.qi@linux.alibaba.com \
--cc=mark@fasheh.com \
--cc=mm-commits@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=zzzccc427@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.