diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md index 271d8ab1e3..d5a8046676 100644 --- a/docs/TRANSIENT-SETTINGS.md +++ b/docs/TRANSIENT-SETTINGS.md @@ -114,6 +114,7 @@ All execution-related settings are available for transient units. ✓ SupplementaryGroups= ✓ Nice= ✓ OOMScoreAdjust= +✓ CoredumpFilter= ✓ IOSchedulingClass= ✓ IOSchedulingPriority= ✓ CPUSchedulingPolicy= diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 79a2c744c6..073d331e6d 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -656,6 +656,32 @@ CapabilityBoundingSet=~CAP_B CAP_C to 0022. + + CoredumpFilter= + + Controls which types of memory mappings will be saved if the process dumps core + (using the /proc/pid/coredump_filter file). Takes a + whitespace-separated combination of mapping type names or numbers (with the default base 16). Mapping + type names are private-anonymous, shared-anonymous, + private-file-backed, shared-file-backed, + elf-headers, private-huge, + shared-huge, private-dax, shared-dax, + and the special values all (all types) and default (the + kernel default of private-anonymous + shared-anonymous elf-headers + private-huge). See + core5 for the + meaning of the mapping types. When specified multiple times, all specified masks are ORed. When not + set, or if the empty value is assigned, the inherited value is not changed. + + + Add DAX pages to the dump filter + + CoredumpFilter=default private-dax shared-dax + + + + KeyringMode= diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index e8be76e315..cedc026881 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -120,6 +120,42 @@ static int property_get_oom_score_adjust( return sd_bus_message_append(reply, "i", n); } +static int property_get_coredump_filter( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + ExecContext *c = userdata; + uint64_t n; + int r; + + assert(bus); + assert(reply); + assert(c); + + if (c->coredump_filter_set) + n = c->coredump_filter; + else { + _cleanup_free_ char *t = NULL; + + n = COREDUMP_FILTER_MASK_DEFAULT; + r = read_one_line_file("/proc/self/coredump_filter", &t); + if (r < 0) + log_debug_errno(r, "Failed to read /proc/self/coredump_filter, ignoring: %m"); + else { + r = safe_atoux64(t, &n); + if (r < 0) + log_debug_errno(r, "Failed to parse \"%s\" from /proc/self/coredump_filter, ignoring: %m", t); + } + } + + return sd_bus_message_append(reply, "t", n); +} + static int property_get_nice( sd_bus *bus, const char *path, @@ -747,6 +783,7 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IOSchedulingClass", "i", property_get_ioprio_class, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IOSchedulingPriority", "i", property_get_ioprio_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST), @@ -2189,6 +2226,21 @@ int bus_exec_context_set_transient_property( return 1; + } else if (streq(name, "CoredumpFilter")) { + uint64_t f; + + r = sd_bus_message_read(message, "t", &f); + if (r < 0) + return r; + + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + c->coredump_filter = f; + c->coredump_filter_set = true; + unit_write_settingf(u, flags, name, "CoredumpFilter=0x%"PRIx64, f); + } + + return 1; + } else if (streq(name, "EnvironmentFiles")) { _cleanup_free_ char *joined = NULL; diff --git a/src/core/execute.c b/src/core/execute.c index 8e1e77b4b2..c59acad4ce 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3323,6 +3323,14 @@ static int exec_child( } } + if (context->coredump_filter_set) { + r = set_coredump_filter(context->coredump_filter); + if (ERRNO_IS_PRIVILEGE(r)) + log_unit_debug_errno(unit, r, "Failed to adjust coredump_filter, ignoring: %m"); + else if (r < 0) + return log_unit_error_errno(unit, r, "Failed to adjust coredump_filter: %m"); + } + if (context->nice_set) { r = setpriority_closest(context->nice); if (r < 0) @@ -4614,6 +4622,11 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { "%sOOMScoreAdjust: %i\n", prefix, c->oom_score_adjust); + if (c->coredump_filter_set) + fprintf(f, + "%sCoredumpFilter: 0x%"PRIx64"\n", + prefix, c->coredump_filter); + for (i = 0; i < RLIM_NLIMITS; i++) if (c->rlimit[i]) { fprintf(f, "%sLimit%s: " RLIM_FMT "\n", diff --git a/src/core/execute.h b/src/core/execute.h index 4baf5b1a40..f96a2915eb 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -14,6 +14,7 @@ typedef struct Manager Manager; #include #include "cgroup-util.h" +#include "coredump-util.h" #include "cpu-set-util.h" #include "exec-util.h" #include "fdset.h" @@ -161,6 +162,7 @@ struct ExecContext { bool working_directory_home:1; bool oom_score_adjust_set:1; + bool coredump_filter_set:1; bool nice_set:1; bool ioprio_set:1; bool cpu_sched_set:1; @@ -179,6 +181,7 @@ struct ExecContext { int ioprio; int cpu_sched_policy; int cpu_sched_priority; + uint64_t coredump_filter; CPUSet cpu_set; NUMAPolicy numa_policy; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 69abdb65ba..165b9ca9c1 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -28,6 +28,7 @@ $1.Group, config_parse_user_group_compat, 0, $1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups) $1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context) $1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context) +$1.CoredumpFilter, config_parse_exec_coredump_filter, 0, offsetof($1, exec_context) $1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context) $1.IOSchedulingPriority, config_parse_exec_io_priority, 0, offsetof($1, exec_context) $1.CPUSchedulingPolicy, config_parse_exec_cpu_sched_policy, 0, offsetof($1, exec_context) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 646364eb89..b4d6c522e4 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -592,6 +592,45 @@ int config_parse_exec_oom_score_adjust( return 0; } +int config_parse_exec_coredump_filter( + const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + ExecContext *c = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + if (isempty(rvalue)) { + c->coredump_filter = 0; + c->coredump_filter_set = false; + return 0; + } + + uint64_t f; + r = coredump_filter_mask_from_string(rvalue, &f); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse the CoredumpFilter=%s, ignoring: %m", rvalue); + return 0; + } + + c->coredump_filter |= f; + c->oom_score_adjust_set = true; + return 0; +} + int config_parse_exec( const char *unit, const char *filename, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index b6b46b2449..bc72ef7745 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -26,6 +26,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_socket_protocol); CONFIG_PARSER_PROTOTYPE(config_parse_socket_bind); CONFIG_PARSER_PROTOTYPE(config_parse_exec_nice); CONFIG_PARSER_PROTOTYPE(config_parse_exec_oom_score_adjust); +CONFIG_PARSER_PROTOTYPE(config_parse_exec_coredump_filter); CONFIG_PARSER_PROTOTYPE(config_parse_exec); CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout); CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_abort); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index a30876c1a1..463a0ddb71 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -8,6 +8,7 @@ #include "cgroup-setup.h" #include "cgroup-util.h" #include "condition.h" +#include "coredump-util.h" #include "cpu-set-util.h" #include "escape.h" #include "exec-util.h" @@ -119,6 +120,7 @@ DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, safe_atou64); DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, mode_t, parse_mode); DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou); DEFINE_BUS_APPEND_PARSE_PTR("x", int64_t, int64_t, safe_atoi64); +DEFINE_BUS_APPEND_PARSE_PTR("t", uint64_t, uint64_t, coredump_filter_mask_from_string); static int bus_append_string(sd_bus_message *m, const char *field, const char *eq) { int r; @@ -898,6 +900,9 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con "OOMScoreAdjust")) return bus_append_safe_atoi(m, field, eq); + if (streq(field, "CoredumpFilter")) + return bus_append_coredump_filter_mask_from_string(m, field, eq); + if (streq(field, "Nice")) return bus_append_parse_nice(m, field, eq); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 4b0a3a3e31..ab6c257bf0 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -373,6 +373,12 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b (void) format_timespan(timespan, sizeof(timespan), u, 0); bus_print_property_value(name, expected_value, value, timespan); + } else if (streq(name, "CoredumpFilter")) { + char buf[STRLEN("0xFFFFFFFF")]; + + xsprintf(buf, "0x%"PRIx64, u); + bus_print_property_value(name, expected_value, value, buf); + } else if (streq(name, "RestrictNamespaces")) { _cleanup_free_ char *s = NULL; const char *result; diff --git a/src/shared/coredump-util.c b/src/shared/coredump-util.c index 3fa8664051..67897414bc 100644 --- a/src/shared/coredump-util.c +++ b/src/shared/coredump-util.c @@ -2,6 +2,7 @@ #include "coredump-util.h" #include "extract-word.h" +#include "fileio.h" #include "string-table.h" static const char *const coredump_filter_table[_COREDUMP_FILTER_MAX] = { @@ -62,3 +63,12 @@ int coredump_filter_mask_from_string(const char *s, uint64_t *ret) { *ret = m; return 0; } + +int set_coredump_filter(uint64_t value) { + char t[STRLEN("0xFFFFFFFF")]; + + sprintf(t, "0x%"PRIx64, value); + + return write_string_file("/proc/self/coredump_filter", t, + WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER); +} diff --git a/src/shared/coredump-util.h b/src/shared/coredump-util.h index f7fb5f18db..ff2e511bf1 100644 --- a/src/shared/coredump-util.h +++ b/src/shared/coredump-util.h @@ -25,3 +25,5 @@ typedef enum CoredumpFilter { const char* coredump_filter_to_string(CoredumpFilter i) _const_; CoredumpFilter coredump_filter_from_string(const char *s) _pure_; int coredump_filter_mask_from_string(const char *s, uint64_t *ret); + +int set_coredump_filter(uint64_t value); diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service index 45f8751971..98cddad349 100644 --- a/test/fuzz/fuzz-unit-file/directives.service +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -44,6 +44,7 @@ BlockIOWeight= BlockIOWriteBandwidth= Broadcast= BusName= +CoredumpFilter= CPUAccounting= CPUQuota= CPUShares=