Line data Source code
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 62 : bool mac_smack_use(void) {
29 : static int cached_use = -1;
30 :
31 62 : if (cached_use < 0)
32 46 : cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
33 :
34 62 : return cached_use;
35 : }
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 0 : 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 :
53 0 : if (!mac_smack_use())
54 0 : return 0;
55 :
56 0 : return getxattr_malloc(path, smack_attr_to_string(attr), label, true);
57 : }
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 :
64 0 : if (!mac_smack_use())
65 0 : return 0;
66 :
67 0 : return fgetxattr_malloc(fd, smack_attr_to_string(attr), label);
68 : }
69 :
70 0 : int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
71 : int r;
72 :
73 0 : assert(path);
74 0 : assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
75 :
76 0 : if (!mac_smack_use())
77 0 : return 0;
78 :
79 0 : if (label)
80 0 : r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0);
81 : else
82 0 : r = lremovexattr(path, smack_attr_to_string(attr));
83 0 : if (r < 0)
84 0 : return -errno;
85 :
86 0 : return 0;
87 : }
88 :
89 0 : int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
90 : int r;
91 :
92 0 : assert(fd >= 0);
93 0 : assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
94 :
95 0 : if (!mac_smack_use())
96 0 : return 0;
97 :
98 0 : if (label)
99 0 : r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0);
100 : else
101 0 : r = fremovexattr(fd, smack_attr_to_string(attr));
102 0 : if (r < 0)
103 0 : return -errno;
104 :
105 0 : return 0;
106 : }
107 :
108 0 : int mac_smack_apply_pid(pid_t pid, const char *label) {
109 : const char *p;
110 0 : int r = 0;
111 :
112 0 : assert(label);
113 :
114 0 : if (!mac_smack_use())
115 0 : return 0;
116 :
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 :
122 0 : return r;
123 : }
124 :
125 0 : static int smack_fix_fd(int fd , const char *abspath, LabelFixFlags flags) {
126 : char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
127 : const char *label;
128 : struct stat st;
129 : int r;
130 :
131 : /* The caller should have done the sanity checks. */
132 0 : assert(abspath);
133 0 : assert(path_is_absolute(abspath));
134 :
135 : /* Path must be in /dev. */
136 0 : if (!path_startswith(abspath, "/dev"))
137 0 : return 0;
138 :
139 0 : if (fstat(fd, &st) < 0)
140 0 : return -errno;
141 :
142 : /*
143 : * Label directories and character devices "*".
144 : * Label symlinks "_".
145 : * Don't change anything else.
146 : */
147 :
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 : else
155 0 : return 0;
156 :
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 :
161 0 : r = -errno;
162 :
163 : /* If the FS doesn't support labels, then exit without warning */
164 0 : if (r == -EOPNOTSUPP)
165 0 : return 0;
166 :
167 : /* 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 :
171 : /* 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 :
176 0 : return log_debug_errno(r, "Unable to fix SMACK label of %s: %m", abspath);
177 : }
178 :
179 0 : return 0;
180 : }
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 : int r;
186 :
187 0 : assert(path);
188 :
189 0 : if (!mac_smack_use())
190 0 : return 0;
191 :
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 :
197 0 : return -errno;
198 : }
199 :
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 : }
206 :
207 0 : return smack_fix_fd(fd, path, flags);
208 : }
209 :
210 59 : int mac_smack_fix(const char *path, LabelFixFlags flags) {
211 59 : _cleanup_free_ char *abspath = NULL;
212 59 : _cleanup_close_ int fd = -1;
213 : int r;
214 :
215 59 : assert(path);
216 :
217 59 : if (!mac_smack_use())
218 59 : return 0;
219 :
220 0 : r = path_make_absolute_cwd(path, &abspath);
221 0 : if (r < 0)
222 0 : return r;
223 :
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 :
229 0 : return -errno;
230 : }
231 :
232 0 : return smack_fix_fd(fd, abspath, flags);
233 : }
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 :
239 0 : assert(dest);
240 0 : assert(src);
241 :
242 0 : r = mac_smack_read(src, SMACK_ATTR_ACCESS, &label);
243 0 : if (r < 0)
244 0 : return r;
245 :
246 0 : r = mac_smack_apply(dest, SMACK_ATTR_ACCESS, label);
247 0 : if (r < 0)
248 0 : return r;
249 :
250 0 : return r;
251 : }
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
|