/src/systemd/src/basic/smack-util.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | | /*** |
3 | | Copyright © 2013 Intel Corporation |
4 | | |
5 | | Author: Auke Kok <auke-jan.h.kok@intel.com> |
6 | | ***/ |
7 | | |
8 | | #include <errno.h> |
9 | | #include <fcntl.h> |
10 | | #include <string.h> |
11 | | #include <sys/stat.h> |
12 | | #include <sys/xattr.h> |
13 | | #include <unistd.h> |
14 | | |
15 | | #include "alloc-util.h" |
16 | | #include "fd-util.h" |
17 | | #include "fileio.h" |
18 | | #include "log.h" |
19 | | #include "macro.h" |
20 | | #include "path-util.h" |
21 | | #include "process-util.h" |
22 | | #include "smack-util.h" |
23 | | #include "stdio-util.h" |
24 | | #include "string-table.h" |
25 | | #include "xattr-util.h" |
26 | | |
27 | | #if ENABLE_SMACK |
28 | 0 | bool mac_smack_use(void) { |
29 | 0 | static int cached_use = -1; |
30 | 0 |
|
31 | 0 | if (cached_use < 0) |
32 | 0 | cached_use = access("/sys/fs/smackfs/", F_OK) >= 0; |
33 | 0 |
|
34 | 0 | return cached_use; |
35 | 0 | } |
36 | | |
37 | | static const char* const smack_attr_table[_SMACK_ATTR_MAX] = { |
38 | | [SMACK_ATTR_ACCESS] = "security.SMACK64", |
39 | | [SMACK_ATTR_EXEC] = "security.SMACK64EXEC", |
40 | | [SMACK_ATTR_MMAP] = "security.SMACK64MMAP", |
41 | | [SMACK_ATTR_TRANSMUTE] = "security.SMACK64TRANSMUTE", |
42 | | [SMACK_ATTR_IPIN] = "security.SMACK64IPIN", |
43 | | [SMACK_ATTR_IPOUT] = "security.SMACK64IPOUT", |
44 | | }; |
45 | | |
46 | | DEFINE_STRING_TABLE_LOOKUP(smack_attr, SmackAttr); |
47 | | |
48 | 0 | int mac_smack_read(const char *path, SmackAttr attr, char **label) { |
49 | 0 | assert(path); |
50 | 0 | assert(attr >= 0 && attr < _SMACK_ATTR_MAX); |
51 | 0 | assert(label); |
52 | 0 |
|
53 | 0 | if (!mac_smack_use()) |
54 | 0 | return 0; |
55 | 0 | |
56 | 0 | return getxattr_malloc(path, smack_attr_to_string(attr), label, true); |
57 | 0 | } |
58 | | |
59 | 0 | int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { |
60 | 0 | assert(fd >= 0); |
61 | 0 | assert(attr >= 0 && attr < _SMACK_ATTR_MAX); |
62 | 0 | assert(label); |
63 | 0 |
|
64 | 0 | if (!mac_smack_use()) |
65 | 0 | return 0; |
66 | 0 | |
67 | 0 | return fgetxattr_malloc(fd, smack_attr_to_string(attr), label); |
68 | 0 | } |
69 | | |
70 | 0 | int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { |
71 | 0 | int r; |
72 | 0 |
|
73 | 0 | assert(path); |
74 | 0 | assert(attr >= 0 && attr < _SMACK_ATTR_MAX); |
75 | 0 |
|
76 | 0 | if (!mac_smack_use()) |
77 | 0 | return 0; |
78 | 0 | |
79 | 0 | if (label) |
80 | 0 | r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0); |
81 | 0 | else |
82 | 0 | r = lremovexattr(path, smack_attr_to_string(attr)); |
83 | 0 | if (r < 0) |
84 | 0 | return -errno; |
85 | 0 | |
86 | 0 | return 0; |
87 | 0 | } |
88 | | |
89 | 0 | int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { |
90 | 0 | int r; |
91 | 0 |
|
92 | 0 | assert(fd >= 0); |
93 | 0 | assert(attr >= 0 && attr < _SMACK_ATTR_MAX); |
94 | 0 |
|
95 | 0 | if (!mac_smack_use()) |
96 | 0 | return 0; |
97 | 0 | |
98 | 0 | if (label) |
99 | 0 | r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0); |
100 | 0 | else |
101 | 0 | r = fremovexattr(fd, smack_attr_to_string(attr)); |
102 | 0 | if (r < 0) |
103 | 0 | return -errno; |
104 | 0 | |
105 | 0 | return 0; |
106 | 0 | } |
107 | | |
108 | 0 | int mac_smack_apply_pid(pid_t pid, const char *label) { |
109 | 0 | const char *p; |
110 | 0 | int r = 0; |
111 | 0 |
|
112 | 0 | assert(label); |
113 | 0 |
|
114 | 0 | if (!mac_smack_use()) |
115 | 0 | return 0; |
116 | 0 | |
117 | 0 | p = procfs_file_alloca(pid, "attr/current"); |
118 | 0 | r = write_string_file(p, label, WRITE_STRING_FILE_DISABLE_BUFFER); |
119 | 0 | if (r < 0) |
120 | 0 | return r; |
121 | 0 | |
122 | 0 | return r; |
123 | 0 | } |
124 | | |
125 | 0 | static int smack_fix_fd(int fd , const char *abspath, LabelFixFlags flags) { |
126 | 0 | char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; |
127 | 0 | const char *label; |
128 | 0 | struct stat st; |
129 | 0 | int r; |
130 | 0 |
|
131 | 0 | /* The caller should have done the sanity checks. */ |
132 | 0 | assert(abspath); |
133 | 0 | assert(path_is_absolute(abspath)); |
134 | 0 |
|
135 | 0 | /* Path must be in /dev. */ |
136 | 0 | if (!path_startswith(abspath, "/dev")) |
137 | 0 | return 0; |
138 | 0 | |
139 | 0 | if (fstat(fd, &st) < 0) |
140 | 0 | return -errno; |
141 | 0 | |
142 | 0 | /* |
143 | 0 | * Label directories and character devices "*". |
144 | 0 | * Label symlinks "_". |
145 | 0 | * Don't change anything else. |
146 | 0 | */ |
147 | 0 | |
148 | 0 | if (S_ISDIR(st.st_mode)) |
149 | 0 | label = SMACK_STAR_LABEL; |
150 | 0 | else if (S_ISLNK(st.st_mode)) |
151 | 0 | label = SMACK_FLOOR_LABEL; |
152 | 0 | else if (S_ISCHR(st.st_mode)) |
153 | 0 | label = SMACK_STAR_LABEL; |
154 | 0 | else |
155 | 0 | return 0; |
156 | 0 | |
157 | 0 | xsprintf(procfs_path, "/proc/self/fd/%i", fd); |
158 | 0 | if (setxattr(procfs_path, "security.SMACK64", label, strlen(label), 0) < 0) { |
159 | 0 | _cleanup_free_ char *old_label = NULL; |
160 | 0 |
|
161 | 0 | r = -errno; |
162 | 0 |
|
163 | 0 | /* If the FS doesn't support labels, then exit without warning */ |
164 | 0 | if (r == -EOPNOTSUPP) |
165 | 0 | return 0; |
166 | 0 | |
167 | 0 | /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */ |
168 | 0 | if (r == -EROFS && (flags & LABEL_IGNORE_EROFS)) |
169 | 0 | return 0; |
170 | 0 | |
171 | 0 | /* If the old label is identical to the new one, suppress any kind of error */ |
172 | 0 | if (getxattr_malloc(procfs_path, "security.SMACK64", &old_label, false) >= 0 && |
173 | 0 | streq(old_label, label)) |
174 | 0 | return 0; |
175 | 0 | |
176 | 0 | return log_debug_errno(r, "Unable to fix SMACK label of %s: %m", abspath); |
177 | 0 | } |
178 | 0 |
|
179 | 0 | return 0; |
180 | 0 | } |
181 | | |
182 | 0 | int mac_smack_fix_at(int dirfd, const char *path, LabelFixFlags flags) { |
183 | 0 | _cleanup_free_ char *p = NULL; |
184 | 0 | _cleanup_close_ int fd = -1; |
185 | 0 | int r; |
186 | 0 |
|
187 | 0 | assert(path); |
188 | 0 |
|
189 | 0 | if (!mac_smack_use()) |
190 | 0 | return 0; |
191 | 0 | |
192 | 0 | fd = openat(dirfd, path, O_NOFOLLOW|O_CLOEXEC|O_PATH); |
193 | 0 | if (fd < 0) { |
194 | 0 | if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT) |
195 | 0 | return 0; |
196 | 0 | |
197 | 0 | return -errno; |
198 | 0 | } |
199 | 0 | |
200 | 0 | if (!path_is_absolute(path)) { |
201 | 0 | r = fd_get_path(fd, &p); |
202 | 0 | if (r < 0) |
203 | 0 | return r; |
204 | 0 | path = p; |
205 | 0 | } |
206 | 0 |
|
207 | 0 | return smack_fix_fd(fd, path, flags); |
208 | 0 | } |
209 | | |
210 | 0 | int mac_smack_fix(const char *path, LabelFixFlags flags) { |
211 | 0 | _cleanup_free_ char *abspath = NULL; |
212 | 0 | _cleanup_close_ int fd = -1; |
213 | 0 | int r; |
214 | 0 |
|
215 | 0 | assert(path); |
216 | 0 |
|
217 | 0 | if (!mac_smack_use()) |
218 | 0 | return 0; |
219 | 0 | |
220 | 0 | r = path_make_absolute_cwd(path, &abspath); |
221 | 0 | if (r < 0) |
222 | 0 | return r; |
223 | 0 | |
224 | 0 | fd = open(abspath, O_NOFOLLOW|O_CLOEXEC|O_PATH); |
225 | 0 | if (fd < 0) { |
226 | 0 | if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT) |
227 | 0 | return 0; |
228 | 0 | |
229 | 0 | return -errno; |
230 | 0 | } |
231 | 0 | |
232 | 0 | return smack_fix_fd(fd, abspath, flags); |
233 | 0 | } |
234 | | |
235 | 0 | int mac_smack_copy(const char *dest, const char *src) { |
236 | 0 | int r = 0; |
237 | 0 | _cleanup_free_ char *label = NULL; |
238 | 0 |
|
239 | 0 | assert(dest); |
240 | 0 | assert(src); |
241 | 0 |
|
242 | 0 | r = mac_smack_read(src, SMACK_ATTR_ACCESS, &label); |
243 | 0 | if (r < 0) |
244 | 0 | return r; |
245 | 0 | |
246 | 0 | r = mac_smack_apply(dest, SMACK_ATTR_ACCESS, label); |
247 | 0 | if (r < 0) |
248 | 0 | return r; |
249 | 0 | |
250 | 0 | return r; |
251 | 0 | } |
252 | | |
253 | | #else |
254 | | bool mac_smack_use(void) { |
255 | | return false; |
256 | | } |
257 | | |
258 | | int mac_smack_read(const char *path, SmackAttr attr, char **label) { |
259 | | return -EOPNOTSUPP; |
260 | | } |
261 | | |
262 | | int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { |
263 | | return -EOPNOTSUPP; |
264 | | } |
265 | | |
266 | | int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { |
267 | | return 0; |
268 | | } |
269 | | |
270 | | int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { |
271 | | return 0; |
272 | | } |
273 | | |
274 | | int mac_smack_apply_pid(pid_t pid, const char *label) { |
275 | | return 0; |
276 | | } |
277 | | |
278 | | int mac_smack_fix(const char *path, LabelFixFlags flags) { |
279 | | return 0; |
280 | | } |
281 | | |
282 | | int mac_smack_fix_at(int dirfd, const char *path, LabelFixFlags flags) { |
283 | | return 0; |
284 | | } |
285 | | |
286 | | int mac_smack_copy(const char *dest, const char *src) { |
287 | | return 0; |
288 | | } |
289 | | #endif |