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