Syzkaller reported an out-of-bounds access in ocfs2_xa_remove_entry(), triggered when removing an xattr entry.
The root cause is that the original code decrements xh_count in-place using le16_add_cpu() before reading the updated count value into a local variable. However, due to the way the entry removal logic interacts with the array bounds checking (enforced by __counted_by(xh_count)), the stale count during subsequent operations leads to the out-of-bounds access during the removal process. This patch fixes the issue by reading the current count first, computing the decremented value locally, and then explicitly writing the updated count back to xh_count at the end of the function. This ensures the array bounds are correctly reflected throughout the entry removal without relying on in-place modification timing. The fix has been tested by reproducing the syzkaller crash report, which no longer triggers after applying the patch. Reported-by: [email protected] Closes: https://syzkaller.appspot.com./bug?extid=cf96bc82a588a27346a8 Signed-off-by: Swaraj Gaikwad <[email protected]> --- fs/ocfs2/xattr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index dc1761e84814..de99276d12f0 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -1941,8 +1941,7 @@ static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) ocfs2_xa_wipe_namevalue(loc); loc->xl_entry = NULL; - le16_add_cpu(&xh->xh_count, -1); - count = le16_to_cpu(xh->xh_count); + count = le16_to_cpu(xh->xh_count) - 1; /* * Only zero out the entry if there are more remaining. This is @@ -1957,6 +1956,8 @@ static void ocfs2_xa_remove_entry(struct ocfs2_xa_loc *loc) memset(&xh->xh_entries[count], 0, sizeof(struct ocfs2_xattr_entry)); } + + xh->xh_count = cpu_to_le16(count); } /* base-commit: c2f2b01b74be8b40a2173372bcd770723f87e7b2 -- 2.52.0
