Re: [PATCH v2] ocfs2: rebase copied fsdlm LVB pointers in locking_state
Joseph Qi <[email protected]> Mon, 25 May 2026 11:26:35 +0800
| Newsgroups | dev.linux.lists.ocfs2-devel |
|---|---|
| Message-ID | <[email protected]> |
On 5/24/26 7:07 PM, Zhang Cen wrote:
> value under ocfs2_dlm_tracking_lock and later formats that copy in
Seens it is cut off at the beginning?
> ocfs2_dlm_seq_show(). That is fine for the inline fields, but the
> userspace fsdlm stack stores the LVB through lksb_fsdlm.sb_lvbptr. Once
> the iterator drops the tracking lock, a copied non-NULL sb_lvbptr still
> points into the original lockres owner, so teardown can free that
>
This is also incomplete.
> Rebase the copied sb_lvbptr to the copied l_lksb before dumping the raw
> LVB. The seq snapshot already carries the inline LVB storage reserved in
> without borrowing the original lockres lifetime.
>
> The buggy scenario involves two paths, with each column showing the order
> within that path:
>
> locking_state reader: lockres teardown:
> 1. ocfs2_dlm_seq_start()/next() 1. file release or another owner
> copies struct ocfs2_lock_res teardown reaches
> 2. ocfs2_dlm_seq_show() formats ocfs2_lock_res_free()
> the copied row 2. the lockres is removed from the
> 3. ocfs2_dlm_lvb() follows the tracking list
> copied sb_lvbptr 3. the owner frees the original
> lockres container
>
> Validation reproduced this kernel report:
> KASAN slab-use-after-free in ocfs2_dlm_seq_show+0x1bd/0x430
> RIP: 0033:0x7f8ec4b1e29d
> The buggy address belongs to the object at ffff88810a1e0800 which belongs
>
And here.
Thanks,
Joseph
> Fixes: cf4d8d75d8ab ("ocfs2: add fsdlm to stackglue")
> Assisted-by: Codex:gpt-5.5
> Signed-off-by: Zhang Cen <[email protected]>
> ---
> v2:
> Document the introducing fsdlm stackglue commit.
>
> fs/ocfs2/dlmglue.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> index 7283bb2c5a31..a23dd8f86c89 100644
> --- a/fs/ocfs2/dlmglue.c
> +++ b/fs/ocfs2/dlmglue.c
> @@ -3134,6 +3134,22 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)
> * - Add last pr/ex unlock times and first lock wait time in usecs
> */
> #define OCFS2_DLM_DEBUG_STR_VERSION 4
> +
> +/*
> + * The debug iterator snapshots lockres by value, so a userspace-stack LVB
> + * pointer copied from the original lockres must be rebased to the copied
> + * lksb before the dump walks the raw bytes.
> + */
> +static void ocfs2_dlm_seq_rebase_lvb(struct ocfs2_lock_res *lockres)
> +{
> + if (!ocfs2_stack_supports_plocks())
> + return;
> +
> + if (lockres->l_lksb.lksb_fsdlm.sb_lvbptr)
> + lockres->l_lksb.lksb_fsdlm.sb_lvbptr =
> + (char *)&lockres->l_lksb + sizeof(struct dlm_lksb);
> +}
> +
> static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
> {
> int i;
> @@ -3191,6 +3207,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
> lockres->l_blocking);
>
> /* Dump the raw LVB */
> + ocfs2_dlm_seq_rebase_lvb(lockres);
> lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
> for(i = 0; i < DLM_LVB_LEN; i++)
> seq_printf(m, "0x%x\t", lvb[i]);