smack-setup.c revision a4783bd17ad96f55b0fe83a50959da13555292bf
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen/***
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen This file is part of systemd.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Copyright (C) 2013 Intel Corporation
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Authors:
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Nathaniel Chen <nathaniel.chen@intel.com>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen systemd is free software; you can redistribute it and/or modify it
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen under the terms of the GNU Lesser General Public License as published
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen by the Free Software Foundation; either version 2.1 of the License,
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen or (at your option) any later version.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen systemd is distributed in the hope that it will be useful, but
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen WITHOUT ANY WARRANTY; without even the implied warranty of
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen Lesser General Public License for more details.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen You should have received a copy of the GNU Lesser General Public License
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen along with systemd; If not, see <http://www.gnu.org/licenses/>.
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen***/
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <stdio.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <errno.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <string.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <unistd.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <stdlib.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <sys/vfs.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <fcntl.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <sys/types.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <dirent.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <sys/mount.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include <stdint.h>
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include "macro.h"
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include "smack-setup.h"
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include "util.h"
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include "log.h"
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen#include "label.h"
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek#define SMACK_CONFIG "/etc/smack/accesses.d/"
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmekstatic int write_rules(const char* dstpath, const char* srcdir) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *dst = NULL;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen _cleanup_closedir_ DIR *dir = NULL;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen struct dirent *entry;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen char buf[NAME_MAX];
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen int dfd = -1;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek int r = 0;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek dst = fopen(dstpath, "we");
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (!dst) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (errno != ENOENT)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_warning("Failed to open %s: %m", dstpath);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return -errno; /* negative error */
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen }
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek /* write rules to dst from every file in the directory */
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek dir = opendir(srcdir);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen if (!dir) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (errno != ENOENT)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_warning("Failed to opendir %s: %m", srcdir);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return errno; /* positive on purpose */
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen }
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen dfd = dirfd(dir);
fea7838e7e0b2724f5e0bc028121a08b42995045Zbigniew Jędrzejewski-Szmek assert(dfd >= 0);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen FOREACH_DIRENT(entry, dir, return 0) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek int fd;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen _cleanup_fclose_ FILE *policy = NULL;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (fd < 0) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (r == 0)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek r = -errno;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_warning("Failed to open %s: %m", entry->d_name);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen continue;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen }
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek policy = fdopen(fd, "re");
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen if (!policy) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (r == 0)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek r = -errno;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek close_nointr_nofail(fd);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_error("Failed to open %s: %m", entry->d_name);
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen continue;
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen }
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen /* load2 write rules in the kernel require a line buffered stream */
fea7838e7e0b2724f5e0bc028121a08b42995045Zbigniew Jędrzejewski-Szmek FOREACH_LINE(buf, policy,
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_error("Failed to read line from %s: %m",
fea7838e7e0b2724f5e0bc028121a08b42995045Zbigniew Jędrzejewski-Szmek entry->d_name)) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (!fputs(buf, dst)) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (r == 0)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek r = -EINVAL;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_error("Failed to write line to %s", dstpath);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek break;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek }
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (fflush(dst)) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek if (r == 0)
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek r = -errno;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_error("Failed to flush writes to %s: %m", dstpath);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek break;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek }
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen }
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen }
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return r;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek}
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmekint smack_setup(void) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek int r;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek r = write_rules("/sys/fs/smackfs/load2", SMACK_CONFIG);
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek switch(r) {
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek case -ENOENT:
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_debug("Smack is not enabled in the kernel.");
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return 0;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek case ENOENT:
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_debug("Smack access rules directory " SMACK_CONFIG " not found");
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return 0;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek case 0:
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_info("Successfully loaded Smack policies.");
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return 0;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek default:
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek log_warning("Failed to load smack access rules: %s, ignoring.",
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek strerror(abs(r)));
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek return 0;
a4783bd17ad96f55b0fe83a50959da13555292bfZbigniew Jędrzejewski-Szmek }
ffbd2c4d45787ba5ba85a32db6551efba66a1ee6Nathaniel Chen}