chiark / gitweb /
0c3697b61b841b29b5c9504d336c47034058362f
[elogind.git] / src / shared / 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 #define SMACK_FLOOR_LABEL "_"
33 #define SMACK_STAR_LABEL  "*"
34
35 bool mac_smack_use(void) {
36 #ifdef HAVE_SMACK
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 #else
44         return false;
45 #endif
46 }
47
48 int mac_smack_apply(const char *path, const char *label) {
49         int r = 0;
50
51         assert(path);
52
53 #ifdef HAVE_SMACK
54         if (!mac_smack_use())
55                 return 0;
56
57         if (label)
58                 r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
59         else
60                 r = lremovexattr(path, "security.SMACK64");
61         if (r < 0)
62                 return -errno;
63 #endif
64
65         return r;
66 }
67
68 int mac_smack_apply_fd(int fd, const char *label) {
69         int r = 0;
70
71         assert(fd >= 0);
72
73 #ifdef HAVE_SMACK
74         if (!mac_smack_use())
75                 return 0;
76
77         if (label)
78                 r = fsetxattr(fd, "security.SMACK64", label, strlen(label), 0);
79         else
80                 r = fremovexattr(fd, "security.SMACK64");
81         if (r < 0)
82                 return -errno;
83 #endif
84
85         return r;
86 }
87
88 int mac_smack_apply_ip_out_fd(int fd, const char *label) {
89         int r = 0;
90
91         assert(fd >= 0);
92
93 #ifdef HAVE_SMACK
94         if (!mac_smack_use())
95                 return 0;
96
97         if (label)
98                 r = fsetxattr(fd, "security.SMACK64IPOUT", label, strlen(label), 0);
99         else
100                 r = fremovexattr(fd, "security.SMACK64IPOUT");
101         if (r < 0)
102                 return -errno;
103 #endif
104
105         return r;
106 }
107
108 int mac_smack_apply_ip_in_fd(int fd, const char *label) {
109         int r = 0;
110
111         assert(fd >= 0);
112
113 #ifdef HAVE_SMACK
114         if (!mac_smack_use())
115                 return 0;
116
117         if (label)
118                 r = fsetxattr(fd, "security.SMACK64IPIN", label, strlen(label), 0);
119         else
120                 r = fremovexattr(fd, "security.SMACK64IPIN");
121         if (r < 0)
122                 return -errno;
123 #endif
124
125         return r;
126 }
127
128 int mac_smack_apply_pid(pid_t pid, const char *label) {
129
130 #ifdef HAVE_SMACK
131         const char *p;
132 #endif
133         int r = 0;
134
135         assert(label);
136
137 #ifdef HAVE_SMACK
138         if (!mac_smack_use())
139                 return 0;
140
141         p = procfs_file_alloca(pid, "attr/current");
142         r = write_string_file(p, label, WRITE_STRING_FILE_CREATE);
143         if (r < 0)
144                 return r;
145 #endif
146
147         return r;
148 }
149
150 int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
151
152 #ifdef HAVE_SMACK
153         struct stat st;
154 #endif
155         int r = 0;
156
157         assert(path);
158
159 #ifdef HAVE_SMACK
160         if (!mac_smack_use())
161                 return 0;
162
163         /*
164          * Path must be in /dev and must exist
165          */
166         if (!path_startswith(path, "/dev"))
167                 return 0;
168
169         r = lstat(path, &st);
170         if (r >= 0) {
171                 const char *label;
172
173                 /*
174                  * Label directories and character devices "*".
175                  * Label symlinks "_".
176                  * Don't change anything else.
177                  */
178
179                 if (S_ISDIR(st.st_mode))
180                         label = SMACK_STAR_LABEL;
181                 else if (S_ISLNK(st.st_mode))
182                         label = SMACK_FLOOR_LABEL;
183                 else if (S_ISCHR(st.st_mode))
184                         label = SMACK_STAR_LABEL;
185                 else
186                         return 0;
187
188                 r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
189
190                 /* If the FS doesn't support labels, then exit without warning */
191                 if (r < 0 && errno == EOPNOTSUPP)
192                         return 0;
193         }
194
195         if (r < 0) {
196                 /* Ignore ENOENT in some cases */
197                 if (ignore_enoent && errno == ENOENT)
198                         return 0;
199
200                 if (ignore_erofs && errno == EROFS)
201                         return 0;
202
203                 r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
204         }
205 #endif
206
207         return r;
208 }