]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: fix ri_total validation in xlog_recover_attri_commit_pass2
authorLong Li <leo.lilong@huawei.com>
Fri, 20 Mar 2026 02:11:29 +0000 (10:11 +0800)
committerCarlos Maiolino <cem@kernel.org>
Mon, 23 Mar 2026 10:00:08 +0000 (11:00 +0100)
The ri_total checks for SET/REPLACE operations are hardcoded to 3,
but xfs_attri_item_size() only emits a value iovec when value_len > 0,
so ri_total is 2 when value_len == 0.

For PPTR_SET/PPTR_REMOVE/PPTR_REPLACE, value_len is validated by
xfs_attri_validate() to be exactly sizeof(struct xfs_parent_rec) and
is never zero, so their hardcoded checks remain correct.

This problem may cause log recovery failures. The following script can be
used to reproduce the problem:

 #!/bin/bash
 mkfs.xfs -f /dev/sda
 mount /dev/sda /mnt/test/
 touch /mnt/test/file
 for i in {1..200}; do
         attr -s "user.attr_$i" -V "value_$i" /mnt/test/file > /dev/null
 done
 echo 1 > /sys/fs/xfs/debug/larp
 echo 1 > /sys/fs/xfs/sda/errortag/larp
 attr -s "user.zero" -V "" /mnt/test/file
 echo 0 > /sys/fs/xfs/sda/errortag/larp
 umount /mnt/test
 mount /dev/sda /mnt/test/  # mount failed

Fix this by deriving the expected count dynamically as "2 + !!value_len"
for SET/REPLACE operations.

Cc: stable@vger.kernel.org # v6.9
Fixes: ad206ae50eca ("xfs: check opcode and iovec count match in xlog_recover_attri_commit_pass2")
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Long Li <leo.lilong@huawei.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
fs/xfs/xfs_attr_item.c

index 354472bf45f1455f3c97671bae0f43304eb732fe..83d09635b2008e6514290d8b8243ffa32707ec40 100644 (file)
@@ -1047,8 +1047,8 @@ xlog_recover_attri_commit_pass2(
                break;
        case XFS_ATTRI_OP_FLAGS_SET:
        case XFS_ATTRI_OP_FLAGS_REPLACE:
-               /* Log item, attr name, attr value */
-               if (item->ri_total != 3) {
+               /* Log item, attr name, optional attr value */
+               if (item->ri_total != 2 + !!attri_formatp->alfi_value_len) {
                        XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
                                             attri_formatp, len);
                        return -EFSCORRUPTED;