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