|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
1 | 2 | /*
|
2 | 3 | * Copyright (c) 2014 Fujitsu Ltd.
|
3 |
| - * Author: Zeng Linggang <[email protected]> |
4 |
| - * |
5 |
| - * This program is free software; you can redistribute it and/or modify it |
6 |
| - * under the terms of version 2 of the GNU General Public License as |
7 |
| - * published by the Free Software Foundation. |
8 |
| - * |
9 |
| - * This program is distributed in the hope that it would be useful, but |
10 |
| - * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
| - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
12 |
| - * |
13 |
| - * You should have received a copy of the GNU General Public License along |
14 |
| - * with this program. |
| 4 | + * Copyright (c) Linux Test Project, 2014-2025 |
15 | 5 | */
|
16 |
| -/* |
17 |
| - * Test Description: |
18 |
| - * Verify that, |
19 |
| - * The flag of fchownat() is AT_SYMLINK_NOFOLLOW and the pathname would |
20 |
| - * not be dereferenced if the pathname is a symbolic link. |
| 6 | + |
| 7 | +/*\ |
| 8 | + * [Description] |
| 9 | + * |
| 10 | + * Verify that fchownat() will operate on symbolic links when |
| 11 | + * AT_SYMLINK_NOFOLLOW is used. |
21 | 12 | */
|
22 | 13 |
|
23 | 14 | #define _GNU_SOURCE
|
24 |
| - |
25 |
| -#include <sys/types.h> |
26 |
| -#include <sys/stat.h> |
27 |
| -#include <unistd.h> |
28 |
| -#include <stdlib.h> |
29 |
| -#include <errno.h> |
30 |
| -#include <string.h> |
31 |
| -#include <signal.h> |
32 |
| -#include "test.h" |
33 |
| -#include "safe_macros.h" |
34 |
| -#include "lapi/fcntl.h" |
| 15 | +#include "tst_test.h" |
35 | 16 |
|
36 | 17 | #define TESTFILE "testfile"
|
37 | 18 | #define TESTFILE_LINK "testfile_link"
|
38 | 19 |
|
39 |
| -char *TCID = "fchownat02"; |
40 |
| -int TST_TOTAL = 1; |
41 |
| - |
42 |
| -static int dir_fd; |
43 | 20 | static uid_t set_uid = 1000;
|
44 | 21 | static gid_t set_gid = 1000;
|
45 |
| -static void setup(void); |
46 |
| -static void cleanup(void); |
47 |
| -static void test_verify(void); |
48 |
| -static void fchownat_verify(void); |
49 |
| - |
50 |
| -int main(int ac, char **av) |
51 |
| -{ |
52 |
| - int lc; |
53 |
| - int i; |
54 |
| - |
55 |
| - tst_parse_opts(ac, av, NULL, NULL); |
56 |
| - |
57 |
| - setup(); |
58 |
| - |
59 |
| - for (lc = 0; TEST_LOOPING(lc); lc++) { |
60 |
| - tst_count = 0; |
61 |
| - for (i = 0; i < TST_TOTAL; i++) |
62 |
| - fchownat_verify(); |
63 |
| - } |
64 |
| - |
65 |
| - cleanup(); |
66 |
| - tst_exit(); |
67 |
| -} |
68 | 22 |
|
69 | 23 | static void setup(void)
|
70 | 24 | {
|
71 | 25 | struct stat c_buf, l_buf;
|
72 | 26 |
|
73 |
| - tst_require_root(); |
74 |
| - |
75 |
| - tst_sig(NOFORK, DEF_HANDLER, cleanup); |
76 |
| - |
77 |
| - TEST_PAUSE; |
78 |
| - |
79 |
| - tst_tmpdir(); |
80 |
| - |
81 |
| - dir_fd = SAFE_OPEN(cleanup, "./", O_DIRECTORY); |
82 |
| - |
83 |
| - SAFE_TOUCH(cleanup, TESTFILE, 0600, NULL); |
84 |
| - |
85 |
| - SAFE_SYMLINK(cleanup, TESTFILE, TESTFILE_LINK); |
86 |
| - |
87 |
| - SAFE_STAT(cleanup, TESTFILE_LINK, &c_buf); |
88 |
| - |
89 |
| - SAFE_LSTAT(cleanup, TESTFILE_LINK, &l_buf); |
| 27 | + SAFE_TOUCH(TESTFILE, 0600, NULL); |
| 28 | + SAFE_SYMLINK(TESTFILE, TESTFILE_LINK); |
| 29 | + SAFE_STAT(TESTFILE_LINK, &c_buf); |
| 30 | + SAFE_LSTAT(TESTFILE_LINK, &l_buf); |
90 | 31 |
|
91 | 32 | if (l_buf.st_uid == set_uid || l_buf.st_gid == set_gid) {
|
92 |
| - tst_brkm(TBROK | TERRNO, cleanup, |
93 |
| - "link_uid(%d) == set_uid(%d) or link_gid(%d) == " |
94 |
| - "set_gid(%d)", l_buf.st_uid, set_uid, l_buf.st_gid, |
95 |
| - set_gid); |
| 33 | + tst_brk(TBROK, |
| 34 | + "uid link(%d) == set(%d) or gid link(%d) == set(%d)", |
| 35 | + l_buf.st_uid, set_uid, l_buf.st_gid, set_gid); |
96 | 36 | }
|
97 | 37 | }
|
98 | 38 |
|
99 |
| -static void fchownat_verify(void) |
100 |
| -{ |
101 |
| - TEST(fchownat(dir_fd, TESTFILE_LINK, set_uid, set_gid, |
102 |
| - AT_SYMLINK_NOFOLLOW)); |
103 |
| - |
104 |
| - if (TEST_RETURN != 0) { |
105 |
| - tst_resm(TFAIL | TTERRNO, "fchownat() failed, errno=%d : %s", |
106 |
| - TEST_ERRNO, strerror(TEST_ERRNO)); |
107 |
| - } else { |
108 |
| - test_verify(); |
109 |
| - } |
110 |
| -} |
111 |
| - |
112 |
| -static void test_verify(void) |
| 39 | +static void run(void) |
113 | 40 | {
|
114 | 41 | struct stat c_buf, l_buf;
|
115 | 42 |
|
116 |
| - SAFE_STAT(cleanup, TESTFILE_LINK, &c_buf); |
| 43 | + TST_EXP_PASS(fchownat(AT_FDCWD, TESTFILE_LINK, set_uid, set_gid, AT_SYMLINK_NOFOLLOW), |
| 44 | + "fchownat(%d, %s, %d, %d, %d)", |
| 45 | + AT_FDCWD, TESTFILE_LINK, set_uid, set_gid, AT_SYMLINK_NOFOLLOW); |
117 | 46 |
|
118 |
| - SAFE_LSTAT(cleanup, TESTFILE_LINK, &l_buf); |
| 47 | + SAFE_STAT(TESTFILE_LINK, &c_buf); |
| 48 | + SAFE_LSTAT(TESTFILE_LINK, &l_buf); |
119 | 49 |
|
120 |
| - if (c_buf.st_uid != set_uid && l_buf.st_uid == set_uid && |
121 |
| - c_buf.st_gid != set_gid && l_buf.st_gid == set_gid) { |
122 |
| - tst_resm(TPASS, "fchownat() test AT_SYMLINK_NOFOLLOW success"); |
123 |
| - } else { |
124 |
| - tst_resm(TFAIL, |
125 |
| - "fchownat() test AT_SYMLINK_NOFOLLOW fail with uid=%d " |
126 |
| - "link_uid=%d set_uid=%d | gid=%d link_gid=%d " |
127 |
| - "set_gid=%d", c_buf.st_uid, l_buf.st_uid, set_uid, |
128 |
| - c_buf.st_gid, l_buf.st_gid, set_gid); |
129 |
| - } |
| 50 | + TST_EXP_EXPR(c_buf.st_uid != set_uid && l_buf.st_uid == set_uid, |
| 51 | + "fchownat() correctly operated on symlink user ID"); |
| 52 | + TST_EXP_EXPR(c_buf.st_gid != set_gid && l_buf.st_gid == set_gid, |
| 53 | + "fchownat() correctly operated on symlink group ID"); |
130 | 54 | }
|
131 | 55 |
|
132 |
| -static void cleanup(void) |
133 |
| -{ |
134 |
| - tst_rmdir(); |
135 |
| -} |
| 56 | +static struct tst_test test = { |
| 57 | + .needs_tmpdir = 1, |
| 58 | + .needs_root = 1, |
| 59 | + .test_all = run, |
| 60 | + .setup = setup, |
| 61 | +}; |
0 commit comments