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