Re: [PATCH v2] ocfs2: rebase copied fsdlm LVB pointers in locking_state

Cen Zhang <[email protected]> Mon, 25 May 2026 11:42:03 +0800
Newsgroups dev.linux.lists.ocfs2-devel
Message-ID <CAB7XQsFfaaymc_2B5O0dA6YmR9vGDqXTpM=QvWmSf+g5BNtmxw@mail.gmail.com>
Hi Joseph,

Thanks for checking. Yes, the commit log in v2 was accidentally
truncated in a few places. Sorry about that.

I'll send a v3 with the commit message fixed. The code change itself is
unchanged.

Thanks,
Zhang Cen

Joseph Qi <[email protected]> 于2026年5月25日周一 11:26写道:
>
>
>
> 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]);
>