libselinux: turn into dlopen() dep

This commit is contained in:
Lennart Poettering
2025-09-08 18:31:49 +02:00
parent 26cde6f0ce
commit 83b6ef9b62
20 changed files with 248 additions and 97 deletions

View File

@@ -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',

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 + {

View File

@@ -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",

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 + {

View File

@@ -48,7 +48,7 @@ executables += [
'extract' : nspawn_extract_sources,
'dependencies' : [
libseccomp_cflags,
libselinux,
libselinux_cflags,
],
},
nspawn_test_template + {

View File

@@ -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

View File

@@ -29,7 +29,7 @@ executables += [
'sources' : systemd_portabled_sources,
'link_with' : portabled_link_with,
'dependencies' : [
libselinux,
libselinux_cflags,
threads,
],
},

View File

@@ -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) {

View File

@@ -328,7 +328,7 @@ libshared_deps = [threads,
libpam_cflags,
librt,
libseccomp_cflags,
libselinux,
libselinux_cflags,
libxenctrl_cflags,
libxz_cflags,
libzstd_cflags]

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -58,7 +58,6 @@ executables += [
'dependencies' : [
libcap,
liblz4_cflags,
libselinux,
libxz_cflags,
libzstd_cflags,
threads,

View File

@@ -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'),

View File

@@ -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;
}

View File

@@ -232,7 +232,7 @@ executables += [
udev_test_template + {
'sources' : files('test-udev-rule-runner.c'),
'dependencies' : udev_dependencies + [
libselinux,
libselinux_cflags,
],
'type' : 'manual',
},

View File

@@ -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();