xfs: check opcode and iovec count match in xlog_recover_attri_commit_pass2
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Apr 2024 16:47:26 +0000 (09:47 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 23 Apr 2024 14:46:52 +0000 (07:46 -0700)
Check that the number of recovered log iovecs is what is expected for
the xattri opcode is expecting.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_attr_item.c

index e5e7ddbc594b963281a3cf9a43cf38da7e01976e..d3559e6b24b7db687ee6793269a358c2add0c1ff 100644 (file)
@@ -737,6 +737,7 @@ xlog_recover_attri_commit_pass2(
        const void                      *attr_value = NULL;
        const void                      *attr_name;
        size_t                          len;
+       unsigned int                    op;
 
        attri_formatp = item->ri_buf[0].i_addr;
        attr_name = item->ri_buf[1].i_addr;
@@ -755,6 +756,32 @@ xlog_recover_attri_commit_pass2(
                return -EFSCORRUPTED;
        }
 
+       /* Check the number of log iovecs makes sense for the op code. */
+       op = attri_formatp->alfi_op_flags & XFS_ATTRI_OP_FLAGS_TYPE_MASK;
+       switch (op) {
+       case XFS_ATTRI_OP_FLAGS_SET:
+       case XFS_ATTRI_OP_FLAGS_REPLACE:
+               /* Log item, attr name, attr value */
+               if (item->ri_total != 3) {
+                       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                                            attri_formatp, len);
+                       return -EFSCORRUPTED;
+               }
+               break;
+       case XFS_ATTRI_OP_FLAGS_REMOVE:
+               /* Log item, attr name */
+               if (item->ri_total != 2) {
+                       XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                                            attri_formatp, len);
+                       return -EFSCORRUPTED;
+               }
+               break;
+       default:
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+                                    attri_formatp, len);
+               return -EFSCORRUPTED;
+       }
+
        /* Validate the attr name */
        if (item->ri_buf[1].i_len !=
                        xlog_calc_iovec_len(attri_formatp->alfi_name_len)) {