mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 06:29:06 -04:00
ocfs2: fix missing metadata reservation for large xattrs
[BUG]
lsetxattr() panics the kernel when setting a large xattr value on a
fragmented filesystem where the file already has an external xattr
block.
[CAUSE]
ocfs2_calc_xattr_set_need() never reserves metadata blocks for a new
xattr value's extent tree when the file already has an external xattr
block. The not_found path leaves meta_add at zero, so meta_ac is NULL
when ocfs2_xattr_extend_allocation() runs.
A new value root has room for a single extent record. On a fragmented
filesystem, the allocator cannot satisfy the xattr value in one
contiguous run, so each non-contiguous run requires its own extent
record. When the value root's extent list is full and meta_ac is NULL,
ocfs2_add_clusters_in_btree() returns RESTART_META, and
ocfs2_xattr_extend_allocation() hits BUG_ON(why == RESTART_META).
[FIX]
The case where no xattr block exists yet already calls
ocfs2_extend_meta_needed(&def_xv.xv.xr_list) to reserve value tree
metadata. Add the same reservation to the case where an xattr block
already exists, making the two cases consistent.
Replace the BUG_ON with a -ENOSPC return so that if RESTART_META is
returned despite the reservation, the error propagates to userspace
instead of panicking the kernel.
Link: https://lore.kernel.org/amLwn3i9tET8yhG7@dev
Fixes: a78f9f4668 ("ocfs2: make xattr extension work with new local alloc reservation.")
Signed-off-by: Ian Bridges <icb@fastmail.org>
Reported-by: syzbot+e538032956b1157914a3@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e538032956b1157914a3
Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Cc: Mark Fasheh <mark@fasheh.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Changwei Ge <gechangwei@live.cn>
Cc: Jun Piao <piaojun@huawei.com>
Cc: Heming Zhao <heming.zhao@suse.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
2c5a2a6afe
commit
0cdc7dde00
@@ -764,12 +764,10 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode,
|
||||
prev_clusters;
|
||||
|
||||
if (why != RESTART_NONE && clusters_to_add) {
|
||||
/*
|
||||
* We can only fail in case the alloc file doesn't give
|
||||
* up enough clusters.
|
||||
*/
|
||||
BUG_ON(why == RESTART_META);
|
||||
|
||||
if (why == RESTART_META) {
|
||||
status = -ENOSPC;
|
||||
break;
|
||||
}
|
||||
credits = ocfs2_calc_extend_credits(inode->i_sb,
|
||||
&vb->vb_xv->xr_list);
|
||||
status = ocfs2_extend_trans(handle, credits);
|
||||
@@ -3443,6 +3441,14 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode,
|
||||
} else
|
||||
credits += OCFS2_SUBALLOC_ALLOC + 1;
|
||||
|
||||
/*
|
||||
* Reserve metadata for the new xattr's value extent tree.
|
||||
* The not_found path above adds credits for this tree but
|
||||
* omits meta_add, leaving meta_ac NULL for large values.
|
||||
*/
|
||||
if (xi->xi_value_len > OCFS2_XATTR_INLINE_SIZE)
|
||||
meta_add += ocfs2_extend_meta_needed(&def_xv.xv.xr_list);
|
||||
|
||||
/*
|
||||
* This cluster will be used either for new bucket or for
|
||||
* new xattr block.
|
||||
|
||||
Reference in New Issue
Block a user