Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

selftests/fchmodat2: clean up temporary files and directories

Patch series "selftests/fchmodat2: Error handling and general", v4.

I looked at the fchmodat2() tests since I've been experiencing some random
intermittent segfaults with them in my test systems, while doing so I
noticed these two issues. Unfortunately I didn't figure out the original
yet, unless I managed to fix it unwittingly.


This patch (of 2):

The fchmodat2() test program creates a temporary directory with a file and
a symlink for every test it runs but never cleans these up, resulting in
${TMPDIR} getting left with stale files after every run. Restructure the
program a bit to ensure that we clean these up, this is more invasive than
it might otherwise be due to the extensive use of ksft_exit_fail_msg() in
the program.

As a side effect this also ensures that we report a consistent test name
for the tests and always try both tests even if they are skipped.

Link: https://lkml.kernel.org/r/20260226-selftests-fchmodat2-v4-0-a6419435f2e8@kernel.org
Link: https://lkml.kernel.org/r/20260226-selftests-fchmodat2-v4-1-a6419435f2e8@kernel.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Acked-by: Alexey Gladkov <legion@kernel.org>
Cc: Christian Brauner <brauner@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Mark Brown and committed by
Andrew Morton
04e23830 ac2428c1

+107 -46
+107 -46
tools/testing/selftests/fchmodat2/fchmodat2_test.c
··· 9 9 10 10 #include "kselftest.h" 11 11 12 + struct testdir { 13 + char *dirname; 14 + int dfd; 15 + }; 16 + 12 17 int sys_fchmodat2(int dfd, const char *filename, mode_t mode, int flags) 13 18 { 14 19 int ret = syscall(__NR_fchmodat2, dfd, filename, mode, flags); ··· 21 16 return ret >= 0 ? ret : -errno; 22 17 } 23 18 24 - int setup_testdir(void) 19 + static void setup_testdir(struct testdir *testdir) 25 20 { 26 - int dfd, ret; 21 + int ret, dfd; 27 22 char dirname[] = "/tmp/ksft-fchmodat2.XXXXXX"; 28 23 29 24 /* Make the top-level directory. */ ··· 31 26 ksft_exit_fail_msg("%s: failed to create tmpdir\n", __func__); 32 27 33 28 dfd = open(dirname, O_PATH | O_DIRECTORY); 34 - if (dfd < 0) 35 - ksft_exit_fail_msg("%s: failed to open tmpdir\n", __func__); 29 + if (dfd < 0) { 30 + ksft_perror("failed to open tmpdir"); 31 + goto err; 32 + } 36 33 37 34 ret = openat(dfd, "regfile", O_CREAT | O_WRONLY | O_TRUNC, 0644); 38 - if (ret < 0) 39 - ksft_exit_fail_msg("%s: failed to create file in tmpdir\n", 40 - __func__); 35 + if (ret < 0) { 36 + ksft_perror("failed to create file in tmpdir"); 37 + goto err; 38 + } 41 39 close(ret); 42 40 43 41 ret = symlinkat("regfile", dfd, "symlink"); 44 - if (ret < 0) 45 - ksft_exit_fail_msg("%s: failed to create symlink in tmpdir\n", 46 - __func__); 42 + if (ret < 0) { 43 + ksft_perror("symlinkat() failed"); 44 + goto err_regfile; 45 + } 47 46 48 - return dfd; 47 + testdir->dirname = strdup(dirname); 48 + if (!testdir->dirname) { 49 + ksft_perror("Out of memory"); 50 + goto err_symlink; 51 + } 52 + testdir->dfd = dfd; 53 + 54 + return; 55 + 56 + err_symlink: 57 + unlinkat(testdir->dfd, "symlink", 0); 58 + err_regfile: 59 + unlinkat(testdir->dfd, "regfile", 0); 60 + err: 61 + unlink(dirname); 62 + ksft_exit_fail(); 63 + } 64 + 65 + static void cleanup_testdir(struct testdir *testdir) 66 + { 67 + unlinkat(testdir->dfd, "regfile", 0); 68 + unlinkat(testdir->dfd, "symlink", 0); 69 + rmdir(testdir->dirname); 70 + free(testdir->dirname); 49 71 } 50 72 51 73 int expect_mode(int dfd, const char *filename, mode_t expect_mode) ··· 80 48 struct stat st; 81 49 int ret = fstatat(dfd, filename, &st, AT_SYMLINK_NOFOLLOW); 82 50 83 - if (ret) 84 - ksft_exit_fail_msg("%s: %s: fstatat failed\n", 85 - __func__, filename); 51 + if (ret) { 52 + ksft_perror("fstatat() failed\n"); 53 + return 0; 54 + } 86 55 87 56 return (st.st_mode == expect_mode); 88 57 } 89 58 90 59 void test_regfile(void) 91 60 { 92 - int dfd, ret; 61 + struct testdir testdir; 62 + int ret; 93 63 94 - dfd = setup_testdir(); 64 + setup_testdir(&testdir); 95 65 96 - ret = sys_fchmodat2(dfd, "regfile", 0640, 0); 66 + ret = sys_fchmodat2(testdir.dfd, "regfile", 0640, 0); 97 67 98 - if (ret < 0) 99 - ksft_exit_fail_msg("%s: fchmodat2(noflag) failed\n", __func__); 68 + if (ret < 0) { 69 + ksft_perror("fchmodat2(noflag) failed"); 70 + goto out; 71 + } 100 72 101 - if (!expect_mode(dfd, "regfile", 0100640)) 102 - ksft_exit_fail_msg("%s: wrong file mode bits after fchmodat2\n", 73 + if (!expect_mode(testdir.dfd, "regfile", 0100640)) { 74 + ksft_print_msg("%s: wrong file mode bits after fchmodat2\n", 103 75 __func__); 76 + ret = 1; 77 + goto out; 78 + } 104 79 105 - ret = sys_fchmodat2(dfd, "regfile", 0600, AT_SYMLINK_NOFOLLOW); 80 + ret = sys_fchmodat2(testdir.dfd, "regfile", 0600, AT_SYMLINK_NOFOLLOW); 106 81 107 - if (ret < 0) 108 - ksft_exit_fail_msg("%s: fchmodat2(AT_SYMLINK_NOFOLLOW) failed\n", 109 - __func__); 82 + if (ret < 0) { 83 + ksft_perror("fchmodat2(AT_SYMLINK_NOFOLLOW) failed"); 84 + goto out; 85 + } 110 86 111 - if (!expect_mode(dfd, "regfile", 0100600)) 112 - ksft_exit_fail_msg("%s: wrong file mode bits after fchmodat2 with nofollow\n", 113 - __func__); 87 + if (!expect_mode(testdir.dfd, "regfile", 0100600)) { 88 + ksft_print_msg("%s: wrong file mode bits after fchmodat2 with nofollow\n", 89 + __func__); 90 + ret = 1; 91 + } 114 92 115 - ksft_test_result_pass("fchmodat2(regfile)\n"); 93 + out: 94 + ksft_test_result(ret == 0, "fchmodat2(regfile)\n"); 95 + cleanup_testdir(&testdir); 116 96 } 117 97 118 98 void test_symlink(void) 119 99 { 120 - int dfd, ret; 100 + struct testdir testdir; 101 + int ret; 121 102 122 - dfd = setup_testdir(); 103 + setup_testdir(&testdir); 123 104 124 - ret = sys_fchmodat2(dfd, "symlink", 0640, 0); 105 + ret = sys_fchmodat2(testdir.dfd, "symlink", 0640, 0); 125 106 126 - if (ret < 0) 127 - ksft_exit_fail_msg("%s: fchmodat2(noflag) failed\n", __func__); 107 + if (ret < 0) { 108 + ksft_perror("fchmodat2(noflag) failed"); 109 + goto err; 110 + } 128 111 129 - if (!expect_mode(dfd, "regfile", 0100640)) 130 - ksft_exit_fail_msg("%s: wrong file mode bits after fchmodat2\n", 131 - __func__); 112 + if (!expect_mode(testdir.dfd, "regfile", 0100640)) { 113 + ksft_print_msg("%s: wrong file mode bits after fchmodat2\n", 114 + __func__); 115 + goto err; 116 + } 132 117 133 - if (!expect_mode(dfd, "symlink", 0120777)) 134 - ksft_exit_fail_msg("%s: wrong symlink mode bits after fchmodat2\n", 135 - __func__); 118 + if (!expect_mode(testdir.dfd, "symlink", 0120777)) { 119 + ksft_print_msg("%s: wrong symlink mode bits after fchmodat2\n", 120 + __func__); 121 + goto err; 122 + } 136 123 137 - ret = sys_fchmodat2(dfd, "symlink", 0600, AT_SYMLINK_NOFOLLOW); 124 + ret = sys_fchmodat2(testdir.dfd, "symlink", 0600, AT_SYMLINK_NOFOLLOW); 138 125 139 126 /* 140 127 * On certain filesystems (xfs or btrfs), chmod operation fails. So we ··· 162 111 * 163 112 * https://sourceware.org/legacy-ml/libc-alpha/2020-02/msg00467.html 164 113 */ 165 - if (ret == 0 && !expect_mode(dfd, "symlink", 0120600)) 166 - ksft_exit_fail_msg("%s: wrong symlink mode bits after fchmodat2 with nofollow\n", 114 + if (ret == 0 && !expect_mode(testdir.dfd, "symlink", 0120600)) { 115 + ksft_print_msg("%s: wrong symlink mode bits after fchmodat2 with nofollow\n", 167 116 __func__); 117 + ret = 1; 118 + goto err; 119 + } 168 120 169 - if (!expect_mode(dfd, "regfile", 0100640)) 170 - ksft_exit_fail_msg("%s: wrong file mode bits after fchmodat2 with nofollow\n", 171 - __func__); 121 + if (!expect_mode(testdir.dfd, "regfile", 0100640)) { 122 + ksft_print_msg("%s: wrong file mode bits after fchmodat2 with nofollow\n", 123 + __func__); 124 + } 172 125 173 126 if (ret != 0) 174 127 ksft_test_result_skip("fchmodat2(symlink)\n"); 175 128 else 176 129 ksft_test_result_pass("fchmodat2(symlink)\n"); 130 + cleanup_testdir(&testdir); 131 + return; 132 + 133 + err: 134 + ksft_test_result_fail("fchmodat2(symlink)\n"); 135 + cleanup_testdir(&testdir); 177 136 } 178 137 179 138 #define NUM_TESTS 2