mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 00:47:10 +09:00
libselinux: turn into dlopen() dep
This commit is contained in:
@@ -1154,6 +1154,7 @@ libselinux = dependency('libselinux',
|
||||
version : '>= 2.1.9',
|
||||
required : get_option('selinux'))
|
||||
conf.set10('HAVE_SELINUX', libselinux.found())
|
||||
libselinux_cflags = libselinux.partial_dependency(includes: true, compile_args: true)
|
||||
|
||||
libapparmor = dependency('libapparmor',
|
||||
version : '>= 2.13',
|
||||
|
||||
@@ -6111,7 +6111,7 @@ int exec_invoke(
|
||||
char *exec_context = mac_selinux_context_net ?: context->selinux_context;
|
||||
|
||||
if (exec_context) {
|
||||
r = setexeccon(exec_context);
|
||||
r = sym_setexeccon_raw(exec_context);
|
||||
if (r < 0) {
|
||||
if (!context->selinux_context_ignore) {
|
||||
*exit_status = EXIT_SELINUX_CONTEXT;
|
||||
|
||||
@@ -6124,7 +6124,7 @@ int unit_load_fragment(Unit *u) {
|
||||
_cleanup_freecon_ char *selcon = NULL;
|
||||
|
||||
/* Cache the SELinux context of the unit file here. We'll make use of when checking access permissions to loaded units */
|
||||
r = fgetfilecon_raw(fileno(f), &selcon);
|
||||
r = sym_fgetfilecon_raw(fileno(f), &selcon);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(u, r, "Failed to read SELinux context of '%s', ignoring: %m", fragment);
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ libcore_static = static_library(
|
||||
libmount_cflags,
|
||||
librt,
|
||||
libseccomp_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
threads,
|
||||
userspace],
|
||||
build_by_default : false)
|
||||
@@ -200,7 +200,7 @@ executables += [
|
||||
libapparmor_cflags,
|
||||
libkmod_cflags,
|
||||
libseccomp_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
],
|
||||
},
|
||||
libexec_template + {
|
||||
@@ -213,7 +213,7 @@ executables += [
|
||||
libapparmor_cflags,
|
||||
libpam_cflags,
|
||||
libseccomp_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
],
|
||||
},
|
||||
fuzz_template + {
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#if HAVE_SELINUX
|
||||
|
||||
#include <selinux/avc.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
@@ -153,7 +151,7 @@ static int access_init(sd_bus_error *error) {
|
||||
if (initialized)
|
||||
return 1;
|
||||
|
||||
if (avc_open(NULL, 0) != 0) {
|
||||
if (sym_avc_open(NULL, 0) != 0) {
|
||||
/* Passing errno to save original value for later */
|
||||
r = log_selinux_enforcing_errno(errno, "Failed to open the SELinux AVC: %m");
|
||||
if (r == 0)
|
||||
@@ -168,8 +166,8 @@ static int access_init(sd_bus_error *error) {
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to open the SELinux AVC: %m");
|
||||
}
|
||||
|
||||
selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) { .func_audit = audit_callback });
|
||||
selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) { .func_log = log_callback });
|
||||
sym_selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) { .func_audit = audit_callback });
|
||||
sym_selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) { .func_log = log_callback });
|
||||
|
||||
initialized = true;
|
||||
return 1;
|
||||
@@ -196,7 +194,7 @@ static int get_our_contexts(const Unit *unit, const char **ret_acon, const char
|
||||
* does exactly the same - call getcon_raw(). However, it involves
|
||||
* selinux_init() which opens label DB. It was not part of the
|
||||
* original code. I don't want to change it for now. */
|
||||
if (getcon_raw(&fcon) < 0)
|
||||
if (sym_getcon_raw(&fcon) < 0)
|
||||
return log_debug_errno(errno, "SELinux getcon_raw() failed: %m");
|
||||
|
||||
if (!fcon)
|
||||
@@ -226,7 +224,7 @@ static int check_access(
|
||||
assert(audit_info);
|
||||
assert(audit_info->function);
|
||||
|
||||
r = selinux_check_access(scon, tcon, tclass, permission, audit_info);
|
||||
r = sym_selinux_check_access(scon, tcon, tclass, permission, audit_info);
|
||||
if (r < 0) {
|
||||
errno = -(r = errno_or_else(EPERM));
|
||||
|
||||
@@ -357,7 +355,7 @@ int mac_selinux_access_check_varlink_internal(
|
||||
|
||||
/* We should call mac_selinux_get_peer_label() here similarly to get_our_contexts().
|
||||
* See the explanation there why not. */
|
||||
if (getpeercon_raw(fd, &scon) < 0)
|
||||
if (sym_getpeercon_raw(fd, &scon) < 0)
|
||||
return log_selinux_enforcing_errno(
|
||||
errno,
|
||||
"Failed to get peer SELinux context%s: %m",
|
||||
|
||||
@@ -18,13 +18,17 @@ int mac_selinux_setup(bool *loaded_policy) {
|
||||
#if HAVE_SELINUX
|
||||
int r;
|
||||
|
||||
r = dlopen_libselinux();
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "No SELinux library available, skipping setup: %m");
|
||||
|
||||
mac_selinux_disable_logging();
|
||||
|
||||
/* Don't load policy in the initrd if we don't appear to have it. For the real root, we check below
|
||||
* if we've already loaded policy, and return gracefully. */
|
||||
if (in_initrd() && access(selinux_path(), F_OK) < 0) {
|
||||
if (in_initrd() && access(sym_selinux_path(), F_OK) < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_warning_errno(errno, "Unable to check if %s exists, assuming it does not: %m", selinux_path());
|
||||
log_warning_errno(errno, "Unable to check if %s exists, assuming it does not: %m", sym_selinux_path());
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -37,7 +41,7 @@ int mac_selinux_setup(bool *loaded_policy) {
|
||||
* empty. SELinux guarantees this won't happen, but that file isn't specific to SELinux, and may be
|
||||
* provided by some other arbitrary LSM with different semantics. */
|
||||
_cleanup_freecon_ char *con = NULL;
|
||||
if (getcon_raw(&con) < 0)
|
||||
if (sym_getcon_raw(&con) < 0)
|
||||
log_debug_errno(errno, "getcon_raw() failed, assuming SELinux is not initialized: %m");
|
||||
else if (con) {
|
||||
initialized = !streq(con, "kernel");
|
||||
@@ -50,7 +54,7 @@ int mac_selinux_setup(bool *loaded_policy) {
|
||||
/* Now load the policy */
|
||||
usec_t before_load = now(CLOCK_MONOTONIC);
|
||||
int enforce = 0;
|
||||
if (selinux_init_load_policy(&enforce) == 0) { /* NB: Apparently doesn't set useful errno! */
|
||||
if (sym_selinux_init_load_policy(&enforce) == 0) { /* NB: Apparently doesn't set useful errno! */
|
||||
mac_selinux_retest();
|
||||
|
||||
/* Transition to the new context */
|
||||
@@ -60,7 +64,7 @@ int mac_selinux_setup(bool *loaded_policy) {
|
||||
log_open();
|
||||
log_warning_errno(r, "Failed to compute init label, ignoring: %m");
|
||||
} else {
|
||||
r = RET_NERRNO(setcon_raw(label));
|
||||
r = RET_NERRNO(sym_setcon_raw(label));
|
||||
log_open();
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to transition into init label '%s', ignoring: %m", label);
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#if HAVE_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -27,6 +23,7 @@
|
||||
#include "prioq.h"
|
||||
#include "process-util.h"
|
||||
#include "procfs-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
#include "syslog-util.h"
|
||||
@@ -257,6 +254,9 @@ static int client_context_read_label(
|
||||
assert(pid_is_valid(c->pid));
|
||||
assert(label_size == 0 || label);
|
||||
|
||||
if (!mac_selinux_use())
|
||||
return 0;
|
||||
|
||||
if (label_size > 0) {
|
||||
char *l;
|
||||
|
||||
@@ -275,7 +275,7 @@ static int client_context_read_label(
|
||||
|
||||
/* If we got no SELinux label passed in, let's try to acquire one */
|
||||
|
||||
if (getpidcon(c->pid, &con) >= 0 && con) {
|
||||
if (sym_getpidcon_raw(c->pid, &con) >= 0 && con) {
|
||||
free_and_replace(c->label, con);
|
||||
c->label_size = strlen(c->label);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ journal_test_template = test_template + {
|
||||
|
||||
journal_fuzz_template = fuzz_template + {
|
||||
'objects' : ['systemd-journald'],
|
||||
'dependencies' : libselinux,
|
||||
'dependencies' : libselinux_cflags,
|
||||
}
|
||||
|
||||
executables += [
|
||||
@@ -69,7 +69,7 @@ executables += [
|
||||
'extract' : systemd_journald_extract_sources,
|
||||
'dependencies' : [
|
||||
liblz4_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
libxz_cflags,
|
||||
libzstd_cflags,
|
||||
threads,
|
||||
@@ -87,7 +87,7 @@ executables += [
|
||||
'public' : true,
|
||||
'sources' : files('cat.c'),
|
||||
'objects' : ['systemd-journald'],
|
||||
'dependencies' : [libselinux, threads],
|
||||
'dependencies' : [threads],
|
||||
},
|
||||
executable_template + {
|
||||
'name' : 'journalctl',
|
||||
@@ -106,7 +106,7 @@ executables += [
|
||||
'sources' : files('test-journald-config.c'),
|
||||
'dependencies' : [
|
||||
liblz4_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
libxz_cflags,
|
||||
],
|
||||
},
|
||||
@@ -114,7 +114,7 @@ executables += [
|
||||
'sources' : files('test-journald-rate-limit.c'),
|
||||
'dependencies' : [
|
||||
liblz4_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
libxz_cflags,
|
||||
],
|
||||
},
|
||||
@@ -122,7 +122,7 @@ executables += [
|
||||
'sources' : files('test-journald-syslog.c'),
|
||||
'dependencies' : [
|
||||
liblz4_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
libxz_cflags,
|
||||
threads,
|
||||
],
|
||||
@@ -130,7 +130,7 @@ executables += [
|
||||
journal_test_template + {
|
||||
'sources' : files('test-journald-tables.c'),
|
||||
'dependencies' : [
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
],
|
||||
},
|
||||
journal_fuzz_template + {
|
||||
|
||||
@@ -48,7 +48,7 @@ executables += [
|
||||
'extract' : nspawn_extract_sources,
|
||||
'dependencies' : [
|
||||
libseccomp_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
],
|
||||
},
|
||||
nspawn_test_template + {
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if HAVE_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#endif
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-daemon.h"
|
||||
#include "sd-event.h"
|
||||
@@ -104,6 +100,7 @@
|
||||
#include "rm-rf.h"
|
||||
#include "runtime-scope.h"
|
||||
#include "seccomp-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "shift-uid.h"
|
||||
#include "signal-util.h"
|
||||
#include "siphash24.h"
|
||||
@@ -3532,8 +3529,8 @@ static int inner_child(
|
||||
}
|
||||
|
||||
#if HAVE_SELINUX
|
||||
if (arg_selinux_context)
|
||||
if (setexeccon(arg_selinux_context) < 0)
|
||||
if (arg_selinux_context && mac_selinux_use())
|
||||
if (sym_setexeccon_raw(arg_selinux_context) < 0)
|
||||
return log_error_errno(errno, "setexeccon(\"%s\") failed: %m", arg_selinux_context);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ executables += [
|
||||
'sources' : systemd_portabled_sources,
|
||||
'link_with' : portabled_link_with,
|
||||
'dependencies' : [
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
threads,
|
||||
],
|
||||
},
|
||||
|
||||
@@ -310,10 +310,11 @@ static int extract_now(
|
||||
#if HAVE_SELINUX
|
||||
/* The units will be copied on the host's filesystem, so if they had a SELinux label
|
||||
* we have to preserve it. Copy it out so that it can be applied later. */
|
||||
|
||||
r = fgetfilecon_raw(fd, &con);
|
||||
if (r < 0 && !ERRNO_IS_XATTR_ABSENT(errno))
|
||||
log_debug_errno(errno, "Failed to get SELinux file context from '%s', ignoring: %m", de->d_name);
|
||||
if (mac_selinux_use()) {
|
||||
r = sym_fgetfilecon_raw(fd, &con);
|
||||
if (r < 0 && !ERRNO_IS_XATTR_ABSENT(errno))
|
||||
log_debug_errno(errno, "Failed to get SELinux file context from '%s', ignoring: %m", de->d_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (socket_fd >= 0) {
|
||||
|
||||
@@ -328,7 +328,7 @@ libshared_deps = [threads,
|
||||
libpam_cflags,
|
||||
librt,
|
||||
libseccomp_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
libxenctrl_cflags,
|
||||
libxz_cflags,
|
||||
libzstd_cflags]
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "time-util.h"
|
||||
|
||||
#if HAVE_SELINUX
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(context_t, context_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(context_t, sym_context_free, context_freep, NULL);
|
||||
|
||||
typedef enum Initialized {
|
||||
UNINITIALIZED,
|
||||
@@ -49,12 +49,98 @@ static int mac_selinux_label_post(int dir_fd, const char *path, bool created) {
|
||||
mac_selinux_create_file_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *libselinux_dl = NULL;
|
||||
|
||||
DLSYM_PROTOTYPE(avc_open) = NULL;
|
||||
DLSYM_PROTOTYPE(context_free) = NULL;
|
||||
DLSYM_PROTOTYPE(context_new) = NULL;
|
||||
DLSYM_PROTOTYPE(context_range_get) = NULL;
|
||||
DLSYM_PROTOTYPE(context_range_set) = NULL;
|
||||
DLSYM_PROTOTYPE(context_str) = NULL;
|
||||
DLSYM_PROTOTYPE(fgetfilecon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(fini_selinuxmnt) = NULL;
|
||||
DLSYM_PROTOTYPE(freecon) = NULL;
|
||||
DLSYM_PROTOTYPE(getcon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(getfilecon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(getpeercon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(getpidcon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(is_selinux_enabled) = NULL;
|
||||
DLSYM_PROTOTYPE(security_compute_create_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(security_getenforce) = NULL;
|
||||
DLSYM_PROTOTYPE(selabel_close) = NULL;
|
||||
DLSYM_PROTOTYPE(selabel_lookup_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(selabel_open) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_check_access) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_getenforcemode) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_init_load_policy) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_path) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_set_callback) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_status_close) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_status_getenforce) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_status_open) = NULL;
|
||||
DLSYM_PROTOTYPE(selinux_status_policyload) = NULL;
|
||||
DLSYM_PROTOTYPE(setcon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(setexeccon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(setfilecon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(setfscreatecon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(setsockcreatecon_raw) = NULL;
|
||||
DLSYM_PROTOTYPE(string_to_security_class) = NULL;
|
||||
|
||||
int dlopen_libselinux(void) {
|
||||
ELF_NOTE_DLOPEN("selinux",
|
||||
"Support for SELinux",
|
||||
ELF_NOTE_DLOPEN_PRIORITY_RECOMMENDED,
|
||||
"libselinux.so.1");
|
||||
|
||||
return dlopen_many_sym_or_warn(
|
||||
&libselinux_dl,
|
||||
"libselinux.so.1",
|
||||
LOG_DEBUG,
|
||||
DLSYM_ARG(avc_open),
|
||||
DLSYM_ARG(context_free),
|
||||
DLSYM_ARG(context_new),
|
||||
DLSYM_ARG(context_range_get),
|
||||
DLSYM_ARG(context_range_set),
|
||||
DLSYM_ARG(context_str),
|
||||
DLSYM_ARG(fgetfilecon_raw),
|
||||
DLSYM_ARG(fini_selinuxmnt),
|
||||
DLSYM_ARG(freecon),
|
||||
DLSYM_ARG(getcon_raw),
|
||||
DLSYM_ARG(getfilecon_raw),
|
||||
DLSYM_ARG(getpeercon_raw),
|
||||
DLSYM_ARG(getpidcon_raw),
|
||||
DLSYM_ARG(is_selinux_enabled),
|
||||
DLSYM_ARG(security_compute_create_raw),
|
||||
DLSYM_ARG(security_getenforce),
|
||||
DLSYM_ARG(selabel_close),
|
||||
DLSYM_ARG(selabel_lookup_raw),
|
||||
DLSYM_ARG(selabel_open),
|
||||
DLSYM_ARG(selinux_check_access),
|
||||
DLSYM_ARG(selinux_getenforcemode),
|
||||
DLSYM_ARG(selinux_init_load_policy),
|
||||
DLSYM_ARG(selinux_path),
|
||||
DLSYM_ARG(selinux_set_callback),
|
||||
DLSYM_ARG(selinux_status_close),
|
||||
DLSYM_ARG(selinux_status_getenforce),
|
||||
DLSYM_ARG(selinux_status_open),
|
||||
DLSYM_ARG(selinux_status_policyload),
|
||||
DLSYM_ARG(setcon_raw),
|
||||
DLSYM_ARG(setexeccon_raw),
|
||||
DLSYM_ARG(setfilecon_raw),
|
||||
DLSYM_ARG(setfscreatecon_raw),
|
||||
DLSYM_ARG(setsockcreatecon_raw),
|
||||
DLSYM_ARG(string_to_security_class));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool mac_selinux_use(void) {
|
||||
#if HAVE_SELINUX
|
||||
if (_unlikely_(cached_use < 0)) {
|
||||
cached_use = is_selinux_enabled() > 0;
|
||||
if (dlopen_libselinux() < 0)
|
||||
return (cached_use = false);
|
||||
|
||||
cached_use = sym_is_selinux_enabled() > 0;
|
||||
log_trace("SELinux enabled state cached to: %s", enabled_disabled(cached_use));
|
||||
}
|
||||
|
||||
@@ -71,10 +157,13 @@ bool mac_selinux_enforcing(void) {
|
||||
/* If the SELinux status page has been successfully opened, retrieve the enforcing
|
||||
* status over it to avoid system calls in security_getenforce(). */
|
||||
|
||||
if (dlopen_libselinux() < 0)
|
||||
return false;
|
||||
|
||||
if (have_status_page)
|
||||
r = selinux_status_getenforce();
|
||||
r = sym_selinux_status_getenforce();
|
||||
else
|
||||
r = security_getenforce();
|
||||
r = sym_security_getenforce();
|
||||
|
||||
#endif
|
||||
return r != 0;
|
||||
@@ -92,13 +181,18 @@ static int open_label_db(void) {
|
||||
/* Avoid maybe-uninitialized false positives */
|
||||
usec_t before_timestamp = USEC_INFINITY, after_timestamp = USEC_INFINITY;
|
||||
struct mallinfo2 before_mallinfo = {};
|
||||
int r;
|
||||
|
||||
r = dlopen_libselinux();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (DEBUG_LOGGING) {
|
||||
before_mallinfo = mallinfo2();
|
||||
before_timestamp = now(CLOCK_MONOTONIC);
|
||||
}
|
||||
|
||||
hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
|
||||
hnd = sym_selabel_open(SELABEL_CTX_FILE, NULL, 0);
|
||||
if (!hnd)
|
||||
return log_selinux_enforcing_errno(errno, "Failed to initialize SELinux labeling handle: %m");
|
||||
|
||||
@@ -113,7 +207,7 @@ static int open_label_db(void) {
|
||||
|
||||
/* release memory after measurement */
|
||||
if (label_hnd)
|
||||
selabel_close(label_hnd);
|
||||
sym_selabel_close(label_hnd);
|
||||
label_hnd = TAKE_PTR(hnd);
|
||||
|
||||
return 0;
|
||||
@@ -142,7 +236,7 @@ static int selinux_init(bool force) {
|
||||
|
||||
mac_selinux_disable_logging();
|
||||
|
||||
r = selinux_status_open(/* netlink fallback= */ 1);
|
||||
r = sym_selinux_status_open(/* netlink fallback= */ 1);
|
||||
if (r < 0) {
|
||||
if (!ERRNO_IS_PRIVILEGE(errno))
|
||||
return log_selinux_enforcing_errno(errno, "Failed to open SELinux status page: %m");
|
||||
@@ -154,7 +248,7 @@ static int selinux_init(bool force) {
|
||||
|
||||
r = open_label_db();
|
||||
if (r < 0) {
|
||||
selinux_status_close();
|
||||
sym_selinux_status_close();
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -164,7 +258,7 @@ static int selinux_init(bool force) {
|
||||
|
||||
/* Save the current policyload sequence number, so mac_selinux_maybe_reload() does not trigger on
|
||||
* first call without any actual change. */
|
||||
last_policyload = selinux_status_policyload();
|
||||
last_policyload = sym_selinux_status_policyload();
|
||||
|
||||
initialized = INITIALIZED;
|
||||
return 1;
|
||||
@@ -203,6 +297,9 @@ void mac_selinux_maybe_reload(void) {
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
if (dlopen_libselinux() < 0)
|
||||
return;
|
||||
|
||||
/* Do not use selinux_status_updated(3), cause since libselinux 3.2 selinux_check_access(3),
|
||||
* called in core and user instances, does also use it under the hood.
|
||||
* That can cause changes to be consumed by selinux_check_access(3) and not being visible here.
|
||||
@@ -210,7 +307,7 @@ void mac_selinux_maybe_reload(void) {
|
||||
* invoked since libselinux 3.2 by selinux_status_updated(3).
|
||||
* Relevant libselinux commit: https://github.com/SELinuxProject/selinux/commit/05bdc03130d741e53e1fb45a958d0a2c184be503
|
||||
* Debian Bullseye is going to ship libselinux 3.1, so stay compatible for backports. */
|
||||
policyload = selinux_status_policyload();
|
||||
policyload = sym_selinux_status_policyload();
|
||||
if (policyload < 0) {
|
||||
log_debug_errno(errno, "Failed to get SELinux policyload from status page: %m");
|
||||
return;
|
||||
@@ -227,11 +324,13 @@ void mac_selinux_finish(void) {
|
||||
|
||||
#if HAVE_SELINUX
|
||||
if (label_hnd) {
|
||||
selabel_close(label_hnd);
|
||||
sym_selabel_close(label_hnd);
|
||||
label_hnd = NULL;
|
||||
}
|
||||
|
||||
selinux_status_close();
|
||||
if (sym_selinux_status_close)
|
||||
sym_selinux_status_close();
|
||||
|
||||
have_status_page = false;
|
||||
|
||||
initialized = false;
|
||||
@@ -248,7 +347,10 @@ static int selinux_log_glue(int type, const char *fmt, ...) {
|
||||
void mac_selinux_disable_logging(void) {
|
||||
#if HAVE_SELINUX
|
||||
/* Turn off all of SELinux' own logging, we want to do that ourselves */
|
||||
selinux_set_callback(SELINUX_CB_LOG, (const union selinux_callback) { .func_log = selinux_log_glue });
|
||||
if (dlopen_libselinux() < 0)
|
||||
return;
|
||||
|
||||
sym_selinux_set_callback(SELINUX_CB_LOG, (const union selinux_callback) { .func_log = selinux_log_glue });
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -274,7 +376,7 @@ static int selinux_fix_fd(
|
||||
if (!label_hnd)
|
||||
return 0;
|
||||
|
||||
if (selabel_lookup_raw(label_hnd, &fcon, label_path, st.st_mode) < 0) {
|
||||
if (sym_selabel_lookup_raw(label_hnd, &fcon, label_path, st.st_mode) < 0) {
|
||||
/* If there's no label to set, then exit without warning */
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
@@ -282,11 +384,8 @@ static int selinux_fix_fd(
|
||||
return log_selinux_enforcing_errno(errno, "Unable to lookup intended SELinux security context of %s: %m", label_path);
|
||||
}
|
||||
|
||||
if (setfilecon_raw(FORMAT_PROC_FD_PATH(fd), fcon) < 0) {
|
||||
_cleanup_freecon_ char *oldcon = NULL;
|
||||
|
||||
r = -errno;
|
||||
|
||||
r = RET_NERRNO(sym_setfilecon_raw(FORMAT_PROC_FD_PATH(fd), fcon));
|
||||
if (r < 0) {
|
||||
/* If the FS doesn't support labels, then exit without warning */
|
||||
if (ERRNO_IS_NOT_SUPPORTED(r))
|
||||
return 0;
|
||||
@@ -296,7 +395,8 @@ static int selinux_fix_fd(
|
||||
return 0;
|
||||
|
||||
/* If the old label is identical to the new one, suppress any kind of error */
|
||||
if (getfilecon_raw(FORMAT_PROC_FD_PATH(fd), &oldcon) >= 0 && streq_ptr(fcon, oldcon))
|
||||
_cleanup_freecon_ char *oldcon = NULL;
|
||||
if (sym_getfilecon_raw(FORMAT_PROC_FD_PATH(fd), &oldcon) >= 0 && streq_ptr(fcon, oldcon))
|
||||
return 0;
|
||||
|
||||
return log_selinux_enforcing_errno(r, "Unable to fix SELinux security context of %s: %m", label_path);
|
||||
@@ -371,7 +471,7 @@ int mac_selinux_apply(const char *path, const char *label) {
|
||||
|
||||
assert(label);
|
||||
|
||||
if (setfilecon(path, label) < 0)
|
||||
if (sym_setfilecon_raw(path, label) < 0)
|
||||
return log_selinux_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path);
|
||||
#endif
|
||||
return 0;
|
||||
@@ -390,7 +490,7 @@ int mac_selinux_apply_fd(int fd, const char *path, const char *label) {
|
||||
|
||||
assert(label);
|
||||
|
||||
if (setfilecon(FORMAT_PROC_FD_PATH(fd), label) < 0)
|
||||
if (sym_setfilecon_raw(FORMAT_PROC_FD_PATH(fd), label) < 0)
|
||||
return log_selinux_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, strna(path));
|
||||
#endif
|
||||
return 0;
|
||||
@@ -411,21 +511,21 @@ int mac_selinux_get_create_label_from_exe(const char *exe, char **ret_label) {
|
||||
if (r == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (getcon_raw(&mycon) < 0)
|
||||
if (sym_getcon_raw(&mycon) < 0)
|
||||
return -errno;
|
||||
if (!mycon)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (getfilecon_raw(exe, &fcon) < 0)
|
||||
if (sym_getfilecon_raw(exe, &fcon) < 0)
|
||||
return -errno;
|
||||
if (!fcon)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
sclass = string_to_security_class("process");
|
||||
sclass = sym_string_to_security_class("process");
|
||||
if (sclass == 0)
|
||||
return -ENOSYS;
|
||||
|
||||
return RET_NERRNO(security_compute_create_raw(mycon, fcon, sclass, ret_label));
|
||||
return RET_NERRNO(sym_security_compute_create_raw(mycon, fcon, sclass, ret_label));
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
@@ -444,7 +544,7 @@ int mac_selinux_get_our_label(char **ret_label) {
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
_cleanup_freecon_ char *con = NULL;
|
||||
if (getcon_raw(&con) < 0)
|
||||
if (sym_getcon_raw(&con) < 0)
|
||||
return -errno;
|
||||
if (!con)
|
||||
return -EOPNOTSUPP;
|
||||
@@ -470,7 +570,7 @@ int mac_selinux_get_peer_label(int socket_fd, char **ret_label) {
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
_cleanup_freecon_ char *con = NULL;
|
||||
if (getpeercon_raw(socket_fd, &con) < 0)
|
||||
if (sym_getpeercon_raw(socket_fd, &con) < 0)
|
||||
return -errno;
|
||||
if (!con)
|
||||
return -EOPNOTSUPP;
|
||||
@@ -500,47 +600,47 @@ int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *
|
||||
if (r == 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (getcon_raw(&mycon) < 0)
|
||||
if (sym_getcon_raw(&mycon) < 0)
|
||||
return -errno;
|
||||
if (!mycon)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (getpeercon_raw(socket_fd, &peercon) < 0)
|
||||
if (sym_getpeercon_raw(socket_fd, &peercon) < 0)
|
||||
return -errno;
|
||||
if (!peercon)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!exec_label) { /* If there is no context set for next exec let's use context of target executable */
|
||||
if (getfilecon_raw(exe, &fcon) < 0)
|
||||
if (sym_getfilecon_raw(exe, &fcon) < 0)
|
||||
return -errno;
|
||||
if (!fcon)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
bcon = context_new(mycon);
|
||||
bcon = sym_context_new(mycon);
|
||||
if (!bcon)
|
||||
return -ENOMEM;
|
||||
|
||||
pcon = context_new(peercon);
|
||||
pcon = sym_context_new(peercon);
|
||||
if (!pcon)
|
||||
return -ENOMEM;
|
||||
|
||||
range = context_range_get(pcon);
|
||||
range = sym_context_range_get(pcon);
|
||||
if (!range)
|
||||
return -errno;
|
||||
|
||||
if (context_range_set(bcon, range) != 0)
|
||||
if (sym_context_range_set(bcon, range) != 0)
|
||||
return -errno;
|
||||
|
||||
bcon_str = context_str(bcon);
|
||||
bcon_str = sym_context_str(bcon);
|
||||
if (!bcon_str)
|
||||
return -ENOMEM;
|
||||
|
||||
sclass = string_to_security_class("process");
|
||||
sclass = sym_string_to_security_class("process");
|
||||
if (sclass == 0)
|
||||
return -ENOSYS;
|
||||
|
||||
return RET_NERRNO(security_compute_create_raw(bcon_str, fcon, sclass, ret_label));
|
||||
return RET_NERRNO(sym_security_compute_create_raw(bcon_str, fcon, sclass, ret_label));
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
@@ -563,7 +663,7 @@ static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode)
|
||||
if (!label_hnd)
|
||||
return 0;
|
||||
|
||||
r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode);
|
||||
r = sym_selabel_lookup_raw(label_hnd, &filecon, abspath, mode);
|
||||
if (r < 0) {
|
||||
/* No context specified by the policy? Proceed without setting it. */
|
||||
if (errno == ENOENT)
|
||||
@@ -572,7 +672,7 @@ static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode)
|
||||
return log_selinux_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath);
|
||||
}
|
||||
|
||||
if (setfscreatecon_raw(filecon) < 0)
|
||||
if (sym_setfscreatecon_raw(filecon) < 0)
|
||||
return log_selinux_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath);
|
||||
|
||||
return 0;
|
||||
@@ -625,7 +725,7 @@ int mac_selinux_create_file_prepare_label(const char *path, const char *label) {
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (setfscreatecon_raw(label) < 0)
|
||||
if (sym_setfscreatecon_raw(label) < 0)
|
||||
return log_selinux_enforcing_errno(errno, "Failed to set specified SELinux security context '%s' for '%s': %m", label, strna(path));
|
||||
#endif
|
||||
return 0;
|
||||
@@ -639,7 +739,7 @@ void mac_selinux_create_file_clear(void) {
|
||||
if (selinux_init(/* force= */ false) <= 0)
|
||||
return;
|
||||
|
||||
setfscreatecon_raw(NULL);
|
||||
(void) sym_setfscreatecon_raw(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -654,7 +754,7 @@ int mac_selinux_create_socket_prepare(const char *label) {
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (setsockcreatecon(label) < 0)
|
||||
if (sym_setsockcreatecon_raw(label) < 0)
|
||||
return log_selinux_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label);
|
||||
#endif
|
||||
|
||||
@@ -669,7 +769,7 @@ void mac_selinux_create_socket_clear(void) {
|
||||
if (selinux_init(/* force= */ false) <= 0)
|
||||
return;
|
||||
|
||||
setsockcreatecon_raw(NULL);
|
||||
(void) sym_setsockcreatecon_raw(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -719,7 +819,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
goto skipped;
|
||||
|
||||
if (path_is_absolute(path))
|
||||
r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK);
|
||||
r = sym_selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK);
|
||||
else {
|
||||
_cleanup_free_ char *newpath = NULL;
|
||||
|
||||
@@ -727,7 +827,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK);
|
||||
r = sym_selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
@@ -739,7 +839,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
if (setfscreatecon_raw(fcon) < 0) {
|
||||
if (sym_setfscreatecon_raw(fcon) < 0) {
|
||||
r = log_selinux_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -750,7 +850,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
r = RET_NERRNO(bind(fd, addr, addrlen));
|
||||
|
||||
if (context_changed)
|
||||
(void) setfscreatecon_raw(NULL);
|
||||
(void) sym_setfscreatecon_raw(NULL);
|
||||
|
||||
return r;
|
||||
|
||||
|
||||
@@ -6,10 +6,58 @@
|
||||
#include "forward.h"
|
||||
|
||||
#if HAVE_SELINUX
|
||||
#include <selinux/avc.h>
|
||||
#include <selinux/label.h>
|
||||
#include <selinux/context.h>
|
||||
#include <selinux/selinux.h> /* IWYU pragma: export */
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(char*, freecon, NULL);
|
||||
#include "dlfcn-util.h"
|
||||
|
||||
int dlopen_libselinux(void);
|
||||
|
||||
extern DLSYM_PROTOTYPE(avc_open);
|
||||
extern DLSYM_PROTOTYPE(context_free);
|
||||
extern DLSYM_PROTOTYPE(context_new);
|
||||
extern DLSYM_PROTOTYPE(context_range_get);
|
||||
extern DLSYM_PROTOTYPE(context_range_set);
|
||||
extern DLSYM_PROTOTYPE(context_str);
|
||||
extern DLSYM_PROTOTYPE(fgetfilecon_raw);
|
||||
extern DLSYM_PROTOTYPE(fini_selinuxmnt);
|
||||
extern DLSYM_PROTOTYPE(freecon);
|
||||
extern DLSYM_PROTOTYPE(getcon_raw);
|
||||
extern DLSYM_PROTOTYPE(getfilecon_raw);
|
||||
extern DLSYM_PROTOTYPE(getpeercon_raw);
|
||||
extern DLSYM_PROTOTYPE(getpidcon_raw);
|
||||
extern DLSYM_PROTOTYPE(is_selinux_enabled);
|
||||
extern DLSYM_PROTOTYPE(security_compute_create_raw);
|
||||
extern DLSYM_PROTOTYPE(security_getenforce);
|
||||
extern DLSYM_PROTOTYPE(selabel_close);
|
||||
extern DLSYM_PROTOTYPE(selabel_lookup_raw);
|
||||
extern DLSYM_PROTOTYPE(selabel_open);
|
||||
extern DLSYM_PROTOTYPE(selinux_check_access);
|
||||
extern DLSYM_PROTOTYPE(selinux_getenforcemode);
|
||||
extern DLSYM_PROTOTYPE(selinux_init_load_policy);
|
||||
extern DLSYM_PROTOTYPE(selinux_path);
|
||||
extern DLSYM_PROTOTYPE(selinux_set_callback);
|
||||
extern DLSYM_PROTOTYPE(selinux_status_close);
|
||||
extern DLSYM_PROTOTYPE(selinux_status_getenforce);
|
||||
extern DLSYM_PROTOTYPE(selinux_status_open);
|
||||
extern DLSYM_PROTOTYPE(selinux_status_policyload);
|
||||
extern DLSYM_PROTOTYPE(setcon_raw);
|
||||
extern DLSYM_PROTOTYPE(setexeccon_raw);
|
||||
extern DLSYM_PROTOTYPE(setfilecon_raw);
|
||||
extern DLSYM_PROTOTYPE(setfscreatecon_raw);
|
||||
extern DLSYM_PROTOTYPE(setsockcreatecon_raw);
|
||||
extern DLSYM_PROTOTYPE(string_to_security_class);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL_RENAME(char*, sym_freecon, freeconp, NULL);
|
||||
|
||||
#else
|
||||
|
||||
static inline int dlopen_libselinux(void) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void freeconp(char **p) {
|
||||
assert(*p == NULL);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ executables += [
|
||||
'dependencies' : [
|
||||
libcap,
|
||||
liblz4_cflags,
|
||||
libselinux,
|
||||
libxz_cflags,
|
||||
libzstd_cflags,
|
||||
threads,
|
||||
|
||||
@@ -218,7 +218,7 @@ common_test_dependencies = [
|
||||
libmount_cflags,
|
||||
librt,
|
||||
libseccomp_cflags,
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
threads,
|
||||
]
|
||||
|
||||
@@ -432,7 +432,7 @@ executables += [
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-selinux.c'),
|
||||
'dependencies' : libselinux,
|
||||
'dependencies' : libselinux_cflags,
|
||||
},
|
||||
test_template + {
|
||||
'sources' : files('test-set-disable-mempool.c'),
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "pkcs11-util.h"
|
||||
#include "qrcode-util.h"
|
||||
#include "seccomp-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "tests.h"
|
||||
#include "tpm2-util.h"
|
||||
|
||||
@@ -60,6 +61,7 @@ static int run(int argc, char **argv) {
|
||||
ASSERT_DLOPEN(dlopen_libblkid, HAVE_BLKID);
|
||||
ASSERT_DLOPEN(dlopen_libseccomp, HAVE_SECCOMP);
|
||||
ASSERT_DLOPEN(dlopen_libmount, true);
|
||||
ASSERT_DLOPEN(dlopen_libselinux, HAVE_SELINUX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ executables += [
|
||||
udev_test_template + {
|
||||
'sources' : files('test-udev-rule-runner.c'),
|
||||
'dependencies' : udev_dependencies + [
|
||||
libselinux,
|
||||
libselinux_cflags,
|
||||
],
|
||||
'type' : 'manual',
|
||||
},
|
||||
|
||||
@@ -103,7 +103,8 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
/* Let's make sure the test runs with selinux assumed disabled. */
|
||||
#if HAVE_SELINUX
|
||||
fini_selinuxmnt();
|
||||
if (dlopen_libselinux() >= 0)
|
||||
sym_fini_selinuxmnt();
|
||||
#endif
|
||||
mac_selinux_retest();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user