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