Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <sys/xattr.h>
4 : : #include <unistd.h>
5 : :
6 : : #include "alloc-util.h"
7 : : #include "chown-recursive.h"
8 : : #include "log.h"
9 : : #include "rm-rf.h"
10 : : #include "string-util.h"
11 : : #include "tests.h"
12 : : #include "tmpfile-util.h"
13 : :
14 : : static const uint8_t acl[] = {
15 : : 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00,
16 : : 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x07, 0x00,
17 : : 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x07, 0x00,
18 : : 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x07, 0x00,
19 : : 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x05, 0x00,
20 : : 0xff, 0xff, 0xff, 0xff,
21 : : };
22 : :
23 : : static const uint8_t default_acl[] = {
24 : : 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00,
25 : : 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x07, 0x00,
26 : : 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x07, 0x00,
27 : : 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x00,
28 : : 0xff, 0xff, 0xff, 0xff, 0x20, 0x00, 0x05, 0x00,
29 : : 0xff, 0xff, 0xff, 0xff,
30 : : };
31 : :
32 : 0 : static bool has_xattr(const char *p) {
33 : : char buffer[sizeof(acl) * 4];
34 : :
35 [ # # ]: 0 : if (lgetxattr(p, "system.posix_acl_access", buffer, sizeof(buffer)) < 0) {
36 [ # # # # ]: 0 : if (IN_SET(errno, EOPNOTSUPP, ENOTTY, ENODATA, ENOSYS))
37 : 0 : return false;
38 : : }
39 : :
40 : 0 : return true;
41 : : }
42 : :
43 : 0 : static void test_chown_recursive(void) {
44 : 0 : _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
45 : : struct stat st;
46 : : const char *p;
47 : 0 : const uid_t uid = getuid();
48 : 0 : const gid_t gid = getgid();
49 : :
50 : 0 : umask(022);
51 [ # # ]: 0 : assert_se(mkdtemp_malloc(NULL, &t) >= 0);
52 : :
53 [ # # # # : 0 : p = strjoina(t, "/dir");
# # # # #
# # # ]
54 [ # # ]: 0 : assert_se(mkdir(p, 0777) >= 0);
55 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
56 [ # # ]: 0 : assert_se(S_ISDIR(st.st_mode));
57 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0755);
58 [ # # ]: 0 : assert_se(st.st_uid == uid);
59 [ # # ]: 0 : assert_se(st.st_gid == gid);
60 [ # # ]: 0 : assert_se(!has_xattr(p));
61 : :
62 [ # # # # : 0 : p = strjoina(t, "/dir/symlink");
# # # # #
# # # ]
63 [ # # ]: 0 : assert_se(symlink("../../", p) >= 0);
64 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
65 [ # # ]: 0 : assert_se(S_ISLNK(st.st_mode));
66 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0777);
67 [ # # ]: 0 : assert_se(st.st_uid == uid);
68 [ # # ]: 0 : assert_se(st.st_gid == gid);
69 [ # # ]: 0 : assert_se(!has_xattr(p));
70 : :
71 [ # # # # : 0 : p = strjoina(t, "/dir/reg");
# # # # #
# # # ]
72 [ # # ]: 0 : assert_se(mknod(p, S_IFREG|0777, 0) >= 0);
73 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
74 [ # # ]: 0 : assert_se(S_ISREG(st.st_mode));
75 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0755);
76 [ # # ]: 0 : assert_se(st.st_uid == uid);
77 [ # # ]: 0 : assert_se(st.st_gid == gid);
78 [ # # ]: 0 : assert_se(!has_xattr(p));
79 : :
80 [ # # # # : 0 : p = strjoina(t, "/dir/sock");
# # # # #
# # # ]
81 [ # # ]: 0 : assert_se(mknod(p, S_IFSOCK|0777, 0) >= 0);
82 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
83 [ # # ]: 0 : assert_se(S_ISSOCK(st.st_mode));
84 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0755);
85 [ # # ]: 0 : assert_se(st.st_uid == uid);
86 [ # # ]: 0 : assert_se(st.st_gid == gid);
87 [ # # ]: 0 : assert_se(!has_xattr(p));
88 : :
89 [ # # # # : 0 : p = strjoina(t, "/dir/fifo");
# # # # #
# # # ]
90 [ # # ]: 0 : assert_se(mknod(p, S_IFIFO|0777, 0) >= 0);
91 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
92 [ # # ]: 0 : assert_se(S_ISFIFO(st.st_mode));
93 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0755);
94 [ # # ]: 0 : assert_se(st.st_uid == uid);
95 [ # # ]: 0 : assert_se(st.st_gid == gid);
96 [ # # ]: 0 : assert_se(!has_xattr(p));
97 : :
98 : : /* We now apply an xattr to the dir, and check it again */
99 [ # # # # : 0 : p = strjoina(t, "/dir");
# # # # #
# # # ]
100 [ # # ]: 0 : assert_se(setxattr(p, "system.posix_acl_access", acl, sizeof(acl), 0) >= 0);
101 [ # # ]: 0 : assert_se(setxattr(p, "system.posix_acl_default", default_acl, sizeof(default_acl), 0) >= 0);
102 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
103 [ # # ]: 0 : assert_se(S_ISDIR(st.st_mode));
104 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0775); /* acl change changed the mode too */
105 [ # # ]: 0 : assert_se(st.st_uid == uid);
106 [ # # ]: 0 : assert_se(st.st_gid == gid);
107 [ # # ]: 0 : assert_se(has_xattr(p));
108 : :
109 [ # # ]: 0 : assert_se(path_chown_recursive(t, 1, 2, 07777) >= 0);
110 : :
111 [ # # # # : 0 : p = strjoina(t, "/dir");
# # # # #
# # # ]
112 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
113 [ # # ]: 0 : assert_se(S_ISDIR(st.st_mode));
114 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0775);
115 [ # # ]: 0 : assert_se(st.st_uid == 1);
116 [ # # ]: 0 : assert_se(st.st_gid == 2);
117 [ # # ]: 0 : assert_se(!has_xattr(p));
118 : :
119 [ # # # # : 0 : p = strjoina(t, "/dir/symlink");
# # # # #
# # # ]
120 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
121 [ # # ]: 0 : assert_se(S_ISLNK(st.st_mode));
122 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0777);
123 [ # # ]: 0 : assert_se(st.st_uid == 1);
124 [ # # ]: 0 : assert_se(st.st_gid == 2);
125 [ # # ]: 0 : assert_se(!has_xattr(p));
126 : :
127 [ # # # # : 0 : p = strjoina(t, "/dir/reg");
# # # # #
# # # ]
128 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
129 [ # # ]: 0 : assert_se(S_ISREG(st.st_mode));
130 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0755);
131 [ # # ]: 0 : assert_se(st.st_uid == 1);
132 [ # # ]: 0 : assert_se(st.st_gid == 2);
133 [ # # ]: 0 : assert_se(!has_xattr(p));
134 : :
135 [ # # # # : 0 : p = strjoina(t, "/dir/sock");
# # # # #
# # # ]
136 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
137 [ # # ]: 0 : assert_se(S_ISSOCK(st.st_mode));
138 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0755);
139 [ # # ]: 0 : assert_se(st.st_uid == 1);
140 [ # # ]: 0 : assert_se(st.st_gid == 2);
141 [ # # ]: 0 : assert_se(!has_xattr(p));
142 : :
143 [ # # # # : 0 : p = strjoina(t, "/dir/fifo");
# # # # #
# # # ]
144 [ # # ]: 0 : assert_se(lstat(p, &st) >= 0);
145 [ # # ]: 0 : assert_se(S_ISFIFO(st.st_mode));
146 [ # # ]: 0 : assert_se((st.st_mode & 07777) == 0755);
147 [ # # ]: 0 : assert_se(st.st_uid == 1);
148 [ # # ]: 0 : assert_se(st.st_gid == 2);
149 [ # # ]: 0 : assert_se(!has_xattr(p));
150 : 0 : }
151 : :
152 : 4 : int main(int argc, char *argv[]) {
153 : 4 : test_setup_logging(LOG_DEBUG);
154 : :
155 [ + - ]: 4 : if (geteuid() != 0)
156 : 4 : return log_tests_skipped("not running as root");
157 : :
158 : 0 : test_chown_recursive();
159 : :
160 : 0 : return EXIT_SUCCESS;
161 : : }
|