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