]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/smack-setup.c
816ac1ce74f300a809f94fda5ec38a59c6df98e4
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright (C) 2013 Intel Corporation
5 Nathaniel Chen <nathaniel.chen@intel.com>
12 #include <stdio_ext.h>
16 #include "alloc-util.h"
17 #include "dirent-util.h"
22 #include "smack-setup.h"
23 #include "string-util.h"
28 static int write_access2_rules(const char* srcdir
) {
29 _cleanup_close_
int load2_fd
= -1, change_fd
= -1;
30 _cleanup_closedir_
DIR *dir
= NULL
;
36 load2_fd
= open("/sys/fs/smackfs/load2", O_RDWR
|O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
);
39 log_warning_errno(errno
, "Failed to open '/sys/fs/smackfs/load2': %m");
40 return -errno
; /* negative error */
43 change_fd
= open("/sys/fs/smackfs/change-rule", O_RDWR
|O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
);
46 log_warning_errno(errno
, "Failed to open '/sys/fs/smackfs/change-rule': %m");
47 return -errno
; /* negative error */
50 /* write rules to load2 or change-rule from every file in the directory */
51 dir
= opendir(srcdir
);
54 log_warning_errno(errno
, "Failed to opendir '%s': %m", srcdir
);
55 return errno
; /* positive on purpose */
61 FOREACH_DIRENT(entry
, dir
, return 0) {
63 _cleanup_fclose_
FILE *policy
= NULL
;
65 if (!dirent_is_file(entry
))
68 fd
= openat(dfd
, entry
->d_name
, O_RDONLY
|O_CLOEXEC
);
72 log_warning_errno(errno
, "Failed to open '%s': %m", entry
->d_name
);
76 policy
= fdopen(fd
, "re");
81 log_error_errno(errno
, "Failed to open '%s': %m", entry
->d_name
);
85 /* load2 write rules in the kernel require a line buffered stream */
86 FOREACH_LINE(buf
, policy
,
87 log_error_errno(errno
, "Failed to read line from '%s': %m",
90 _cleanup_free_
char *sbj
= NULL
, *obj
= NULL
, *acc1
= NULL
, *acc2
= NULL
;
92 if (isempty(truncate_nl(buf
)) || strchr(COMMENTS
, *buf
))
95 /* if 3 args -> load rule : subject object access1 */
96 /* if 4 args -> change rule : subject object access1 access2 */
97 if (sscanf(buf
, "%ms %ms %ms %ms", &sbj
, &obj
, &acc1
, &acc2
) < 3) {
98 log_error_errno(errno
, "Failed to parse rule '%s' in '%s', ignoring.", buf
, entry
->d_name
);
102 if (write(isempty(acc2
) ? load2_fd
: change_fd
, buf
, strlen(buf
)) < 0) {
105 log_error_errno(errno
, "Failed to write '%s' to '%s' in '%s'",
106 buf
, isempty(acc2
) ? "/sys/fs/smackfs/load2" : "/sys/fs/smackfs/change-rule", entry
->d_name
);
114 static int write_cipso2_rules(const char* srcdir
) {
115 _cleanup_close_
int cipso2_fd
= -1;
116 _cleanup_closedir_
DIR *dir
= NULL
;
117 struct dirent
*entry
;
122 cipso2_fd
= open("/sys/fs/smackfs/cipso2", O_RDWR
|O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
);
125 log_warning_errno(errno
, "Failed to open '/sys/fs/smackfs/cipso2': %m");
126 return -errno
; /* negative error */
129 /* write rules to cipso2 from every file in the directory */
130 dir
= opendir(srcdir
);
133 log_warning_errno(errno
, "Failed to opendir '%s': %m", srcdir
);
134 return errno
; /* positive on purpose */
140 FOREACH_DIRENT(entry
, dir
, return 0) {
142 _cleanup_fclose_
FILE *policy
= NULL
;
144 if (!dirent_is_file(entry
))
147 fd
= openat(dfd
, entry
->d_name
, O_RDONLY
|O_CLOEXEC
);
151 log_error_errno(errno
, "Failed to open '%s': %m", entry
->d_name
);
155 policy
= fdopen(fd
, "re");
160 log_error_errno(errno
, "Failed to open '%s': %m", entry
->d_name
);
164 /* cipso2 write rules in the kernel require a line buffered stream */
165 FOREACH_LINE(buf
, policy
,
166 log_error_errno(errno
, "Failed to read line from '%s': %m",
169 if (isempty(truncate_nl(buf
)) || strchr(COMMENTS
, *buf
))
172 if (write(cipso2_fd
, buf
, strlen(buf
)) < 0) {
175 log_error_errno(errno
, "Failed to write '%s' to '/sys/fs/smackfs/cipso2' in '%s'",
185 static int write_netlabel_rules(const char* srcdir
) {
186 _cleanup_fclose_
FILE *dst
= NULL
;
187 _cleanup_closedir_
DIR *dir
= NULL
;
188 struct dirent
*entry
;
193 dst
= fopen("/sys/fs/smackfs/netlabel", "we");
196 log_warning_errno(errno
, "Failed to open /sys/fs/smackfs/netlabel: %m");
197 return -errno
; /* negative error */
200 /* write rules to dst from every file in the directory */
201 dir
= opendir(srcdir
);
204 log_warning_errno(errno
, "Failed to opendir %s: %m", srcdir
);
205 return errno
; /* positive on purpose */
211 FOREACH_DIRENT(entry
, dir
, return 0) {
213 _cleanup_fclose_
FILE *policy
= NULL
;
215 fd
= openat(dfd
, entry
->d_name
, O_RDONLY
|O_CLOEXEC
);
219 log_warning_errno(errno
, "Failed to open %s: %m", entry
->d_name
);
223 policy
= fdopen(fd
, "re");
228 log_error_errno(errno
, "Failed to open %s: %m", entry
->d_name
);
232 (void) __fsetlocking(policy
, FSETLOCKING_BYCALLER
);
234 /* load2 write rules in the kernel require a line buffered stream */
235 FOREACH_LINE(buf
, policy
,
236 log_error_errno(errno
, "Failed to read line from %s: %m", entry
->d_name
)) {
240 if (!fputs(buf
, dst
)) {
243 log_error_errno(errno
, "Failed to write line to /sys/fs/smackfs/netlabel");
246 q
= fflush_and_check(dst
);
250 log_error_errno(q
, "Failed to flush writes to /sys/fs/smackfs/netlabel: %m");
259 static int write_onlycap_list(void) {
260 _cleanup_close_
int onlycap_fd
= -1;
261 _cleanup_free_
char *list
= NULL
;
262 _cleanup_fclose_
FILE *f
= NULL
;
263 size_t len
= 0, allocated
= 0;
267 f
= fopen("/etc/smack/onlycap", "re");
270 log_warning_errno(errno
, "Failed to read '/etc/smack/onlycap'");
271 return errno
== ENOENT
? ENOENT
: -errno
;
274 FOREACH_LINE(buf
, f
, return -errno
) {
277 if (isempty(truncate_nl(buf
)) || strchr(COMMENTS
, *buf
))
281 if (!GREEDY_REALLOC(list
, allocated
, len
+ l
+ 1))
284 stpcpy(list
+ len
, buf
)[0] = ' ';
293 onlycap_fd
= open("/sys/fs/smackfs/onlycap", O_WRONLY
|O_CLOEXEC
|O_NONBLOCK
|O_NOCTTY
);
294 if (onlycap_fd
< 0) {
296 log_warning_errno(errno
, "Failed to open '/sys/fs/smackfs/onlycap'");
297 return -errno
; /* negative error */
300 r
= write(onlycap_fd
, list
, len
);
302 return log_error_errno(errno
, "Failed to write onlycap list(%s) to '/sys/fs/smackfs/onlycap'", list
);
309 int mac_smack_setup(bool *loaded_policy
) {
315 assert(loaded_policy
);
317 r
= write_access2_rules("/etc/smack/accesses.d/");
320 log_debug("Smack is not enabled in the kernel.");
323 log_debug("Smack access rules directory '/etc/smack/accesses.d/' not found");
326 log_info("Successfully loaded Smack policies.");
329 log_warning_errno(r
, "Failed to load Smack access rules, ignoring: %m");
333 #ifdef SMACK_RUN_LABEL
334 r
= write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL
, 0);
336 log_warning_errno(r
, "Failed to set SMACK label \"" SMACK_RUN_LABEL
"\" on self: %m");
337 r
= write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL
, 0);
339 log_warning_errno(r
, "Failed to set SMACK ambient label \"" SMACK_RUN_LABEL
"\": %m");
340 r
= write_string_file("/sys/fs/smackfs/netlabel",
341 "0.0.0.0/0 " SMACK_RUN_LABEL
, 0);
343 log_warning_errno(r
, "Failed to set SMACK netlabel rule \"0.0.0.0/0 " SMACK_RUN_LABEL
"\": %m");
344 r
= write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", 0);
346 log_warning_errno(r
, "Failed to set SMACK netlabel rule \"127.0.0.1 -CIPSO\": %m");
349 r
= write_cipso2_rules("/etc/smack/cipso.d/");
352 log_debug("Smack/CIPSO is not enabled in the kernel.");
355 log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found");
358 log_info("Successfully loaded Smack/CIPSO policies.");
361 log_warning_errno(r
, "Failed to load Smack/CIPSO access rules, ignoring: %m");
365 r
= write_netlabel_rules("/etc/smack/netlabel.d/");
368 log_debug("Smack/CIPSO is not enabled in the kernel.");
371 log_debug("Smack network host rules directory '/etc/smack/netlabel.d/' not found");
374 log_info("Successfully loaded Smack network host rules.");
377 log_warning_errno(r
, "Failed to load Smack network host rules: %m, ignoring.");
381 r
= write_onlycap_list();
384 log_debug("Smack is not enabled in the kernel.");
387 log_debug("Smack onlycap list file '/etc/smack/onlycap' not found");
390 log_info("Successfully wrote Smack onlycap list.");
393 log_emergency_errno(r
, "Failed to write Smack onlycap list.");
397 *loaded_policy
= true;