From 513a8d943538643fabf0d31f1eed261677dfbddc Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Fri, 8 Nov 2013 09:42:26 -0800 Subject: [PATCH] tizen-smack: Handling network - Set Smack ambient to match run label - Set Smack netlabel host rules Set Smack ambient to match run label ------------------------------------ Set the Smack networking ambient label to match the run label of systemd. System services may expect to communicate with external services over IP. Setting the ambient label assigns that label to IP packets that do not include CIPSO headers. This allows systemd and the services it spawns access to unlabeled IP packets, and hence external services. A system may choose to restrict network access to particular services later in the startup process. This is easily done by resetting the ambient label elsewhere. Set Smack netlabel host rules ----------------------------- If SMACK_RUN_LABEL is defined set all other hosts to be single label hosts at the specified label. Set the loopback address to be a CIPSO host. If any netlabel host rules are defined in /etc/smack/netlabel.d install them into the smackfs netlabel interface. [Patrick Ohly: adapt to write_string_file() change in "fileio: consolidate write_string_file*()"] [Patrick Ohly: create write_netlabel_rules() based on the original write_rules() that was removed in "smack: support smack access change-rule"] Upstream-Status: Pending --- src/core/smack-setup.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 3 deletions(-) diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c index cbe7d0b..b384aa0 100644 --- a/src/core/smack-setup.c +++ b/src/core/smack-setup.c @@ -34,6 +34,9 @@ #include "fileio.h" #include "log.h" +#define CIPSO_CONFIG "/etc/smack/cipso.d/" +#define NETLABEL_CONFIG "/etc/smack/netlabel.d/" + #ifdef HAVE_SMACK static int write_access2_rules(const char* srcdir) { @@ -193,6 +196,76 @@ static int write_cipso2_rules(const char* srcdir) { return r; } +static int write_netlabel_rules(const char* srcdir) { + _cleanup_fclose_ FILE *dst = NULL; + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *entry; + char buf[NAME_MAX]; + int dfd = -1; + int r = 0; + static const char dstpath[] = "/sys/fs/smackfs/netlabel"; + + dst = fopen(dstpath, "we"); + if (!dst) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to open %s: %m", dstpath); + return -errno; /* negative error */ + } + + /* write rules to dst from every file in the directory */ + dir = opendir(srcdir); + if (!dir) { + if (errno != ENOENT) + log_warning_errno(errno, "Failed to opendir %s: %m", srcdir); + return errno; /* positive on purpose */ + } + + dfd = dirfd(dir); + assert(dfd >= 0); + + FOREACH_DIRENT(entry, dir, return 0) { + int fd; + _cleanup_fclose_ FILE *policy = NULL; + + fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC); + if (fd < 0) { + if (r == 0) + r = -errno; + log_warning_errno(errno, "Failed to open %s: %m", entry->d_name); + continue; + } + + policy = fdopen(fd, "re"); + if (!policy) { + if (r == 0) + r = -errno; + safe_close(fd); + log_error_errno(errno, "Failed to open %s: %m", entry->d_name); + continue; + } + + /* load2 write rules in the kernel require a line buffered stream */ + FOREACH_LINE(buf, policy, + log_error_errno(errno, "Failed to read line from %s: %m", + entry->d_name)) { + if (!fputs(buf, dst)) { + if (r == 0) + r = -EINVAL; + log_error("Failed to write line to %s", dstpath); + break; + } + if (fflush(dst)) { + if (r == 0) + r = -errno; + log_error_errno(errno, "Failed to flush writes to %s: %m", dstpath); + break; + } + } + } + + return r; +} + #endif int mac_smack_setup(bool *loaded_policy) { @@ -225,23 +298,53 @@ int mac_smack_setup(bool *loaded_policy) { if (r) log_warning("Failed to set SMACK label \"%s\" on self: %s", SMACK_RUN_LABEL, strerror(-r)); + r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL, 0); + if (r) + log_warning("Failed to set SMACK ambient label \"%s\": %s", + SMACK_RUN_LABEL, strerror(-r)); + r = write_string_file("/sys/fs/smackfs/netlabel", + "0.0.0.0/0 " SMACK_RUN_LABEL, 0); + if (r) + log_warning("Failed to set SMACK netlabel rule \"%s\": %s", + "0.0.0.0/0 " SMACK_RUN_LABEL, strerror(-r)); + r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", 0); + if (r) + log_warning("Failed to set SMACK netlabel rule \"%s\": %s", + "127.0.0.1 -CIPSO", strerror(-r)); #endif - r = write_cipso2_rules("/etc/smack/cipso.d/"); + r = write_cipso2_rules(CIPSO_CONFIG); switch(r) { case -ENOENT: log_debug("Smack/CIPSO is not enabled in the kernel."); return 0; case ENOENT: - log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found"); - return 0; + log_debug("Smack/CIPSO access rules directory " CIPSO_CONFIG " not found"); + break; case 0: log_info("Successfully loaded Smack/CIPSO policies."); break; default: log_warning("Failed to load Smack/CIPSO access rules: %s, ignoring.", strerror(abs(r))); + break; + } + + r = write_netlabel_rules(NETLABEL_CONFIG); + switch(r) { + case -ENOENT: + log_debug("Smack/CIPSO is not enabled in the kernel."); return 0; + case ENOENT: + log_debug("Smack network host rules directory " NETLABEL_CONFIG " not found"); + break; + case 0: + log_info("Successfully loaded Smack network host rules."); + break; + default: + log_warning("Failed to load Smack network host rules: %s, ignoring.", + strerror(abs(r))); + break; } *loaded_policy = true; -- 2.1.4