xfs: create a separate hashname function for extended attributes
authorDarrick J. Wong <djwong@kernel.org>
Mon, 22 Apr 2024 16:47:38 +0000 (09:47 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 23 Apr 2024 14:46:55 +0000 (07:46 -0700)
Create a separate function to compute name hashvalues for extended
attributes.  When we get to parent pointers we'll be altering the rules
so that metadump obfuscation doesn't turn heinous.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_attr.c
fs/xfs/libxfs/xfs_attr.h
fs/xfs/libxfs/xfs_attr_leaf.c
fs/xfs/scrub/attr.c
fs/xfs/xfs_attr_item.c
fs/xfs/xfs_attr_list.c

index 50eab63ff3be13865b45617a5b3945e777762769..8262c263be9d13626c3eb465df7d1cf4ff1647a7 100644 (file)
@@ -280,7 +280,7 @@ xfs_attr_get(
                args->owner = args->dp->i_ino;
        args->geo = args->dp->i_mount->m_attr_geo;
        args->whichfork = XFS_ATTR_FORK;
-       args->hashval = xfs_da_hashname(args->name, args->namelen);
+       xfs_attr_sethash(args);
 
        /* Entirely possible to look up a name which doesn't exist */
        args->op_flags = XFS_DA_OP_OKNOENT;
@@ -415,6 +415,30 @@ out:
        return error;
 }
 
+/* Compute the hash value for a user/root/secure extended attribute */
+xfs_dahash_t
+xfs_attr_hashname(
+       const uint8_t           *name,
+       int                     namelen)
+{
+       return xfs_da_hashname(name, namelen);
+}
+
+/* Compute the hash value for any extended attribute from any namespace. */
+xfs_dahash_t
+xfs_attr_hashval(
+       struct xfs_mount        *mp,
+       unsigned int            attr_flags,
+       const uint8_t           *name,
+       int                     namelen,
+       const void              *value,
+       int                     valuelen)
+{
+       ASSERT(xfs_attr_check_namespace(attr_flags));
+
+       return xfs_attr_hashname(name, namelen);
+}
+
 /*
  * Handle the state change on completion of a multi-state attr operation.
  *
@@ -925,7 +949,7 @@ xfs_attr_set(
                args->owner = args->dp->i_ino;
        args->geo = mp->m_attr_geo;
        args->whichfork = XFS_ATTR_FORK;
-       args->hashval = xfs_da_hashname(args->name, args->namelen);
+       xfs_attr_sethash(args);
 
        /*
         * We have no control over the attribute names that userspace passes us
index cd106b0a424fa145ef7a704637d5cb62dd480647..c63b1d610e53bc0319ea88b6d50749b105cbbbf7 100644 (file)
@@ -628,6 +628,20 @@ xfs_attr_init_replace_state(struct xfs_da_args *args)
        return xfs_attr_init_add_state(args);
 }
 
+xfs_dahash_t xfs_attr_hashname(const uint8_t *name, int namelen);
+
+xfs_dahash_t xfs_attr_hashval(struct xfs_mount *mp, unsigned int attr_flags,
+               const uint8_t *name, int namelen, const void *value,
+               int valuelen);
+
+/* Set the hash value for any extended attribute from any namespace. */
+static inline void xfs_attr_sethash(struct xfs_da_args *args)
+{
+       args->hashval = xfs_attr_hashval(args->dp->i_mount, args->attr_filter,
+                                        args->name, args->namelen,
+                                        args->value, args->valuelen);
+}
+
 extern struct kmem_cache *xfs_attr_intent_cache;
 int __init xfs_attr_intent_init_cache(void);
 void xfs_attr_intent_destroy_cache(void);
index c47fad39744ee3b729581217ad156b6dd7ad371b..e54a8372a30a4a40ac263f259a26c24d18834a04 100644 (file)
@@ -948,14 +948,13 @@ xfs_attr_shortform_to_leaf(
                nargs.namelen = sfe->namelen;
                nargs.value = &sfe->nameval[nargs.namelen];
                nargs.valuelen = sfe->valuelen;
-               nargs.hashval = xfs_da_hashname(sfe->nameval,
-                                               sfe->namelen);
                nargs.attr_filter = sfe->flags & XFS_ATTR_NSP_ONDISK_MASK;
                if (!xfs_attr_check_namespace(sfe->flags)) {
                        xfs_da_mark_sick(args);
                        error = -EFSCORRUPTED;
                        goto out;
                }
+               xfs_attr_sethash(&nargs);
                error = xfs_attr3_leaf_lookup_int(bp, &nargs); /* set a->index */
                ASSERT(error == -ENOATTR);
                error = xfs_attr3_leaf_add(bp, &nargs);
index 7789bd2f0950743905571cdb6d85b4bc065dac89..22d7ef4df1699d29387f713b92ac0889f0aa5a4e 100644 (file)
@@ -179,7 +179,6 @@ xchk_xattr_actor(
                .dp                     = ip,
                .name                   = name,
                .namelen                = namelen,
-               .hashval                = xfs_da_hashname(name, namelen),
                .trans                  = sc->tp,
                .valuelen               = valuelen,
                .owner                  = ip->i_ino,
@@ -230,6 +229,7 @@ xchk_xattr_actor(
 
        args.value = ab->value;
 
+       xfs_attr_sethash(&args);
        error = xfs_attr_get_ilocked(&args);
        /* ENODATA means the hash lookup failed and the attr is bad */
        if (error == -ENODATA)
@@ -525,7 +525,10 @@ xchk_xattr_rec(
                        xchk_da_set_corrupt(ds, level);
                        goto out;
                }
-               calc_hash = xfs_da_hashname(lentry->nameval, lentry->namelen);
+               calc_hash = xfs_attr_hashval(mp, ent->flags, lentry->nameval,
+                                            lentry->namelen,
+                                            lentry->nameval + lentry->namelen,
+                                            be16_to_cpu(lentry->valuelen));
        } else {
                rentry = (struct xfs_attr_leaf_name_remote *)
                                (((char *)bp->b_addr) + nameidx);
@@ -533,7 +536,9 @@ xchk_xattr_rec(
                        xchk_da_set_corrupt(ds, level);
                        goto out;
                }
-               calc_hash = xfs_da_hashname(rentry->name, rentry->namelen);
+               calc_hash = xfs_attr_hashval(mp, ent->flags, rentry->name,
+                                            rentry->namelen, NULL,
+                                            be32_to_cpu(rentry->valuelen));
        }
        if (calc_hash != hash)
                xchk_da_set_corrupt(ds, level);
index a7d6c9af47e888aa2fbfe36237ad105db8072e3a..4a57bcff49ebded95ad8f4c679274ddcd25c73b2 100644 (file)
@@ -582,13 +582,13 @@ xfs_attri_recover_work(
        args->whichfork = XFS_ATTR_FORK;
        args->name = nv->name.i_addr;
        args->namelen = nv->name.i_len;
-       args->hashval = xfs_da_hashname(args->name, args->namelen);
        args->value = nv->value.i_addr;
        args->valuelen = nv->value.i_len;
        args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK;
        args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT |
                         XFS_DA_OP_LOGGED;
        args->owner = args->dp->i_ino;
+       xfs_attr_sethash(args);
 
        switch (xfs_attr_intent_op(attr)) {
        case XFS_ATTRI_OP_FLAGS_SET:
index 903ed46c68872bcb1bed6b41c394c0c2086a9ebd..9bc4b5322539a96df758186176b14d5d99959b7c 100644 (file)
@@ -135,12 +135,15 @@ xfs_attr_shortform_list(
                }
 
                sbp->entno = i;
-               sbp->hash = xfs_da_hashname(sfe->nameval, sfe->namelen);
                sbp->name = sfe->nameval;
                sbp->namelen = sfe->namelen;
                /* These are bytes, and both on-disk, don't endian-flip */
                sbp->valuelen = sfe->valuelen;
                sbp->flags = sfe->flags;
+               sbp->hash = xfs_attr_hashval(dp->i_mount, sfe->flags,
+                                            sfe->nameval, sfe->namelen,
+                                            sfe->nameval + sfe->namelen,
+                                            sfe->valuelen);
                sfe = xfs_attr_sf_nextentry(sfe);
                sbp++;
                nsbuf++;