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