xfs: salvage parent pointers when rebuilding xattr structures
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Apr 2024 16:48:08 +0000 (09:48 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 23 Apr 2024 14:47:03 +0000 (07:47 -0700)
When we're salvaging extended attributes, make sure we validate the ones
that claim to be parent pointers before adding them to the salvage pile.

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

index cbcc446d5119b2fa3e70e1b106450dbd35186681..48443e88e298bbddeb101bca532b88100c0303b5 100644 (file)
@@ -28,6 +28,7 @@
 #include "xfs_exchmaps.h"
 #include "xfs_exchrange.h"
 #include "xfs_acl.h"
+#include "xfs_parent.h"
 #include "scrub/xfs_scrub.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
@@ -127,6 +128,9 @@ xrep_xattr_want_salvage(
                return false;
        if (valuelen > XATTR_SIZE_MAX || valuelen < 0)
                return false;
+       if (attr_flags & XFS_ATTR_PARENT)
+               return xfs_parent_valuecheck(rx->sc->mp, value, valuelen);
+
        return true;
 }
 
@@ -154,14 +158,21 @@ xrep_xattr_salvage_key(
         * Truncate the name to the first character that would trip namecheck.
         * If we no longer have a name after that, ignore this attribute.
         */
-       while (i < namelen && name[i] != 0)
-               i++;
-       if (i == 0)
-               return 0;
-       key.namelen = i;
+       if (flags & XFS_ATTR_PARENT) {
+               key.namelen = namelen;
+
+               trace_xrep_xattr_salvage_pptr(rx->sc->ip, flags, name,
+                               key.namelen, value, valuelen);
+       } else {
+               while (i < namelen && name[i] != 0)
+                       i++;
+               if (i == 0)
+                       return 0;
+               key.namelen = i;
 
-       trace_xrep_xattr_salvage_rec(rx->sc->ip, flags, name, key.namelen,
-                       valuelen);
+               trace_xrep_xattr_salvage_rec(rx->sc->ip, flags, name,
+                               key.namelen, valuelen);
+       }
 
        error = xfblob_store(rx->xattr_blobs, &key.name_cookie, name,
                        key.namelen);
@@ -598,8 +609,15 @@ xrep_xattr_insert_rec(
 
        ab->name[key->namelen] = 0;
 
-       trace_xrep_xattr_insert_rec(rx->sc->tempip, key->flags, ab->name,
-                       key->namelen, key->valuelen);
+       if (key->flags & XFS_ATTR_PARENT) {
+               trace_xrep_xattr_insert_pptr(rx->sc->tempip, key->flags,
+                               ab->name, key->namelen, ab->value,
+                               key->valuelen);
+               args.op_flags |= XFS_DA_OP_LOGGED;
+       } else {
+               trace_xrep_xattr_insert_rec(rx->sc->tempip, key->flags,
+                               ab->name, key->namelen, key->valuelen);
+       }
 
        /*
         * xfs_attr_set creates and commits its own transaction.  If the attr
index 3e726610b9e322cdbf2b422b05726b0d0a89c381..4b968df3d840cf4b6e3d6fa3419d2c9ce96f819c 100644 (file)
@@ -2540,6 +2540,44 @@ DEFINE_EVENT(xrep_xattr_salvage_class, name, \
 DEFINE_XREP_XATTR_SALVAGE_EVENT(xrep_xattr_salvage_rec);
 DEFINE_XREP_XATTR_SALVAGE_EVENT(xrep_xattr_insert_rec);
 
+DECLARE_EVENT_CLASS(xrep_pptr_salvage_class,
+       TP_PROTO(struct xfs_inode *ip, unsigned int flags, const void *name,
+                unsigned int namelen, const void *value, unsigned int valuelen),
+       TP_ARGS(ip, flags, name, namelen, value, valuelen),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(xfs_ino_t, ino)
+               __field(xfs_ino_t, parent_ino)
+               __field(unsigned int, parent_gen)
+               __field(unsigned int, namelen)
+               __dynamic_array(char, name, namelen)
+       ),
+       TP_fast_assign(
+               const struct xfs_parent_rec     *rec = value;
+
+               __entry->dev = ip->i_mount->m_super->s_dev;
+               __entry->ino = ip->i_ino;
+               __entry->parent_ino = be64_to_cpu(rec->p_ino);
+               __entry->parent_gen = be32_to_cpu(rec->p_gen);
+               __entry->namelen = namelen;
+               memcpy(__get_str(name), name, namelen);
+       ),
+       TP_printk("dev %d:%d ino 0x%llx parent_ino 0x%llx parent_gen 0x%x name '%.*s'",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->ino,
+                 __entry->parent_ino,
+                 __entry->parent_gen,
+                 __entry->namelen,
+                 __get_str(name))
+)
+#define DEFINE_XREP_PPTR_SALVAGE_EVENT(name) \
+DEFINE_EVENT(xrep_pptr_salvage_class, name, \
+       TP_PROTO(struct xfs_inode *ip, unsigned int flags, const void *name, \
+                unsigned int namelen, const void *value, unsigned int valuelen), \
+       TP_ARGS(ip, flags, name, namelen, value, valuelen))
+DEFINE_XREP_PPTR_SALVAGE_EVENT(xrep_xattr_salvage_pptr);
+DEFINE_XREP_PPTR_SALVAGE_EVENT(xrep_xattr_insert_pptr);
+
 TRACE_EVENT(xrep_xattr_class,
        TP_PROTO(struct xfs_inode *ip, struct xfs_inode *arg_ip),
        TP_ARGS(ip, arg_ip),