]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
fuse2fs: make removexattr work correctly
authorDarrick J. Wong <djwong@kernel.org>
Wed, 21 May 2025 22:38:02 +0000 (15:38 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 23 May 2025 13:39:37 +0000 (09:39 -0400)
removexattr is supposed to return ENODATA if the xattr name does not
exist, so we need to check for it explicitly.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Link: https://lore.kernel.org/r/174786677765.1383760.11407998503450588763.stgit@frogsfrogsfrogs
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
misc/fuse2fs.c

index 0fc6aed2246b75f601d1fa780c33c2ad490b631a..9f3093c8595cbe83748c32ea80a9ee875701a880 100644 (file)
 #define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
 #endif
 
+#ifndef XATTR_NAME_POSIX_ACL_DEFAULT
+#define XATTR_NAME_POSIX_ACL_DEFAULT "posix_acl_default"
+#endif
+#ifndef XATTR_SECURITY_PREFIX
+#define XATTR_SECURITY_PREFIX "security."
+#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
+#endif
+
 static ext2_filsys global_fs; /* Try not to use this directly */
 
 #define dbg_printf(fuse2fs, format, ...) \
@@ -2624,6 +2632,8 @@ static int op_removexattr(const char *path, const char *key)
        struct fuse2fs *ff = (struct fuse2fs *)ctxt->private_data;
        ext2_filsys fs;
        struct ext2_xattr_handle *h;
+       void *buf;
+       size_t buflen;
        ext2_ino_t ino;
        errcode_t err;
        int ret = 0;
@@ -2664,6 +2674,27 @@ static int op_removexattr(const char *path, const char *key)
                goto out2;
        }
 
+       err = ext2fs_xattr_get(h, key, &buf, &buflen);
+       switch (err) {
+       case EXT2_ET_EA_KEY_NOT_FOUND:
+               /*
+                * ACLs are special snowflakes that require a 0 return when
+                * the ACL never existed in the first place.
+                */
+               if (!strncmp(XATTR_SECURITY_PREFIX, key,
+                            XATTR_SECURITY_PREFIX_LEN))
+                       ret = 0;
+               else
+                       ret = -ENODATA;
+               goto out2;
+       case 0:
+               ext2fs_free_mem(&buf);
+               break;
+       default:
+               ret = translate_error(fs, ino, err);
+               goto out2;
+       }
+
        err = ext2fs_xattr_remove(h, key);
        if (err) {
                ret = translate_error(fs, ino, err);