1
0
mirror of https://github.com/systemd/systemd synced 2026-04-24 07:55:12 +02:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Lennart Poettering
45bff9b4e2 systemctl: show tainted state 2022-03-31 22:11:32 +01:00
Lennart Poettering
40efaaed42 pid1: check for kernels older than baseline
Let's make this detectable explicitly.
2022-03-31 22:11:20 +01:00
Luca Boccassi
58270534bf
Merge pull request #22923 from poettering/userns-check-refactor
virt: minor running_in_userns() modernizations
2022-03-31 22:11:03 +01:00
Lennart Poettering
16fa47463c virt: use read_virtual_file() for reading /proc/self/setgroups 2022-03-31 16:34:41 +02:00
Lennart Poettering
b2a331f2e0 virt: simplify userns_has_mapping() by using fscanf() instead of scanf()
And while we are at it, also fix propagation of an uninitialized errno
error.
2022-03-31 16:34:41 +02:00
7 changed files with 61 additions and 32 deletions

View File

@ -73,3 +73,5 @@
#define VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM "/run/systemd/io.system.ManagedOOM"
/* Path where systemd-oomd listens for varlink connections from user managers to report changes in ManagedOOM settings. */
#define VARLINK_ADDR_PATH_MANAGED_OOM_USER "/run/systemd/oom/io.system.ManagedOOM"
#define KERNEL_BASELINE_VERSION "3.15"

View File

@ -12,6 +12,7 @@
#include "cgroup-util.h"
#include "dirent-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "macro.h"
@ -791,10 +792,7 @@ int detect_virtualization(void) {
static int userns_has_mapping(const char *name) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *buf = NULL;
size_t n_allocated = 0;
ssize_t n;
uint32_t a, b, c;
uid_t a, b, c;
int r;
f = fopen(name, "re");
@ -803,19 +801,17 @@ static int userns_has_mapping(const char *name) {
return errno == ENOENT ? false : -errno;
}
n = getline(&buf, &n_allocated, f);
if (n < 0) {
if (feof(f)) {
log_debug("%s is empty, we're in an uninitialized user namespace", name);
return true;
}
errno = 0;
r = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT "\n", &a, &b, &c);
if (r == EOF) {
if (ferror(f))
return log_debug_errno(errno_or_else(EIO), "Failed to read %s: %m", name);
return log_debug_errno(errno, "Failed to read %s: %m", name);
log_debug("%s is empty, we're in an uninitialized user namespace", name);
return true;
}
r = sscanf(buf, "%"PRIu32" %"PRIu32" %"PRIu32, &a, &b, &c);
if (r < 3)
return log_debug_errno(errno, "Failed to parse %s: %m", name);
if (r != 3)
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Failed to parse %s: %m", name);
if (a == 0 && b == 0 && c == UINT32_MAX) {
/* The kernel calls mappings_overlap() and does not allow overlaps */
@ -840,19 +836,18 @@ int running_in_userns(void) {
if (r != 0)
return r;
/* "setgroups" file was added in kernel v3.18-rc6-15-g9cc46516dd. It is also
* possible to compile a kernel without CONFIG_USER_NS, in which case "setgroups"
* also does not exist. We cannot distinguish those two cases, so assume that
* we're running on a stripped-down recent kernel, rather than on an old one,
* and if the file is not found, return false.
*/
r = read_one_line_file("/proc/self/setgroups", &line);
/* "setgroups" file was added in kernel v3.18-rc6-15-g9cc46516dd. It is also possible to compile a
* kernel without CONFIG_USER_NS, in which case "setgroups" also does not exist. We cannot
* distinguish those two cases, so assume that we're running on a stripped-down recent kernel, rather
* than on an old one, and if the file is not found, return false. */
r = read_virtual_file("/proc/self/setgroups", SIZE_MAX, &line, NULL);
if (r < 0) {
log_debug_errno(r, "/proc/self/setgroups: %m");
return r == -ENOENT ? false : r;
}
truncate_nl(line);
strstrip(line); /* remove trailing newline */
r = streq(line, "deny");
/* See user_namespaces(7) for a description of this "setgroups" contents. */
log_debug("/proc/self/setgroups contains \"%s\", %s user namespace", line, r ? "in" : "not in");

View File

@ -6,6 +6,7 @@
#include <linux/oom.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/utsname.h>
#include <unistd.h>
#if HAVE_SECCOMP
#include <seccomp.h>
@ -2009,6 +2010,7 @@ static void log_execution_mode(bool *ret_first_boot) {
assert(ret_first_boot);
if (arg_system) {
struct utsname uts;
int v;
log_info("systemd " GIT_VERSION " running in %ssystem mode (%s)",
@ -2046,6 +2048,14 @@ static void log_execution_mode(bool *ret_first_boot) {
log_debug("Detected initialized system, this is not the first boot.");
}
}
assert(uname(&uts) >= 0);
if (strverscmp_improved(uts.release, KERNEL_BASELINE_VERSION) < 0)
log_warning("Warning! Reported kernel version %s is older than systemd's required baseline kernel version %s. "
"Your mileage may vary.", uts.release, KERNEL_BASELINE_VERSION);
else
log_debug("Kernel version %s, our baseline is %s", uts.release, KERNEL_BASELINE_VERSION);
} else {
if (DEBUG_LOGGING) {
_cleanup_free_ char *t = NULL;

View File

@ -8,6 +8,7 @@
#include <sys/ioctl.h>
#include <sys/reboot.h>
#include <sys/timerfd.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
@ -4351,6 +4352,7 @@ int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t re
char *manager_taint_string(Manager *m) {
_cleanup_free_ char *destination = NULL, *overflowuid = NULL, *overflowgid = NULL;
struct utsname uts;
char *buf, *e;
int r;
@ -4367,7 +4369,8 @@ char *manager_taint_string(Manager *m) {
"local-hwclock:"
"var-run-bad:"
"overflowuid-not-65534:"
"overflowgid-not-65534:"));
"overflowgid-not-65534:"
"old-kernel:"));
if (!buf)
return NULL;
@ -4398,6 +4401,10 @@ char *manager_taint_string(Manager *m) {
if (r >= 0 && !streq(overflowgid, "65534"))
e = stpcpy(e, "overflowgid-not-65534:");
assert_se(uname(&uts) >= 0);
if (strverscmp_improved(uts.release, KERNEL_BASELINE_VERSION) < 0)
e = stpcpy(e, "old-kernel:");
/* remove the last ':' */
if (e != buf)
e[-1] = 0;

View File

@ -15,11 +15,15 @@
#include "terminal-util.h"
const struct bus_properties_map machine_info_property_map[] = {
{ "SystemState", "s", NULL, offsetof(struct machine_info, state) },
{ "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
{ "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
{ "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
/* Might good to keep same order here as in bus_manager_vtable[], server side */
{ "Version", "s", NULL, offsetof(struct machine_info, version) },
{ "Tainted", "s", NULL, offsetof(struct machine_info, tainted) },
{ "UserspaceTimestamp", "t", NULL, offsetof(struct machine_info, timestamp) },
{ "NNames", "u", NULL, offsetof(struct machine_info, n_names) },
{ "NFailedUnits", "u", NULL, offsetof(struct machine_info, n_failed_units) },
{ "NJobs", "u", NULL, offsetof(struct machine_info, n_jobs) },
{ "ControlGroup", "s", NULL, offsetof(struct machine_info, control_group) },
{ "SystemState", "s", NULL, offsetof(struct machine_info, state) },
{}
};
@ -27,8 +31,10 @@ void machine_info_clear(struct machine_info *info) {
assert(info);
free(info->name);
free(info->state);
free(info->version);
free(info->tainted);
free(info->control_group);
free(info->state);
zero(*info);
}

View File

@ -12,11 +12,14 @@ int verb_list_machines(int argc, char *argv[], void *userdata);
struct machine_info {
bool is_host;
char *name;
char *state;
char *control_group;
char *version;
char *tainted;
uint64_t timestamp;
uint32_t n_names;
uint32_t n_failed_units;
uint32_t n_jobs;
usec_t timestamp;
char *control_group;
char *state;
};
void machine_info_clear(struct machine_info *info);

View File

@ -2129,6 +2129,7 @@ static int show_system_status(sd_bus *bus) {
printf(" State: %s%s%s\n",
on, strna(mi.state), off);
printf(" Units: %" PRIu32 " loaded (incl. loaded aliases)\n", mi.n_names);
printf(" Jobs: %" PRIu32 " queued\n", mi.n_jobs);
printf(" Failed: %" PRIu32 " units\n", mi.n_failed_units);
@ -2136,6 +2137,11 @@ static int show_system_status(sd_bus *bus) {
FORMAT_TIMESTAMP_STYLE(mi.timestamp, arg_timestamp_style),
FORMAT_TIMESTAMP_RELATIVE(mi.timestamp));
printf(" systemd: %s\n", mi.version);
if (!isempty(mi.tainted))
printf(" Tainted: %s%s%s\n", ansi_highlight_yellow(), mi.tainted, ansi_normal());
printf(" CGroup: %s\n", empty_to_root(mi.control_group));
c = LESS_BY(columns(), strlen(prefix));