chiark / gitweb /
label: rework label_fix() implementations (#8583)
[elogind.git] / src / basic / smack-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
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>
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <errno.h>
24 //#include <fcntl.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/xattr.h>
28 #include <unistd.h>
29
30 #include "alloc-util.h"
31 //#include "fd-util.h"
32 #include "fileio.h"
33 #include "log.h"
34 #include "macro.h"
35 #include "path-util.h"
36 #include "process-util.h"
37 #include "smack-util.h"
38 //#include "stdio-util.h"
39 #include "string-table.h"
40 #include "xattr-util.h"
41
42 #if ENABLE_SMACK
43 bool mac_smack_use(void) {
44         static int cached_use = -1;
45
46         if (cached_use < 0)
47                 cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
48
49         return cached_use;
50 }
51
52 #if 0 /// UNNEEDED by elogind
53 static const char* const smack_attr_table[_SMACK_ATTR_MAX] = {
54         [SMACK_ATTR_ACCESS]     = "security.SMACK64",
55         [SMACK_ATTR_EXEC]       = "security.SMACK64EXEC",
56         [SMACK_ATTR_MMAP]       = "security.SMACK64MMAP",
57         [SMACK_ATTR_TRANSMUTE]  = "security.SMACK64TRANSMUTE",
58         [SMACK_ATTR_IPIN]       = "security.SMACK64IPIN",
59         [SMACK_ATTR_IPOUT]      = "security.SMACK64IPOUT",
60 };
61
62 DEFINE_STRING_TABLE_LOOKUP(smack_attr, SmackAttr);
63
64 int mac_smack_read(const char *path, SmackAttr attr, char **label) {
65         assert(path);
66         assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
67         assert(label);
68
69         if (!mac_smack_use())
70                 return 0;
71
72         return getxattr_malloc(path, smack_attr_to_string(attr), label, true);
73 }
74
75 int mac_smack_read_fd(int fd, SmackAttr attr, char **label) {
76         assert(fd >= 0);
77         assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
78         assert(label);
79
80         if (!mac_smack_use())
81                 return 0;
82
83         return fgetxattr_malloc(fd, smack_attr_to_string(attr), label);
84 }
85
86 int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
87         int r;
88
89         assert(path);
90         assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
91
92         if (!mac_smack_use())
93                 return 0;
94
95         if (label)
96                 r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0);
97         else
98                 r = lremovexattr(path, smack_attr_to_string(attr));
99         if (r < 0)
100                 return -errno;
101
102         return 0;
103 }
104
105 int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
106         int r;
107
108         assert(fd >= 0);
109         assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
110
111         if (!mac_smack_use())
112                 return 0;
113
114         if (label)
115                 r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0);
116         else
117                 r = fremovexattr(fd, smack_attr_to_string(attr));
118         if (r < 0)
119                 return -errno;
120
121         return 0;
122 }
123
124 int mac_smack_apply_pid(pid_t pid, const char *label) {
125         const char *p;
126         int r = 0;
127
128         assert(label);
129
130         if (!mac_smack_use())
131                 return 0;
132
133         p = procfs_file_alloca(pid, "attr/current");
134         r = write_string_file(p, label, 0);
135         if (r < 0)
136                 return r;
137
138         return r;
139 }
140 #endif // 0
141
142 int mac_smack_fix(const char *path, LabelFixFlags flags) {
143         char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
144         _cleanup_close_ int fd = -1;
145         const char *label;
146         struct stat st;
147         int r;
148
149         assert(path);
150
151         if (!mac_smack_use())
152                 return 0;
153
154         /* Path must be in /dev */
155         if (!path_startswith(path, "/dev"))
156                 return 0;
157
158         fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
159         if (fd < 0) {
160                 if ((flags & LABEL_IGNORE_ENOENT) && errno == ENOENT)
161                         return 0;
162
163                 return -errno;
164         }
165
166         if (fstat(fd, &st) < 0)
167                 return -errno;
168
169         /*
170          * Label directories and character devices "*".
171          * Label symlinks "_".
172          * Don't change anything else.
173          */
174
175         if (S_ISDIR(st.st_mode))
176                 label = SMACK_STAR_LABEL;
177         else if (S_ISLNK(st.st_mode))
178                 label = SMACK_FLOOR_LABEL;
179         else if (S_ISCHR(st.st_mode))
180                 label = SMACK_STAR_LABEL;
181         else
182                 return 0;
183
184         xsprintf(procfs_path, "/proc/self/fd/%i", fd);
185         if (setxattr(procfs_path, "security.SMACK64", label, strlen(label), 0) < 0) {
186                 _cleanup_free_ char *old_label = NULL;
187
188                 r = -errno;
189
190                 /* If the FS doesn't support labels, then exit without warning */
191                 if (r == -EOPNOTSUPP)
192                         return 0;
193
194                 /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
195                 if (r == -EROFS && (flags & LABEL_IGNORE_EROFS))
196                         return 0;
197
198                 /* If the old label is identical to the new one, suppress any kind of error */
199                 if (getxattr_malloc(procfs_path, "security.SMACK64", &old_label, false) >= 0 &&
200                     streq(old_label, label))
201                         return 0;
202
203                 return log_debug_errno(r, "Unable to fix SMACK label of %s: %m", path);
204         }
205
206         return 0;
207 }
208
209 #if 0 /// UNNEEDED by elogind
210 int mac_smack_copy(const char *dest, const char *src) {
211         int r = 0;
212         _cleanup_free_ char *label = NULL;
213
214         assert(dest);
215         assert(src);
216
217         r = mac_smack_read(src, SMACK_ATTR_ACCESS, &label);
218         if (r < 0)
219                 return r;
220
221         r = mac_smack_apply(dest, SMACK_ATTR_ACCESS, label);
222         if (r < 0)
223                 return r;
224
225         return r;
226 }
227 #endif // 0
228
229 #else
230 bool mac_smack_use(void) {
231         return false;
232 }
233
234 #if 0 /// UNNEEDED by elogind
235 int mac_smack_read(const char *path, SmackAttr attr, char **label) {
236         return -EOPNOTSUPP;
237 }
238
239 int mac_smack_read_fd(int fd, SmackAttr attr, char **label) {
240         return -EOPNOTSUPP;
241 }
242
243 int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
244         return 0;
245 }
246
247 int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
248         return 0;
249 }
250
251 int mac_smack_apply_pid(pid_t pid, const char *label) {
252         return 0;
253 }
254 #endif // 0
255
256 int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
257         return 0;
258 }
259
260 #if 0 /// UNNEEDED by elogind
261 int mac_smack_copy(const char *dest, const char *src) {
262         return 0;
263 }
264 #endif // 0
265 #endif