]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
manager: add CoredumpFilter= setting
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 4 Apr 2020 14:43:25 +0000 (16:43 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 9 Apr 2020 12:08:48 +0000 (14:08 +0200)
Fixes #6685.

13 files changed:
docs/TRANSIENT-SETTINGS.md
man/systemd.exec.xml
src/core/dbus-execute.c
src/core/execute.c
src/core/execute.h
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/load-fragment.h
src/shared/bus-unit-util.c
src/shared/bus-util.c
src/shared/coredump-util.c
src/shared/coredump-util.h
test/fuzz/fuzz-unit-file/directives.service

index 271d8ab1e3d6d23670bac8a736f987e912b17c42..d5a80466769841be47e77e173875713c0bfdd927 100644 (file)
@@ -114,6 +114,7 @@ All execution-related settings are available for transient units.
 ✓ SupplementaryGroups=
 ✓ Nice=
 ✓ OOMScoreAdjust=
+✓ CoredumpFilter=
 ✓ IOSchedulingClass=
 ✓ IOSchedulingPriority=
 ✓ CPUSchedulingPolicy=
index 79a2c744c64fb15fdb9b05a986d6d89410099c20..073d331e6d94d39454567e843215bbc053ef78ec 100644 (file)
@@ -656,6 +656,32 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
         to 0022.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>CoredumpFilter=</varname></term>
+
+        <listitem><para>Controls which types of memory mappings will be saved if the process dumps core
+        (using the <filename>/proc/<replaceable>pid</replaceable>/coredump_filter</filename> file). Takes a
+        whitespace-separated combination of mapping type names or numbers (with the default base 16). Mapping
+        type names are <constant>private-anonymous</constant>, <constant>shared-anonymous</constant>,
+        <constant>private-file-backed</constant>, <constant>shared-file-backed</constant>,
+        <constant>elf-headers</constant>, <constant>private-huge</constant>,
+        <constant>shared-huge</constant>, <constant>private-dax</constant>, <constant>shared-dax</constant>,
+        and the special values <constant>all</constant> (all types) and <constant>default</constant> (the
+        kernel default of <literal><constant>private-anonymous</constant>
+        <constant>shared-anonymous</constant> <constant>elf-headers</constant>
+        <constant>private-huge</constant></literal>). See
+        <citerefentry><refentrytitle>core</refentrytitle><manvolnum>5</manvolnum></citerefentry> 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.</para>
+
+        <example>
+          <title>Add DAX pages to the dump filter</title>
+
+          <programlisting>CoredumpFilter=default private-dax shared-dax</programlisting>
+        </example>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>KeyringMode=</varname></term>
 
index e8be76e315c56c8e90dd4f025607d0211205893f..cedc026881464960f7666b84c152ce8d2941c0c5 100644 (file)
@@ -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;
index 8e1e77b4b2a5442c741943f978def1495ca85898..c59acad4ce65980f0d67accb108b3794f1836229 100644 (file)
@@ -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",
index 4baf5b1a405f942d7d00de64ab4a6eedd30b03a5..f96a2915eb75701f084a78ca40e93ab1870497c2 100644 (file)
@@ -14,6 +14,7 @@ typedef struct Manager Manager;
 #include <sys/capability.h>
 
 #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;
index 69abdb65ba704d018e37e8aa6afc32bf20ac6898..165b9ca9c12c260b67ae98c9d7a2c1ce93f16513 100644 (file)
@@ -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)
index 646364eb898788b843cc0e72cdbefd662bb12d33..b4d6c522e40178bdd2931b2e4f26ea790afaa7c7 100644 (file)
@@ -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,
index b6b46b2449b118f6cad5876de780871991c1e250..bc72ef77451fe65864170ecace32ac805d599723 100644 (file)
@@ -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);
index a30876c1a13f672dedc943c7923b11c2c9570e95..463a0ddb716086bb83eff8d235c127b33f7fb6f9 100644 (file)
@@ -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);
 
index 4b0a3a3e317e23863a37dbdcbf67309b8291f96a..ab6c257bf09479d574e33162012ce74e5fc46fbd 100644 (file)
@@ -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;
index 3fa866405196392950f256313fbb2c0906ccc7c9..67897414bc1978f7c099ea72189857d5081df412 100644 (file)
@@ -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);
+}
index f7fb5f18dbeac24ccf631d4483cf542b96a1d6f7..ff2e511bf17aea7a29e4b02253fc7b6f80b8d82c 100644 (file)
@@ -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);
index 45f8751971b9b199ced97758b187936a4284b5b7..98cddad3494addaaa333ee33d364c32894820309 100644 (file)
@@ -44,6 +44,7 @@ BlockIOWeight=
 BlockIOWriteBandwidth=
 Broadcast=
 BusName=
+CoredumpFilter=
 CPUAccounting=
 CPUQuota=
 CPUShares=