]>
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"); | |
ad118bda | 118 | r = write_string_file(p, label, 0); |
2ca620c4 WC |
119 | if (r < 0) |
120 | return r; | |
2ca620c4 WC |
121 | |
122 | return r; | |
123 | } | |
124 | ||
08c84981 LP |
125 | int mac_smack_fix(const char *path, LabelFixFlags flags) { |
126 | char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; | |
127 | _cleanup_close_ int fd = -1; | |
128 | const char *label; | |
5dfc5461 | 129 | struct stat st; |
01b2421f | 130 | int r; |
d53e386d LP |
131 | |
132 | assert(path); | |
133 | ||
d53e386d LP |
134 | if (!mac_smack_use()) |
135 | return 0; | |
66b6d9d5 | 136 | |
6696e2a6 LP |
137 | /* Path must be in /dev. Note that this check is pretty sloppy, as we might be called with non-normalized paths |
138 | * and hence not detect all cases of /dev. */ | |
139 | ||
140 | if (path_is_absolute(path)) { | |
141 | if (!path_startswith(path, "/dev")) | |
142 | return 0; | |
143 | } else { | |
144 | _cleanup_free_ char *cwd = NULL; | |
145 | ||
146 | r = safe_getcwd(&cwd); | |
147 | if (r < 0) | |
148 | return r; | |
149 | ||
150 | if (!path_startswith(cwd, "/dev")) | |
151 | return 0; | |
152 | } | |
66b6d9d5 | 153 | |
08c84981 LP |
154 | fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH); |
155 | if (fd < 0) { | |
156 | if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT) | |
5dfc5461 | 157 | return 0; |
66b6d9d5 | 158 | |
08c84981 LP |
159 | return -errno; |
160 | } | |
161 | ||
162 | if (fstat(fd, &st) < 0) | |
163 | return -errno; | |
164 | ||
165 | /* | |
166 | * Label directories and character devices "*". | |
167 | * Label symlinks "_". | |
168 | * Don't change anything else. | |
169 | */ | |
170 | ||
171 | if (S_ISDIR(st.st_mode)) | |
172 | label = SMACK_STAR_LABEL; | |
173 | else if (S_ISLNK(st.st_mode)) | |
174 | label = SMACK_FLOOR_LABEL; | |
175 | else if (S_ISCHR(st.st_mode)) | |
176 | label = SMACK_STAR_LABEL; | |
177 | else | |
178 | return 0; | |
179 | ||
180 | xsprintf(procfs_path, "/proc/self/fd/%i", fd); | |
181 | if (setxattr(procfs_path, "security.SMACK64", label, strlen(label), 0) < 0) { | |
182 | _cleanup_free_ char *old_label = NULL; | |
183 | ||
184 | r = -errno; | |
5dfc5461 LP |
185 | |
186 | /* If the FS doesn't support labels, then exit without warning */ | |
08c84981 | 187 | if (r == -EOPNOTSUPP) |
5dfc5461 | 188 | return 0; |
66b6d9d5 | 189 | |
08c84981 LP |
190 | /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */ |
191 | if (r == -EROFS && (flags & LABEL_IGNORE_EROFS)) | |
5dfc5461 LP |
192 | return 0; |
193 | ||
08c84981 LP |
194 | /* If the old label is identical to the new one, suppress any kind of error */ |
195 | if (getxattr_malloc(procfs_path, "security.SMACK64", &old_label, false) >= 0 && | |
196 | streq(old_label, label)) | |
5dfc5461 LP |
197 | return 0; |
198 | ||
08c84981 | 199 | return log_debug_errno(r, "Unable to fix SMACK label of %s: %m", path); |
66b6d9d5 | 200 | } |
66b6d9d5 | 201 | |
08c84981 | 202 | return 0; |
66b6d9d5 | 203 | } |
5ab58c20 | 204 | |
ba056b73 SW |
205 | int mac_smack_copy(const char *dest, const char *src) { |
206 | int r = 0; | |
207 | _cleanup_free_ char *label = NULL; | |
208 | ||
209 | assert(dest); | |
210 | assert(src); | |
211 | ||
212 | r = mac_smack_read(src, SMACK_ATTR_ACCESS, &label); | |
213 | if (r < 0) | |
214 | return r; | |
215 | ||
216 | r = mac_smack_apply(dest, SMACK_ATTR_ACCESS, label); | |
217 | if (r < 0) | |
218 | return r; | |
219 | ||
220 | return r; | |
221 | } | |
5ab58c20 WC |
222 | |
223 | #else | |
224 | bool mac_smack_use(void) { | |
225 | return false; | |
226 | } | |
227 | ||
228 | int mac_smack_read(const char *path, SmackAttr attr, char **label) { | |
229 | return -EOPNOTSUPP; | |
230 | } | |
231 | ||
232 | int mac_smack_read_fd(int fd, SmackAttr attr, char **label) { | |
233 | return -EOPNOTSUPP; | |
234 | } | |
235 | ||
236 | int mac_smack_apply(const char *path, SmackAttr attr, const char *label) { | |
237 | return 0; | |
238 | } | |
239 | ||
240 | int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) { | |
241 | return 0; | |
242 | } | |
243 | ||
244 | int mac_smack_apply_pid(pid_t pid, const char *label) { | |
245 | return 0; | |
246 | } | |
247 | ||
ee9e629e | 248 | int mac_smack_fix(const char *path, LabelFixFlags flags) { |
5ab58c20 WC |
249 | return 0; |
250 | } | |
ba056b73 SW |
251 | |
252 | int mac_smack_copy(const char *dest, const char *src) { | |
253 | return 0; | |
254 | } | |
5ab58c20 | 255 | #endif |