]> git.apps.os.sepia.ceph.com Git - xfstests-dev.git/commitdiff
vfs: Add tmpfs tests for idmap mounts
authorRodrigo Campos <rodrigo@sdfg.com.ar>
Tue, 14 Mar 2023 11:45:11 +0000 (12:45 +0100)
committerZorro Lang <zlang@kernel.org>
Tue, 14 Mar 2023 14:52:48 +0000 (22:52 +0800)
This patch calls all tests in the suite s_idmapped_mounts, but with a
tmpfs directory mounted inside a userns. This directory is setup as the
mount point for the test that runs nested.

This excercises that tmpfs mounted inside a userns works as expected
regarding idmap mounts.

Signed-off-by: Rodrigo Campos <rodrigo@sdfg.com.ar>
Reviewed-by: Zorro Lang <zlang@redhat.com>
Acked-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Zorro Lang <zlang@kernel.org>
src/vfs/Makefile
src/vfs/tmpfs-idmapped-mounts.c [new file with mode: 0644]
src/vfs/tmpfs-idmapped-mounts.h [new file with mode: 0644]
src/vfs/utils.h
src/vfs/vfstest.c
tests/tmpfs/001 [new file with mode: 0755]
tests/tmpfs/001.out [new file with mode: 0644]
tests/tmpfs/Makefile [new file with mode: 0644]

index 1b0b364b2dec135b40a47c3e7f932c55f6e1f05d..4841da1286bfec5a382d4cb5db6ec31967821b6a 100644 (file)
@@ -4,10 +4,10 @@ TOPDIR = ../..
 include $(TOPDIR)/include/builddefs
 
 TARGETS = vfstest mount-idmapped
-CFILES_VFSTEST = vfstest.c btrfs-idmapped-mounts.c idmapped-mounts.c utils.c
+CFILES_VFSTEST = vfstest.c btrfs-idmapped-mounts.c idmapped-mounts.c utils.c tmpfs-idmapped-mounts.c
 CFILES_MOUNT_IDMAPPED = mount-idmapped.c utils.c
 
-HFILES = missing.h utils.h btrfs-idmapped-mounts.h idmapped-mounts.h
+HFILES = missing.h utils.h btrfs-idmapped-mounts.h idmapped-mounts.h tmpfs-idmapped-mounts.h
 LLDLIBS += -pthread
 LDIRT = $(TARGETS)
 
diff --git a/src/vfs/tmpfs-idmapped-mounts.c b/src/vfs/tmpfs-idmapped-mounts.c
new file mode 100644 (file)
index 0000000..0899aed
--- /dev/null
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "../global.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <grp.h>
+#include <limits.h>
+#include <linux/limits.h>
+#include <linux/types.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <sys/fsuid.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include "missing.h"
+#include "utils.h"
+#include "vfstest.h"
+#include "idmapped-mounts.h"
+
+static int tmpfs_nested_mount_setup(const struct vfstest_info *info, int (*test)(const struct vfstest_info *info))
+{
+       char path[PATH_MAX];
+       int fret = -1;
+       struct vfstest_info nested_test_info = *info;
+
+       /* Create mapping for userns
+        * Make the mapping quite long, so all nested userns that are created by
+        * any test we call is contained here (otherwise userns creation fails).
+        */
+       struct mount_attr attr = {
+               .attr_set       = MOUNT_ATTR_IDMAP,
+               .userns_fd      = -EBADF,
+       };
+       attr.userns_fd = get_userns_fd(0, 10000, 200000);
+       if (attr.userns_fd < 0) {
+               log_stderr("failure: get_userns_fd");
+               goto out_close;
+       }
+
+       if (!switch_userns(attr.userns_fd, 0, 0, false)) {
+               log_stderr("failure: switch_userns");
+               goto out_close;
+       }
+
+       /* create separate mount namespace */
+       if (unshare(CLONE_NEWNS)) {
+               log_stderr("failure: create new mount namespace");
+               goto out_close;
+       }
+
+       /* We don't want this mount in the parent mount ns */
+       if (sys_mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0)) {
+               log_stderr("failure: mount");
+               goto out_close;
+       }
+
+       /* Create DIR0 to mount there */
+       if (mkdirat(info->t_mnt_fd, DIR0, 0777)) {
+               log_stderr("failure: mkdirat");
+               goto out_close;
+       }
+       if (fchmodat(info->t_mnt_fd, DIR0, 0777, 0)) {
+               log_stderr("failure: fchmodat");
+               goto out_rm;
+       }
+
+       snprintf(path, sizeof(path), "%s/%s", info->t_mountpoint, DIR0);
+       if (sys_mount("tmpfs", path, "tmpfs", 0, NULL)) {
+               log_stderr("failure: mount");
+               goto out_rm;
+       }
+
+       // Create a new info to use for the test we will call.
+       nested_test_info = *info;
+       nested_test_info.t_mountpoint = strdup(path);
+       if (!nested_test_info.t_mountpoint) {
+               log_stderr("failure: strdup");
+               goto out;
+       }
+       nested_test_info.t_mnt_fd = openat(-EBADF, nested_test_info.t_mountpoint, O_CLOEXEC | O_DIRECTORY);
+       if (nested_test_info.t_mnt_fd < 0) {
+               log_stderr("failure: openat");
+               goto out;
+       }
+
+       test_setup(&nested_test_info);
+
+       // Run the test.
+       if ((*test)(&nested_test_info)) {
+               log_stderr("failure: calling test");
+               goto out;
+       }
+
+       test_cleanup(&nested_test_info);
+
+       fret = 0;
+       log_debug("Ran test");
+out:
+       snprintf(path, sizeof(path), "%s/" DIR0, info->t_mountpoint);
+       sys_umount2(path, MNT_DETACH);
+out_rm:
+       if (rm_r(info->t_mnt_fd, DIR0))
+               log_stderr("failure: rm_r");
+out_close:
+       safe_close(attr.userns_fd);
+       return fret;
+}
+
+static int tmpfs_acls(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_acls);
+}
+static int tmpfs_create_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_create_in_userns);
+}
+static int tmpfs_device_node_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_device_node_in_userns);
+}
+static int tmpfs_fsids_mapped(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_fsids_mapped);
+}
+static int tmpfs_fsids_unmapped(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_fsids_unmapped);
+}
+static int tmpfs_expected_uid_gid_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_expected_uid_gid_idmapped_mounts);
+}
+static int tmpfs_fscaps_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_fscaps_idmapped_mounts);
+}
+static int tmpfs_fscaps_idmapped_mounts_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_fscaps_idmapped_mounts_in_userns);
+}
+static int tmpfs_fscaps_idmapped_mounts_in_userns_separate_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_fscaps_idmapped_mounts_in_userns_separate_userns);
+}
+
+static int tmpfs_hardlink_crossing_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_hardlink_crossing_idmapped_mounts);
+}
+static int tmpfs_hardlink_from_idmapped_mount(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_hardlink_from_idmapped_mount);
+}
+static int tmpfs_hardlink_from_idmapped_mount_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_hardlink_from_idmapped_mount_in_userns);
+}
+
+#ifdef HAVE_LIBURING_H
+static int tmpfs_io_uring_idmapped(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_io_uring_idmapped);
+}
+static int tmpfs_io_uring_idmapped_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_io_uring_idmapped_userns);
+}
+static int tmpfs_io_uring_idmapped_unmapped(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_io_uring_idmapped_unmapped);
+}
+static int tmpfs_io_uring_idmapped_unmapped_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_io_uring_idmapped_unmapped_userns);
+}
+#endif /* HAVE_LIBURING_H */
+
+static int tmpfs_protected_symlinks_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_protected_symlinks_idmapped_mounts);
+}
+static int tmpfs_protected_symlinks_idmapped_mounts_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_protected_symlinks_idmapped_mounts_in_userns);
+}
+static int tmpfs_rename_crossing_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_rename_crossing_idmapped_mounts);
+}
+static int tmpfs_rename_from_idmapped_mount(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_rename_from_idmapped_mount);
+}
+static int tmpfs_rename_from_idmapped_mount_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_rename_from_idmapped_mount_in_userns);
+}
+static int tmpfs_setattr_truncate_idmapped(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_setattr_truncate_idmapped);
+}
+static int tmpfs_setattr_truncate_idmapped_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_setattr_truncate_idmapped_in_userns);
+}
+static int tmpfs_setgid_create_idmapped(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_setgid_create_idmapped);
+}
+static int tmpfs_setgid_create_idmapped_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_setgid_create_idmapped_in_userns);
+}
+static int tmpfs_setid_binaries_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_setid_binaries_idmapped_mounts);
+}
+static int tmpfs_setid_binaries_idmapped_mounts_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_setid_binaries_idmapped_mounts_in_userns);
+}
+static int tmpfs_setid_binaries_idmapped_mounts_in_userns_separate_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_setid_binaries_idmapped_mounts_in_userns_separate_userns);
+}
+static int tmpfs_sticky_bit_unlink_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_sticky_bit_unlink_idmapped_mounts);
+}
+static int tmpfs_sticky_bit_unlink_idmapped_mounts_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_sticky_bit_unlink_idmapped_mounts_in_userns);
+}
+static int tmpfs_sticky_bit_rename_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_sticky_bit_rename_idmapped_mounts);
+}
+static int tmpfs_sticky_bit_rename_idmapped_mounts_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_sticky_bit_rename_idmapped_mounts_in_userns);
+}
+static int tmpfs_symlink_idmapped_mounts(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_symlink_idmapped_mounts);
+}
+static int tmpfs_symlink_idmapped_mounts_in_userns(const struct vfstest_info *info)
+{
+       return tmpfs_nested_mount_setup(info, tcore_symlink_idmapped_mounts_in_userns);
+}
+
+static const struct test_struct t_tmpfs[] = {
+       { tmpfs_acls,                                           T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs create operations in user namespace",                                                          },
+       { tmpfs_create_in_userns,                                               T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs create operations in user namespace",                                                          },
+       { tmpfs_device_node_in_userns,                                          T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs device node in user namespace",                                                                },
+       { tmpfs_expected_uid_gid_idmapped_mounts,                               T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs expected ownership on idmapped mounts",                                                  },
+       { tmpfs_fscaps_idmapped_mounts,                                         T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs fscaps on idmapped mounts",                                                                      },
+       { tmpfs_fscaps_idmapped_mounts_in_userns,                               T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs fscaps on idmapped mounts in user namespace",                                                    },
+       { tmpfs_fscaps_idmapped_mounts_in_userns_separate_userns,               T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs fscaps on idmapped mounts in user namespace with different id mappings",                 },
+       { tmpfs_fsids_mapped,                                                   T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs mapped fsids",                                                                                 },
+       { tmpfs_fsids_unmapped,                                                 T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs unmapped fsids",                                                                               },
+       { tmpfs_hardlink_crossing_idmapped_mounts,                              T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs cross idmapped mount hardlink",                                                          },
+       { tmpfs_hardlink_from_idmapped_mount,                                   T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs hardlinks from idmapped mounts",                                                         },
+       { tmpfs_hardlink_from_idmapped_mount_in_userns,                         T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs hardlinks from idmapped mounts in user namespace",                                               },
+#ifdef HAVE_LIBURING_H
+       { tmpfs_io_uring_idmapped,                                              T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs io_uring from idmapped mounts",                                                                },
+       { tmpfs_io_uring_idmapped_userns,                                       T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs io_uring from idmapped mounts in user namespace",                                              },
+       { tmpfs_io_uring_idmapped_unmapped,                                     T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs io_uring from idmapped mounts with unmapped ids",                                              },
+       { tmpfs_io_uring_idmapped_unmapped_userns,                              T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs io_uring from idmapped mounts with unmapped ids in user namespace",                            },
+#endif
+       { tmpfs_protected_symlinks_idmapped_mounts,                             T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs following protected symlinks on idmapped mounts",                                                },
+       { tmpfs_protected_symlinks_idmapped_mounts_in_userns,                   T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs following protected symlinks on idmapped mounts in user namespace",                              },
+       { tmpfs_rename_crossing_idmapped_mounts,                                T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs cross idmapped mount rename",                                                                    },
+       { tmpfs_rename_from_idmapped_mount,                                     T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs rename from idmapped mounts",                                                                    },
+       { tmpfs_rename_from_idmapped_mount_in_userns,                           T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs rename from idmapped mounts in user namespace",                                          },
+       { tmpfs_setattr_truncate_idmapped,                                      T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs setattr truncate on idmapped mounts",                                                            },
+       { tmpfs_setattr_truncate_idmapped_in_userns,                            T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs setattr truncate on idmapped mounts in user namespace",                                  },
+       { tmpfs_setgid_create_idmapped,                                         T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs create operations in directories with setgid bit set on idmapped mounts",                        },
+       { tmpfs_setgid_create_idmapped_in_userns,                               T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs create operations in directories with setgid bit set on idmapped mounts in user namespace",      },
+       { tmpfs_setid_binaries_idmapped_mounts,                                 T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs setid binaries on idmapped mounts",                                                              },
+       { tmpfs_setid_binaries_idmapped_mounts_in_userns,                       T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs setid binaries on idmapped mounts in user namespace",                                            },
+       { tmpfs_setid_binaries_idmapped_mounts_in_userns_separate_userns,       T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs setid binaries on idmapped mounts in user namespace with different id mappings",         },
+       { tmpfs_sticky_bit_unlink_idmapped_mounts,                              T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs sticky bit unlink operations on idmapped mounts",                                                },
+       { tmpfs_sticky_bit_unlink_idmapped_mounts_in_userns,                    T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs sticky bit unlink operations on idmapped mounts in user namespace",                              },
+       { tmpfs_sticky_bit_rename_idmapped_mounts,                              T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs sticky bit rename operations on idmapped mounts",                                                },
+       { tmpfs_sticky_bit_rename_idmapped_mounts_in_userns,                    T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs sticky bit rename operations on idmapped mounts in user namespace",                              },
+       { tmpfs_symlink_idmapped_mounts,                                        T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs symlink from idmapped mounts",                                                                   },
+       { tmpfs_symlink_idmapped_mounts_in_userns,                              T_REQUIRE_USERNS | T_REQUIRE_IDMAPPED_MOUNTS,   "tmpfs symlink from idmapped mounts in user namespace",                                         },
+};
+
+
+const struct test_suite s_tmpfs_idmapped_mounts = {
+       .tests = t_tmpfs,
+       .nr_tests = ARRAY_SIZE(t_tmpfs),
+};
diff --git a/src/vfs/tmpfs-idmapped-mounts.h b/src/vfs/tmpfs-idmapped-mounts.h
new file mode 100644 (file)
index 0000000..ed24651
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __TMPFS_IDMAPPED_MOUNTS_H
+#define __TMPFS_IDMAPPED_MOUNTS_H
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "utils.h"
+
+extern const struct test_suite s_tmpfs_idmapped_mounts;
+
+#endif /* __TMPFS_IDMAPPED_MOUNTS_H */
index f16817378aa62dc276b07b68f380dba69ec62bda..872fd96f88c9d9129dce7beae1dfb37c666232ff 100644 (file)
@@ -45,6 +45,8 @@
 #define DIR2 "dir2"
 #define DIR3 "dir3"
 #define DIR1_RENAME "dir1_rename"
+// This directory may be used by tests that call another test.
+#define DIR0 "dir0"
 #define HARDLINK1 "hardlink1"
 #define SYMLINK1 "symlink1"
 #define SYMLINK_USER1 "symlink_user1"
index 325f04a1355dff072051f99328e0fe60c9483f84..f842117df11d88d897d1bd92051d755f4cf69990 100644 (file)
@@ -23,6 +23,7 @@
 #include <unistd.h>
 
 #include "btrfs-idmapped-mounts.h"
+#include "tmpfs-idmapped-mounts.h"
 #include "idmapped-mounts.h"
 #include "missing.h"
 #include "utils.h"
@@ -2316,6 +2317,7 @@ static void usage(void)
        fprintf(stderr, "--test-fscaps-regression            Run fscap regression tests\n");
        fprintf(stderr, "--test-nested-userns                Run nested userns idmapped mount testsuite\n");
        fprintf(stderr, "--test-btrfs                        Run btrfs specific idmapped mount testsuite\n");
+       fprintf(stderr, "--test-tmpfs                        Run tmpfs specific idmapped mount testsuite\n");
        fprintf(stderr, "--test-setattr-fix-968219708108     Run setattr regression tests\n");
        fprintf(stderr, "--test-setxattr-fix-705191b03d50    Run setxattr regression tests\n");
        fprintf(stderr, "--test-setgid-create-umask          Run setgid with umask tests\n");
@@ -2340,6 +2342,7 @@ static const struct option longopts[] = {
        {"test-setxattr-fix-705191b03d50",      no_argument,            0,      'j'},
        {"test-setgid-create-umask",            no_argument,            0,      'u'},
        {"test-setgid-create-acl",              no_argument,            0,      'l'},
+       {"test-tmpfs",                          no_argument,            0,      't'},
        {NULL,                                  0,                      0,        0},
 };
 
@@ -2480,7 +2483,7 @@ int main(int argc, char *argv[])
        bool idmapped_mounts_supported = false, test_btrfs = false,
             test_core = false, test_fscaps_regression = false,
             test_nested_userns = false, test_setattr_fix_968219708108 = false,
-            test_setxattr_fix_705191b03d50 = false,
+            test_setxattr_fix_705191b03d50 = false, test_tmpfs = false,
             test_setgid_create_umask = false, test_setgid_create_acl = false;
 
        init_vfstest_info(&info);
@@ -2529,6 +2532,9 @@ int main(int argc, char *argv[])
                case 'l':
                        test_setgid_create_acl = true;
                        break;
+               case 't':
+                       test_tmpfs = true;
+                       break;
                case 'h':
                        /* fallthrough */
                default:
@@ -2622,6 +2628,11 @@ int main(int argc, char *argv[])
                        goto out;
        }
 
+       if (test_tmpfs) {
+               if (!run_suite(&info, &s_tmpfs_idmapped_mounts))
+                       goto out;
+       }
+
        fret = EXIT_SUCCESS;
 
 out:
diff --git a/tests/tmpfs/001 b/tests/tmpfs/001
new file mode 100755 (executable)
index 0000000..37ef0b1
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2023 Rodrigo Campos Catelin (Microsoft). All Rights Reserved.
+#
+# FS QA Test 001
+#
+# Test that idmapped mounts behave correctly with tmpfs filesystem.
+#
+. ./common/preamble
+_begin_fstest auto quick idmapped
+
+# get standard environment, filters and checks
+. ./common/filter
+
+# real QA test starts here
+
+_supported_fs tmpfs
+_require_idmapped_mounts
+_require_test
+
+echo "Silence is golden"
+
+$here/src/vfs/vfstest --test-tmpfs --device "$TEST_DEV" \
+               --mount "$TEST_DIR" --fstype "$FSTYP"
+
+status=$?
+exit
diff --git a/tests/tmpfs/001.out b/tests/tmpfs/001.out
new file mode 100644 (file)
index 0000000..88678b8
--- /dev/null
@@ -0,0 +1,2 @@
+QA output created by 001
+Silence is golden
diff --git a/tests/tmpfs/Makefile b/tests/tmpfs/Makefile
new file mode 100644 (file)
index 0000000..4654431
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2023 Rodrigo Campos Catelin (Microsoft). All Rights Reserved.
+#
+
+TOPDIR = ../..
+include $(TOPDIR)/include/builddefs
+include $(TOPDIR)/include/buildgrouplist
+
+TMPFS_DIR = tmpfs
+TARGET_DIR = $(PKG_LIB_DIR)/$(TESTS_DIR)/$(TMPFS_DIR)
+DIRT = group.list
+
+default: $(DIRT)
+
+include $(BUILDRULES)
+
+install:
+       $(INSTALL) -m 755 -d $(TARGET_DIR)
+       $(INSTALL) -m 755 $(TESTS) $(TARGET_DIR)
+       $(INSTALL) -m 644 group.list $(TARGET_DIR)
+       $(INSTALL) -m 644 $(OUTFILES) $(TARGET_DIR)
+
+# Nothing.
+install-dev install-lib: