]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/smack-setup.c
util: split out escaping code into escape.[ch]
[thirdparty/systemd.git] / src / core / smack-setup.c
CommitLineData
ffbd2c4d
NC
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright (C) 2013 Intel Corporation
7 Authors:
8 Nathaniel Chen <nathaniel.chen@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
12 by the Free Software Foundation; either version 2.1 of the License,
13 or (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 <stdio.h>
25#include <errno.h>
26#include <string.h>
ffbd2c4d 27#include <stdlib.h>
ffbd2c4d 28#include <fcntl.h>
ffbd2c4d 29#include <dirent.h>
ffbd2c4d
NC
30
31#include "macro.h"
32#include "smack-setup.h"
33#include "util.h"
8b197c3a 34#include "fileio.h"
ffbd2c4d 35#include "log.h"
ffbd2c4d 36
2b3e18de
KL
37#ifdef HAVE_SMACK
38
6656aefb
WC
39static int write_access2_rules(const char* srcdir) {
40 _cleanup_close_ int load2_fd = -1, change_fd = -1;
ffbd2c4d
NC
41 _cleanup_closedir_ DIR *dir = NULL;
42 struct dirent *entry;
43 char buf[NAME_MAX];
44 int dfd = -1;
a4783bd1 45 int r = 0;
ffbd2c4d 46
6656aefb
WC
47 load2_fd = open("/sys/fs/smackfs/load2", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
48 if (load2_fd < 0) {
49 if (errno != ENOENT)
50 log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/load2': %m");
51 return -errno; /* negative error */
52 }
53
54 change_fd = open("/sys/fs/smackfs/change-rule", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
55 if (change_fd < 0) {
a4783bd1 56 if (errno != ENOENT)
6656aefb 57 log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/change-rule': %m");
a4783bd1 58 return -errno; /* negative error */
ffbd2c4d
NC
59 }
60
6656aefb 61 /* write rules to load2 or change-rule from every file in the directory */
a4783bd1 62 dir = opendir(srcdir);
ffbd2c4d 63 if (!dir) {
a4783bd1 64 if (errno != ENOENT)
6656aefb 65 log_warning_errno(errno, "Failed to opendir '%s': %m", srcdir);
a4783bd1 66 return errno; /* positive on purpose */
ffbd2c4d
NC
67 }
68
69 dfd = dirfd(dir);
fea7838e 70 assert(dfd >= 0);
ffbd2c4d
NC
71
72 FOREACH_DIRENT(entry, dir, return 0) {
a4783bd1 73 int fd;
ffbd2c4d 74 _cleanup_fclose_ FILE *policy = NULL;
ffbd2c4d 75
6656aefb
WC
76 if (!dirent_is_file(entry))
77 continue;
78
a4783bd1
ZJS
79 fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC);
80 if (fd < 0) {
81 if (r == 0)
82 r = -errno;
6656aefb 83 log_warning_errno(errno, "Failed to open '%s': %m", entry->d_name);
ffbd2c4d
NC
84 continue;
85 }
86
a4783bd1 87 policy = fdopen(fd, "re");
ffbd2c4d 88 if (!policy) {
a4783bd1
ZJS
89 if (r == 0)
90 r = -errno;
03e334a1 91 safe_close(fd);
6656aefb 92 log_error_errno(errno, "Failed to open '%s': %m", entry->d_name);
ffbd2c4d
NC
93 continue;
94 }
95
ffbd2c4d 96 /* load2 write rules in the kernel require a line buffered stream */
fea7838e 97 FOREACH_LINE(buf, policy,
6656aefb
WC
98 log_error_errno(errno, "Failed to read line from '%s': %m",
99 entry->d_name)) {
100
101 _cleanup_free_ char *sbj = NULL, *obj = NULL, *acc1 = NULL, *acc2 = NULL;
102
103 if (isempty(truncate_nl(buf)))
104 continue;
105
106 /* if 3 args -> load rule : subject object access1 */
107 /* if 4 args -> change rule : subject object access1 access2 */
108 if (sscanf(buf, "%ms %ms %ms %ms", &sbj, &obj, &acc1, &acc2) < 3) {
109 log_error_errno(errno, "Failed to parse rule '%s' in '%s', ignoring.", buf, entry->d_name);
110 continue;
111 }
112
113 if (write(isempty(acc2) ? load2_fd : change_fd, buf, strlen(buf)) < 0) {
a4783bd1 114 if (r == 0)
6656aefb
WC
115 r = -errno;
116 log_error_errno(errno, "Failed to write '%s' to '%s' in '%s'",
117 buf, isempty(acc2) ? "/sys/fs/smackfs/load2" : "/sys/fs/smackfs/change-rule", entry->d_name);
a4783bd1 118 }
6656aefb
WC
119 }
120 }
121
122 return r;
123}
124
125static int write_cipso2_rules(const char* srcdir) {
126 _cleanup_close_ int cipso2_fd = -1;
127 _cleanup_closedir_ DIR *dir = NULL;
128 struct dirent *entry;
129 char buf[NAME_MAX];
130 int dfd = -1;
131 int r = 0;
132
133 cipso2_fd = open("/sys/fs/smackfs/cipso2", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
134 if (cipso2_fd < 0) {
135 if (errno != ENOENT)
136 log_warning_errno(errno, "Failed to open '/sys/fs/smackfs/cipso2': %m");
137 return -errno; /* negative error */
138 }
139
140 /* write rules to cipso2 from every file in the directory */
141 dir = opendir(srcdir);
142 if (!dir) {
143 if (errno != ENOENT)
144 log_warning_errno(errno, "Failed to opendir '%s': %m", srcdir);
145 return errno; /* positive on purpose */
146 }
147
148 dfd = dirfd(dir);
149 assert(dfd >= 0);
150
151 FOREACH_DIRENT(entry, dir, return 0) {
152 int fd;
153 _cleanup_fclose_ FILE *policy = NULL;
154
155 if (!dirent_is_file(entry))
156 continue;
157
158 fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC);
159 if (fd < 0) {
160 if (r == 0)
161 r = -errno;
162 log_error_errno(errno, "Failed to open '%s': %m", entry->d_name);
163 continue;
164 }
165
166 policy = fdopen(fd, "re");
167 if (!policy) {
168 if (r == 0)
169 r = -errno;
170 safe_close(fd);
171 log_error_errno(errno, "Failed to open '%s': %m", entry->d_name);
172 continue;
173 }
174
175 /* cipso2 write rules in the kernel require a line buffered stream */
176 FOREACH_LINE(buf, policy,
177 log_error_errno(errno, "Failed to read line from '%s': %m",
178 entry->d_name)) {
179
180 if (isempty(truncate_nl(buf)))
181 continue;
182
183 if (write(cipso2_fd, buf, strlen(buf)) < 0) {
a4783bd1
ZJS
184 if (r == 0)
185 r = -errno;
6656aefb
WC
186 log_error_errno(errno, "Failed to write '%s' to '/sys/fs/smackfs/cipso2' in '%s'",
187 buf, entry->d_name);
a4783bd1
ZJS
188 break;
189 }
ffbd2c4d
NC
190 }
191 }
192
6656aefb 193 return r;
a4783bd1
ZJS
194}
195
2b3e18de 196#endif
ffbd2c4d 197
8a188de9 198int mac_smack_setup(bool *loaded_policy) {
2b3e18de
KL
199
200#ifdef HAVE_SMACK
201
a4783bd1
ZJS
202 int r;
203
e49d3c01
ŁS
204 assert(loaded_policy);
205
6656aefb 206 r = write_access2_rules("/etc/smack/accesses.d/");
a4783bd1
ZJS
207 switch(r) {
208 case -ENOENT:
209 log_debug("Smack is not enabled in the kernel.");
210 return 0;
211 case ENOENT:
6656aefb 212 log_debug("Smack access rules directory '/etc/smack/accesses.d/' not found");
a4783bd1
ZJS
213 return 0;
214 case 0:
215 log_info("Successfully loaded Smack policies.");
abbacb1d
NC
216 break;
217 default:
e53fc357 218 log_warning_errno(r, "Failed to load Smack access rules, ignoring: %m");
abbacb1d
NC
219 return 0;
220 }
221
8b197c3a 222#ifdef SMACK_RUN_LABEL
4c1fc3e4 223 r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, 0);
8b197c3a 224 if (r)
23446f01 225 log_warning_errno(r, "Failed to set SMACK label \"%s\" on self: %m", SMACK_RUN_LABEL);
8b197c3a
AK
226#endif
227
6656aefb 228 r = write_cipso2_rules("/etc/smack/cipso.d/");
abbacb1d
NC
229 switch(r) {
230 case -ENOENT:
231 log_debug("Smack/CIPSO is not enabled in the kernel.");
232 return 0;
233 case ENOENT:
6656aefb 234 log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found");
abbacb1d
NC
235 return 0;
236 case 0:
237 log_info("Successfully loaded Smack/CIPSO policies.");
b9289d4c 238 break;
a4783bd1 239 default:
e53fc357 240 log_warning_errno(r, "Failed to load Smack/CIPSO access rules, ignoring: %m");
a4783bd1
ZJS
241 return 0;
242 }
2b3e18de 243
e49d3c01
ŁS
244 *loaded_policy = true;
245
2b3e18de
KL
246#endif
247
248 return 0;
ffbd2c4d 249}