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