selinux-util.c revision cf0fbc49e67b55f8d346fc94de28c90113505297
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster/***
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster This file is part of systemd.
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster Copyright 2010 Lennart Poettering
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster systemd is free software; you can redistribute it and/or modify it
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster under the terms of the GNU Lesser General Public License as published by
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster the Free Software Foundation; either version 2.1 of the License, or
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster (at your option) any later version.
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster systemd is distributed in the hope that it will be useful, but
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster WITHOUT ANY WARRANTY; without even the implied warranty of
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster Lesser General Public License for more details.
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster You should have received a copy of the GNU Lesser General Public License
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster along with systemd; If not, see <http://www.gnu.org/licenses/>.
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster***/
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include <errno.h>
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include <malloc.h>
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include <sys/un.h>
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include <selinux/context.h>
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include <selinux/label.h>
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include <selinux/selinux.h>
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include "alloc-util.h"
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include "path-util.h"
b93185b577f7150fec37f9999b95b246d73bf63cjeff.schenk#include "selinux-util.h"
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#include "strv.h"
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan FosterDEFINE_TRIVIAL_CLEANUP_FUNC(security_context_t, freecon);
0a99555401a033704f1f171baab6db11fb5528f2Allan FosterDEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#define _cleanup_security_context_free_ _cleanup_(freeconp)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#define _cleanup_context_free_ _cleanup_(context_freep)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterstatic int cached_use = -1;
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterstatic struct selabel_handle *label_hnd = NULL;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterbool mac_selinux_use(void) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (cached_use < 0)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster cached_use = is_selinux_enabled() > 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return cached_use;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#else
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return false;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster}
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fostervoid mac_selinux_retest(void) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
b93185b577f7150fec37f9999b95b246d73bf63cjeff.schenk cached_use = -1;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster}
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterint mac_selinux_init(const char *prefix) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster int r = 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster usec_t before_timestamp, after_timestamp;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster struct mallinfo before_mallinfo, after_mallinfo;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!mac_selinux_use())
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (label_hnd)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster before_mallinfo = mallinfo();
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster before_timestamp = now(CLOCK_MONOTONIC);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (prefix) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster struct selinux_opt options[] = {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster { .type = SELABEL_OPT_SUBSET, .value = prefix },
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster };
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options));
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster } else
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!label_hnd) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster log_enforcing("Failed to initialize SELinux context: %m");
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = security_getenforce() == 1 ? -errno : 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster } else {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster char timespan[FORMAT_TIMESPAN_MAX];
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster int l;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster after_timestamp = now(CLOCK_MONOTONIC);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster after_mallinfo = mallinfo();
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster (l+1023)/1024);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster }
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return r;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster}
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fostervoid mac_selinux_finish(void) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!label_hnd)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster selabel_close(label_hnd);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster label_hnd = NULL;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster}
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterint mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster struct stat st;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster int r;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(path);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster /* if mac_selinux_init() wasn't called before we are a NOOP */
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!label_hnd)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = lstat(path, &st);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r >= 0) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster _cleanup_security_context_free_ security_context_t fcon = NULL;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster /* If there's no label to set, then exit without warning */
b93185b577f7150fec37f9999b95b246d73bf63cjeff.schenk if (r < 0 && errno == ENOENT)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r >= 0) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = lsetfilecon(path, fcon);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster /* If the FS doesn't support labels, then exit without warning */
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0 && errno == EOPNOTSUPP)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster }
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster }
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster /* Ignore ENOENT in some cases */
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (ignore_enoent && errno == ENOENT)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (ignore_erofs && errno == EROFS)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster log_enforcing("Unable to fix SELinux security context of %s: %m", path);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (security_getenforce() == 1)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -errno;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster }
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster}
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterint mac_selinux_apply(const char *path, const char *label) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!mac_selinux_use())
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(path);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(label);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (setfilecon(path, (security_context_t) label) < 0) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (security_getenforce() > 0)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -errno;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster }
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return 0;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster}
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterint mac_selinux_get_create_label_from_exe(const char *exe, char **label) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster int r = -EOPNOTSUPP;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster _cleanup_security_context_free_ security_context_t mycon = NULL, fcon = NULL;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster security_class_t sclass;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(exe);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(label);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!mac_selinux_use())
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -EOPNOTSUPP;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = getcon_raw(&mycon);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -errno;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = getfilecon_raw(exe, &fcon);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -errno;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster sclass = string_to_security_class("process");
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -errno;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
b93185b577f7150fec37f9999b95b246d73bf63cjeff.schenk return r;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster}
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterint mac_selinux_get_our_label(char **label) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster int r = -EOPNOTSUPP;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(label);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!mac_selinux_use())
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -EOPNOTSUPP;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = getcon_raw(label);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -errno;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#endif
b93185b577f7150fec37f9999b95b246d73bf63cjeff.schenk
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return r;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster}
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Fosterint mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster int r = -EOPNOTSUPP;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster#ifdef HAVE_SELINUX
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster _cleanup_security_context_free_ security_context_t mycon = NULL, peercon = NULL, fcon = NULL;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster _cleanup_context_free_ context_t pcon = NULL, bcon = NULL;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster security_class_t sclass;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster const char *range = NULL;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(socket_fd >= 0);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(exe);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster assert(label);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!mac_selinux_use())
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -EOPNOTSUPP;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = getcon_raw(&mycon);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -errno;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = getpeercon(socket_fd, &peercon);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0)
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster return -errno;
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (!exec_label) {
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster /* If there is no context set for next exec let's use context
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster of target executable */
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster r = getfilecon_raw(exe, &fcon);
0a99555401a033704f1f171baab6db11fb5528f2Allan Foster if (r < 0)
return -errno;
}
bcon = context_new(mycon);
if (!bcon)
return -ENOMEM;
pcon = context_new(peercon);
if (!pcon)
return -ENOMEM;
range = context_range_get(pcon);
if (!range)
return -errno;
r = context_range_set(bcon, range);
if (r)
return -errno;
freecon(mycon);
mycon = strdup(context_str(bcon));
if (!mycon)
return -ENOMEM;
sclass = string_to_security_class("process");
r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
if (r < 0)
return -errno;
#endif
return r;
}
char* mac_selinux_free(char *label) {
#ifdef HAVE_SELINUX
if (!label)
return NULL;
if (!mac_selinux_use())
return NULL;
freecon((security_context_t) label);
#endif
return NULL;
}
int mac_selinux_create_file_prepare(const char *path, mode_t mode) {
#ifdef HAVE_SELINUX
_cleanup_security_context_free_ security_context_t filecon = NULL;
int r;
assert(path);
if (!label_hnd)
return 0;
if (path_is_absolute(path))
r = selabel_lookup_raw(label_hnd, &filecon, path, mode);
else {
_cleanup_free_ char *newpath = NULL;
r = path_make_absolute_cwd(path, &newpath);
if (r < 0)
return r;
r = selabel_lookup_raw(label_hnd, &filecon, newpath, mode);
}
if (r < 0) {
/* No context specified by the policy? Proceed without setting it. */
if (errno == ENOENT)
return 0;
log_enforcing("Failed to determine SELinux security context for %s: %m", path);
} else {
if (setfscreatecon(filecon) >= 0)
return 0; /* Success! */
log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path);
}
if (security_getenforce() > 0)
return -errno;
#endif
return 0;
}
void mac_selinux_create_file_clear(void) {
#ifdef HAVE_SELINUX
PROTECT_ERRNO;
if (!mac_selinux_use())
return;
setfscreatecon(NULL);
#endif
}
int mac_selinux_create_socket_prepare(const char *label) {
#ifdef HAVE_SELINUX
if (!mac_selinux_use())
return 0;
assert(label);
if (setsockcreatecon((security_context_t) label) < 0) {
log_enforcing("Failed to set SELinux security context %s for sockets: %m", label);
if (security_getenforce() == 1)
return -errno;
}
#endif
return 0;
}
void mac_selinux_create_socket_clear(void) {
#ifdef HAVE_SELINUX
PROTECT_ERRNO;
if (!mac_selinux_use())
return;
setsockcreatecon(NULL);
#endif
}
int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
/* Binds a socket and label its file system object according to the SELinux policy */
#ifdef HAVE_SELINUX
_cleanup_security_context_free_ security_context_t fcon = NULL;
const struct sockaddr_un *un;
bool context_changed = false;
char *path;
int r;
assert(fd >= 0);
assert(addr);
assert(addrlen >= sizeof(sa_family_t));
if (!label_hnd)
goto skipped;
/* Filter out non-local sockets */
if (addr->sa_family != AF_UNIX)
goto skipped;
/* Filter out anonymous sockets */
if (addrlen < offsetof(struct sockaddr_un, sun_path) + 1)
goto skipped;
/* Filter out abstract namespace sockets */
un = (const struct sockaddr_un*) addr;
if (un->sun_path[0] == 0)
goto skipped;
path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path));
if (path_is_absolute(path))
r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK);
else {
_cleanup_free_ char *newpath = NULL;
r = path_make_absolute_cwd(path, &newpath);
if (r < 0)
return r;
r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK);
}
if (r < 0) {
/* No context specified by the policy? Proceed without setting it */
if (errno == ENOENT)
goto skipped;
log_enforcing("Failed to determine SELinux security context for %s: %m", path);
if (security_getenforce() > 0)
return -errno;
} else {
if (setfscreatecon(fcon) < 0) {
log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path);
if (security_getenforce() > 0)
return -errno;
} else
context_changed = true;
}
r = bind(fd, addr, addrlen) < 0 ? -errno : 0;
if (context_changed)
setfscreatecon(NULL);
return r;
skipped:
#endif
if (bind(fd, addr, addrlen) < 0)
return -errno;
return 0;
}