chiark / gitweb /
[2/5] Apply missing fixes from upstream
[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 "util.h"
27 #include "process-util.h"
28 #include "path-util.h"
29 #include "fileio.h"
30 #include "smack-util.h"
31
32 #ifdef HAVE_SMACK
33 bool mac_smack_use(void) {
34         static int cached_use = -1;
35
36         if (cached_use < 0)
37                 cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
38
39         return cached_use;
40 }
41
42 static const char* const smack_attr_table[_SMACK_ATTR_MAX] = {
43         [SMACK_ATTR_ACCESS]     = "security.SMACK64",
44         [SMACK_ATTR_EXEC]       = "security.SMACK64EXEC",
45         [SMACK_ATTR_MMAP]       = "security.SMACK64MMAP",
46         [SMACK_ATTR_TRANSMUTE]  = "security.SMACK64TRANSMUTE",
47         [SMACK_ATTR_IPIN]       = "security.SMACK64IPIN",
48         [SMACK_ATTR_IPOUT]      = "security.SMACK64IPOUT",
49 };
50
51 DEFINE_STRING_TABLE_LOOKUP(smack_attr, SmackAttr);
52
53 int mac_smack_read(const char *path, SmackAttr attr, char **label) {
54         assert(path);
55         assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
56         assert(label);
57
58         if (!mac_smack_use())
59                 return 0;
60
61         return getxattr_malloc(path, smack_attr_to_string(attr), label, true);
62 }
63
64 int mac_smack_read_fd(int fd, SmackAttr attr, char **label) {
65         assert(fd >= 0);
66         assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
67         assert(label);
68
69         if (!mac_smack_use())
70                 return 0;
71
72         return fgetxattr_malloc(fd, smack_attr_to_string(attr), label);
73 }
74
75 int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
76         int r;
77
78         assert(path);
79         assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
80
81         if (!mac_smack_use())
82                 return 0;
83
84         if (label)
85                 r = lsetxattr(path, smack_attr_to_string(attr), label, strlen(label), 0);
86         else
87                 r = lremovexattr(path, smack_attr_to_string(attr));
88         if (r < 0)
89                 return -errno;
90
91         return 0;
92 }
93
94 int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
95         int r;
96
97         assert(fd >= 0);
98         assert(attr >= 0 && attr < _SMACK_ATTR_MAX);
99
100         if (!mac_smack_use())
101                 return 0;
102
103         if (label)
104                 r = fsetxattr(fd, smack_attr_to_string(attr), label, strlen(label), 0);
105         else
106                 r = fremovexattr(fd, smack_attr_to_string(attr));
107         if (r < 0)
108                 return -errno;
109
110         return 0;
111 }
112
113 int mac_smack_apply_pid(pid_t pid, const char *label) {
114         const char *p;
115         int r = 0;
116
117         assert(label);
118
119         if (!mac_smack_use())
120                 return 0;
121
122         p = procfs_file_alloca(pid, "attr/current");
123         r = write_string_file(p, label, 0);
124         if (r < 0)
125                 return r;
126
127         return r;
128 }
129
130 int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
131         struct stat st;
132         int r = 0;
133
134         assert(path);
135
136         if (!mac_smack_use())
137                 return 0;
138
139         /*
140          * Path must be in /dev and must exist
141          */
142         if (!path_startswith(path, "/dev"))
143                 return 0;
144
145         r = lstat(path, &st);
146         if (r >= 0) {
147                 const char *label;
148
149                 /*
150                  * Label directories and character devices "*".
151                  * Label symlinks "_".
152                  * Don't change anything else.
153                  */
154
155                 if (S_ISDIR(st.st_mode))
156                         label = SMACK_STAR_LABEL;
157                 else if (S_ISLNK(st.st_mode))
158                         label = SMACK_FLOOR_LABEL;
159                 else if (S_ISCHR(st.st_mode))
160                         label = SMACK_STAR_LABEL;
161                 else
162                         return 0;
163
164                 r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
165
166                 /* If the FS doesn't support labels, then exit without warning */
167                 if (r < 0 && errno == EOPNOTSUPP)
168                         return 0;
169         }
170
171         if (r < 0) {
172                 /* Ignore ENOENT in some cases */
173                 if (ignore_enoent && errno == ENOENT)
174                         return 0;
175
176                 if (ignore_erofs && errno == EROFS)
177                         return 0;
178
179                 r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
180         }
181
182         return r;
183 }
184
185 int mac_smack_copy(const char *dest, const char *src) {
186         int r = 0;
187         _cleanup_free_ char *label = NULL;
188
189         assert(dest);
190         assert(src);
191
192         r = mac_smack_read(src, SMACK_ATTR_ACCESS, &label);
193         if (r < 0)
194                 return r;
195
196         r = mac_smack_apply(dest, SMACK_ATTR_ACCESS, label);
197         if (r < 0)
198                 return r;
199
200         return r;
201 }
202
203 #else
204 bool mac_smack_use(void) {
205         return false;
206 }
207
208 int mac_smack_read(const char *path, SmackAttr attr, char **label) {
209         return -EOPNOTSUPP;
210 }
211
212 int mac_smack_read_fd(int fd, SmackAttr attr, char **label) {
213         return -EOPNOTSUPP;
214 }
215
216 int mac_smack_apply(const char *path, SmackAttr attr, const char *label) {
217         return 0;
218 }
219
220 int mac_smack_apply_fd(int fd, SmackAttr attr, const char *label) {
221         return 0;
222 }
223
224 int mac_smack_apply_pid(pid_t pid, const char *label) {
225         return 0;
226 }
227
228 int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
229         return 0;
230 }
231
232 int mac_smack_copy(const char *dest, const char *src) {
233         return 0;
234 }
235 #endif