1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-10 16:58:28 +03:00

Merge pull request #32447 from keszybz/test-taint

core: drop unused param, move taint calculation to separate file
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2024-04-24 18:09:57 +02:00 committed by GitHub
commit c2e6ed612a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 109 additions and 103 deletions

View File

@ -40,6 +40,7 @@
#include "string-util.h"
#include "strv.h"
#include "syslog-util.h"
#include "taint.h"
#include "user-util.h"
#include "version.h"
#include "virt.h"
@ -126,13 +127,10 @@ static int property_get_tainted(
void *userdata,
sd_bus_error *error) {
_cleanup_free_ char *s = NULL;
Manager *m = ASSERT_PTR(userdata);
assert(bus);
assert(reply);
s = manager_taint_string(m);
_cleanup_free_ char *s = taint_string();
if (!s)
return log_oom();

View File

@ -9,7 +9,6 @@
#include <sys/mount.h>
#include <sys/reboot.h>
#include <sys/timerfd.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
@ -90,6 +89,7 @@
#include "strxcpyx.h"
#include "sysctl-util.h"
#include "syslog-util.h"
#include "taint.h"
#include "terminal-util.h"
#include "time-util.h"
#include "transaction.h"
@ -3683,8 +3683,6 @@ bool manager_unit_inactive_or_pending(Manager *m, const char *name) {
}
static void log_taint_string(Manager *m) {
_cleanup_free_ char *taint = NULL;
assert(m);
if (MANAGER_IS_USER(m) || m->taint_logged)
@ -3692,7 +3690,7 @@ static void log_taint_string(Manager *m) {
m->taint_logged = true; /* only check for taint once */
taint = manager_taint_string(m);
_cleanup_free_ char *taint = taint_string();
if (isempty(taint))
return;
@ -4817,79 +4815,6 @@ static int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint
return 0;
}
static int short_uid_range(const char *path) {
_cleanup_(uid_range_freep) UIDRange *p = NULL;
int r;
assert(path);
/* Taint systemd if we the UID range assigned to this environment doesn't at least cover 0…65534,
* i.e. from root to nobody. */
r = uid_range_load_userns(path, UID_RANGE_USERNS_INSIDE, &p);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return false;
if (r < 0)
return log_debug_errno(r, "Failed to load %s: %m", path);
return !uid_range_covers(p, 0, 65535);
}
char* manager_taint_string(const Manager *m) {
const char *stage[12] = {};
size_t n = 0;
/* Returns a "taint string", e.g. "local-hwclock:var-run-bad". Only things that are detected at
* runtime should be tagged here. For stuff that is known during compilation, emit a warning in the
* configuration phase. */
assert(m);
_cleanup_free_ char *bin = NULL, *usr_sbin = NULL, *var_run = NULL;
if (readlink_malloc("/bin", &bin) < 0 || !PATH_IN_SET(bin, "usr/bin", "/usr/bin"))
stage[n++] = "unmerged-usr";
/* Note that the check is different from default_PATH(), as we want to taint on uncanonical symlinks
* too. */
if (readlink_malloc("/usr/sbin", &usr_sbin) < 0 || !PATH_IN_SET(usr_sbin, "bin", "/usr/bin"))
stage[n++] = "unmerged-bin";
if (readlink_malloc("/var/run", &var_run) < 0 || !PATH_IN_SET(var_run, "../run", "/run"))
stage[n++] = "var-run-bad";
if (cg_all_unified() == 0)
stage[n++] = "cgroupsv1";
if (clock_is_localtime(NULL) > 0)
stage[n++] = "local-hwclock";
if (os_release_support_ended(NULL, /* quiet= */ true, NULL) > 0)
stage[n++] = "support-ended";
struct utsname uts;
assert_se(uname(&uts) >= 0);
if (strverscmp_improved(uts.release, KERNEL_BASELINE_VERSION) < 0)
stage[n++] = "old-kernel";
_cleanup_free_ char *overflowuid = NULL, *overflowgid = NULL;
if (read_one_line_file("/proc/sys/kernel/overflowuid", &overflowuid) >= 0 &&
!streq(overflowuid, "65534"))
stage[n++] = "overflowuid-not-65534";
if (read_one_line_file("/proc/sys/kernel/overflowgid", &overflowgid) >= 0 &&
!streq(overflowgid, "65534"))
stage[n++] = "overflowgid-not-65534";
if (short_uid_range("/proc/self/uid_map") > 0)
stage[n++] = "short-uid-range";
if (short_uid_range("/proc/self/gid_map") > 0)
stage[n++] = "short-gid-range";
assert(n < ELEMENTSOF(stage) - 1); /* One extra for NULL terminator */
return strv_join((char**) stage, ":");
}
void manager_ref_console(Manager *m) {
assert(m);

View File

@ -616,8 +616,6 @@ int manager_ref_uid(Manager *m, uid_t uid, bool clean_ipc);
void manager_unref_gid(Manager *m, gid_t gid, bool destroy_now);
int manager_ref_gid(Manager *m, gid_t gid, bool clean_ipc);
char* manager_taint_string(const Manager *m);
void manager_ref_console(Manager *m);
void manager_unref_console(Manager *m);

View File

@ -61,6 +61,7 @@ libcore_sources = files(
'smack-setup.c',
'socket.c',
'swap.c',
'taint.c',
'target.c',
'timer.c',
'transaction.c',

85
src/core/taint.c Normal file
View File

@ -0,0 +1,85 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <sys/utsname.h>
#include "alloc-util.h"
#include "cgroup-util.h"
#include "clock-util.h"
#include "errno-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "log.h"
#include "os-util.h"
#include "path-util.h"
#include "strv.h"
#include "taint.h"
#include "uid-range.h"
static int short_uid_gid_range(UIDRangeUsernsMode mode) {
_cleanup_(uid_range_freep) UIDRange *p = NULL;
int r;
/* Taint systemd if we the UID/GID range assigned to this environment doesn't at least cover 0…65534,
* i.e. from root to nobody. */
r = uid_range_load_userns(/* path= */ NULL, mode, &p);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return false;
if (r < 0)
return log_debug_errno(r, "Failed to load uid_map or gid_map: %m");
return !uid_range_covers(p, 0, 65535);
}
char* taint_string(void) {
const char *stage[12] = {};
size_t n = 0;
/* Returns a "taint string", e.g. "local-hwclock:var-run-bad". Only things that are detected at
* runtime should be tagged here. For stuff that is known during compilation, emit a warning in the
* configuration phase. */
_cleanup_free_ char *bin = NULL, *usr_sbin = NULL, *var_run = NULL;
if (readlink_malloc("/bin", &bin) < 0 || !PATH_IN_SET(bin, "usr/bin", "/usr/bin"))
stage[n++] = "unmerged-usr";
/* Note that the check is different from default_PATH(), as we want to taint on uncanonical symlinks
* too. */
if (readlink_malloc("/usr/sbin", &usr_sbin) < 0 || !PATH_IN_SET(usr_sbin, "bin", "/usr/bin"))
stage[n++] = "unmerged-bin";
if (readlink_malloc("/var/run", &var_run) < 0 || !PATH_IN_SET(var_run, "../run", "/run"))
stage[n++] = "var-run-bad";
if (cg_all_unified() == 0)
stage[n++] = "cgroupsv1";
if (clock_is_localtime(NULL) > 0)
stage[n++] = "local-hwclock";
if (os_release_support_ended(NULL, /* quiet= */ true, NULL) > 0)
stage[n++] = "support-ended";
struct utsname uts;
assert_se(uname(&uts) >= 0);
if (strverscmp_improved(uts.release, KERNEL_BASELINE_VERSION) < 0)
stage[n++] = "old-kernel";
_cleanup_free_ char *overflowuid = NULL, *overflowgid = NULL;
if (read_one_line_file("/proc/sys/kernel/overflowuid", &overflowuid) >= 0 &&
!streq(overflowuid, "65534"))
stage[n++] = "overflowuid-not-65534";
if (read_one_line_file("/proc/sys/kernel/overflowgid", &overflowgid) >= 0 &&
!streq(overflowgid, "65534"))
stage[n++] = "overflowgid-not-65534";
if (short_uid_gid_range(UID_RANGE_USERNS_INSIDE) > 0)
stage[n++] = "short-uid-range";
if (short_uid_gid_range(GID_RANGE_USERNS_INSIDE) > 0)
stage[n++] = "short-gid-range";
assert(n < ELEMENTSOF(stage) - 1); /* One extra for NULL terminator */
return strv_join((char**) stage, ":");
}

4
src/core/taint.h Normal file
View File

@ -0,0 +1,4 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
char* taint_string(void);

View File

@ -535,7 +535,7 @@ executables += [
'parallel' : false,
},
core_test_template + {
'sources' : files('test-manager.c'),
'sources' : files('test-taint.c'),
},
core_test_template + {
'sources' : files('test-namespace.c'),

View File

@ -1,19 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "manager.h"
#include "tests.h"
TEST(manager_taint_string) {
Manager m = {};
_cleanup_free_ char *a = manager_taint_string(&m);
assert_se(a);
log_debug("taint string: '%s'", a);
if (cg_all_unified() == 0)
assert_se(strstr(a, "cgroupsv1"));
else
assert_se(!strstr(a, "cgroupsv1"));
}
DEFINE_TEST_MAIN(LOG_DEBUG);

14
src/test/test-taint.c Normal file
View File

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "taint.h"
#include "tests.h"
TEST(taint_string) {
_cleanup_free_ char *a = taint_string();
assert_se(a);
log_debug("taint string: '%s'", a);
assert_se(!!strstr(a, "cgroupsv1") == (cg_all_unified() == 0));
}
DEFINE_TEST_MAIN(LOG_DEBUG);