]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
erofs: fix metabuf leak in inode xattr initialization
authorJia Zhu <zhujia.zj@bytedance.com>
Wed, 20 May 2026 04:46:07 +0000 (12:46 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Wed, 20 May 2026 06:53:14 +0000 (14:53 +0800)
commit bb88e8da0025 ("erofs: use meta buffers for xattr operations")
converted xattr operations to use on-stack erofs_buf instances.
erofs_init_inode_xattrs() uses such a metabuf while reading the inline
xattr header and shared xattr id array.

Some error paths after erofs_read_metabuf() leave through out_unlock
without dropping the metabuf, so the folio reference can leak.

Consolidate the cleanup at out_unlock. erofs_put_metabuf() is a
no-op if no folio has been acquired, and this keeps all paths after
taking EROFS_I_BL_XATTR_BIT covered by a single cleanup site.

Fixes: bb88e8da0025 ("erofs: use meta buffers for xattr operations")
Signed-off-by: Jia Zhu <zhujia.zj@bytedance.com>
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Fixes: bb88e8da0025 ("erofs: use meta buffers for xattr operations")
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
fs/erofs/xattr.c

index 41e311019a2514c4da971fa7dd826e9191560b6e..df7ea019526d722c941b6d48fe23e5d1c56cdf52 100644 (file)
@@ -89,13 +89,11 @@ static int erofs_init_inode_xattrs(struct inode *inode)
            vi->xattr_isize - sizeof(struct erofs_xattr_ibody_header)) {
                erofs_err(sb, "invalid h_shared_count %u @ nid %llu",
                          vi->xattr_shared_count, vi->nid);
-               erofs_put_metabuf(&buf);
                ret = -EFSCORRUPTED;
                goto out_unlock;
        }
        vi->xattr_shared_xattrs = kmalloc_objs(uint, vi->xattr_shared_count);
        if (!vi->xattr_shared_xattrs) {
-               erofs_put_metabuf(&buf);
                ret = -ENOMEM;
                goto out_unlock;
        }
@@ -112,12 +110,12 @@ static int erofs_init_inode_xattrs(struct inode *inode)
                }
                vi->xattr_shared_xattrs[i] = le32_to_cpu(*xattr_id);
        }
-       erofs_put_metabuf(&buf);
 
        /* paired with smp_mb() at the beginning of the function. */
        smp_mb();
        set_bit(EROFS_I_EA_INITED_BIT, &vi->flags);
 out_unlock:
+       erofs_put_metabuf(&buf);
        clear_and_wake_up_bit(EROFS_I_BL_XATTR_BIT, &vi->flags);
        return ret;
 }