From: Nick Rosbrook Date: Fri, 29 Sep 2023 19:39:17 +0000 (-0400) Subject: core: add CoredumpReceive= setting X-Git-Tag: v255-rc1~231^2~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6cf96ab4568e39c534e6db6aa80a44fcf43b0c24;p=thirdparty%2Fsystemd.git core: add CoredumpReceive= setting This setting indicates that the given unit wants to receive coredumps for processes that crash within the cgroup of this unit. This setting requires that Delegate= is also true, and therefore is only available where Delegate= is available. This will be used by systemd-coredump to support forwarding coredumps to containers. --- diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 7df419d6076..f4012f1c61c 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -2287,6 +2287,18 @@ int cg_is_delegated(const char *path) { return r; } +int cg_has_coredump_receive(const char *path) { + int r; + + assert(path); + + r = cg_get_xattr_bool(path, "user.coredump_receive"); + if (ERRNO_IS_NEG_XATTR_ABSENT(r)) + return false; + + return r; +} + const uint64_t cgroup_io_limit_defaults[_CGROUP_IO_LIMIT_TYPE_MAX] = { [CGROUP_IO_RBPS_MAX] = CGROUP_LIMIT_MAX, [CGROUP_IO_WBPS_MAX] = CGROUP_LIMIT_MAX, diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 7e79735c3f2..04370b01ec3 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -212,6 +212,8 @@ int cg_is_threaded(const char *path); int cg_is_delegated(const char *path); +int cg_has_coredump_receive(const char *path); + typedef enum { CG_KEY_MODE_GRACEFUL = 1 << 0, } CGroupKeyMode; diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 47bab04f421..b17ca720141 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -526,7 +526,8 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { "%sManagedOOMMemoryPressure: %s\n" "%sManagedOOMMemoryPressureLimit: " PERMYRIAD_AS_PERCENT_FORMAT_STR "\n" "%sManagedOOMPreference: %s\n" - "%sMemoryPressureWatch: %s\n", + "%sMemoryPressureWatch: %s\n" + "%sCoredumpReceive: %s\n", prefix, yes_no(c->cpu_accounting), prefix, yes_no(c->io_accounting), prefix, yes_no(c->blockio_accounting), @@ -569,7 +570,8 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) { prefix, managed_oom_mode_to_string(c->moom_mem_pressure), prefix, PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(c->moom_mem_pressure_limit)), prefix, managed_oom_preference_to_string(c->moom_preference), - prefix, cgroup_pressure_watch_to_string(c->memory_pressure_watch)); + prefix, cgroup_pressure_watch_to_string(c->memory_pressure_watch), + prefix, yes_no(c->coredump_receive)); if (c->delegate_subgroup) fprintf(f, "%sDelegateSubgroup: %s\n", @@ -892,6 +894,21 @@ static void cgroup_invocation_id_xattr_apply(Unit *u) { } } +static void cgroup_coredump_xattr_apply(Unit *u) { + CGroupContext *c; + + assert(u); + + c = unit_get_cgroup_context(u); + if (!c) + return; + + if (unit_cgroup_delegate(u) && c->coredump_receive) + unit_set_xattr_graceful(u, "user.coredump_receive", "1", 1); + else + unit_remove_xattr_graceful(u, "user.coredump_receive"); +} + static void cgroup_delegate_xattr_apply(Unit *u) { bool b; @@ -952,6 +969,7 @@ static void cgroup_xattr_apply(Unit *u) { /* The 'user.*' xattrs can be set from a user manager. */ cgroup_oomd_xattr_apply(u); cgroup_log_xattr_apply(u); + cgroup_coredump_xattr_apply(u); if (!MANAGER_IS_SYSTEM(u->manager)) return; diff --git a/src/core/cgroup.h b/src/core/cgroup.h index 072c92f0117..7f456b99ee6 100644 --- a/src/core/cgroup.h +++ b/src/core/cgroup.h @@ -227,6 +227,10 @@ struct CGroupContext { * triggers, nor triggers for non-memory pressure. We might add that later. */ NFTSetContext nft_set_context; + + /* Forward coredumps for processes that crash within this cgroup. + * Requires 'delegate' to also be true. */ + bool coredump_receive; }; /* Used when querying IP accounting data */ diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index d38e8a6aeb4..e8c6a764e70 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -521,6 +521,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = { SD_BUS_PROPERTY("MemoryPressureWatch", "s", bus_property_get_cgroup_pressure_watch, offsetof(CGroupContext, memory_pressure_watch), 0), SD_BUS_PROPERTY("MemoryPressureThresholdUSec", "t", bus_property_get_usec, offsetof(CGroupContext, memory_pressure_threshold_usec), 0), SD_BUS_PROPERTY("NFTSet", "a(iiss)", property_get_cgroup_nft_set, 0, 0), + SD_BUS_PROPERTY("CoredumpReceive", "b", bus_property_get_bool, offsetof(CGroupContext, coredump_receive), 0), SD_BUS_VTABLE_END }; @@ -839,6 +840,23 @@ static int bus_cgroup_set_transient_property( unit_write_settingf(u, flags, name, "MemoryPressureThresholdUSec=%" PRIu64, t); } + return 1; + } else if (streq(name, "CoredumpReceive")) { + int b; + + if (!UNIT_VTABLE(u)->can_delegate) + return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type"); + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->coredump_receive = b; + + unit_write_settingf(u, flags, name, "CoredumpReceive=%s", yes_no(b)); + } + return 1; } diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in index 0ab468ba176..45f9ab03c4c 100644 --- a/src/core/load-fragment-gperf.gperf.in +++ b/src/core/load-fragment-gperf.gperf.in @@ -260,6 +260,7 @@ {{type}}.MemoryPressureThresholdSec, config_parse_sec, 0, offsetof({{type}}, cgroup_context.memory_pressure_threshold_usec) {{type}}.MemoryPressureWatch, config_parse_memory_pressure_watch, 0, offsetof({{type}}, cgroup_context.memory_pressure_watch) {{type}}.NFTSet, config_parse_cgroup_nft_set, NFT_SET_PARSE_CGROUP, offsetof({{type}}, cgroup_context) +{{type}}.CoredumpReceive, config_parse_bool, 0, offsetof({{type}}, cgroup_context.coredump_receive) {%- endmacro -%} %{ diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 634a8f08c29..4ee9706847d 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -565,7 +565,8 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons "IOAccounting", "BlockIOAccounting", "TasksAccounting", - "IPAccounting")) + "IPAccounting", + "CoredumpReceive")) return bus_append_parse_boolean(m, field, eq); if (STR_IN_SET(field, "CPUWeight",