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