commit
f58921bde3
|
@ -114,6 +114,7 @@ All execution-related settings are available for transient units.
|
|||
✓ SupplementaryGroups=
|
||||
✓ Nice=
|
||||
✓ OOMScoreAdjust=
|
||||
✓ CoredumpFilter=
|
||||
✓ IOSchedulingClass=
|
||||
✓ IOSchedulingPriority=
|
||||
✓ CPUSchedulingPolicy=
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -395,7 +395,7 @@ int safe_atoi(const char *s, int *ret_i) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) {
|
||||
char *x = NULL;
|
||||
unsigned long long l;
|
||||
|
||||
|
@ -404,7 +404,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
|||
s += strspn(s, WHITESPACE);
|
||||
|
||||
errno = 0;
|
||||
l = strtoull(s, &x, 0);
|
||||
l = strtoull(s, &x, base);
|
||||
if (errno > 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x != 0)
|
||||
|
|
|
@ -28,7 +28,6 @@ static inline int safe_atou(const char *s, unsigned *ret_u) {
|
|||
}
|
||||
|
||||
int safe_atoi(const char *s, int *ret_i);
|
||||
int safe_atollu(const char *s, unsigned long long *ret_u);
|
||||
int safe_atolli(const char *s, long long int *ret_i);
|
||||
|
||||
int safe_atou8(const char *s, uint8_t *ret);
|
||||
|
@ -59,6 +58,12 @@ static inline int safe_atoi32(const char *s, int32_t *ret_i) {
|
|||
return safe_atoi(s, (int*) ret_i);
|
||||
}
|
||||
|
||||
int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu);
|
||||
|
||||
static inline int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||
return safe_atollu_full(s, 0, ret_llu);
|
||||
}
|
||||
|
||||
static inline int safe_atou64(const char *s, uint64_t *ret_u) {
|
||||
assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
|
||||
return safe_atollu(s, (unsigned long long*) ret_u);
|
||||
|
@ -69,6 +74,11 @@ static inline int safe_atoi64(const char *s, int64_t *ret_i) {
|
|||
return safe_atolli(s, (long long int*) ret_i);
|
||||
}
|
||||
|
||||
static inline int safe_atoux64(const char *s, uint64_t *ret) {
|
||||
assert_cc(sizeof(int64_t) == sizeof(long long unsigned));
|
||||
return safe_atollu_full(s, 16, (long long unsigned*) ret);
|
||||
}
|
||||
|
||||
#if LONG_MAX == INT_MAX
|
||||
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
|
||||
assert_cc(sizeof(unsigned long) == sizeof(unsigned));
|
||||
|
|
|
@ -102,6 +102,7 @@ static int property_get_oom_score_adjust(
|
|||
|
||||
ExecContext *c = userdata;
|
||||
int32_t n;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
|
@ -113,13 +114,55 @@ static int property_get_oom_score_adjust(
|
|||
_cleanup_free_ char *t = NULL;
|
||||
|
||||
n = 0;
|
||||
if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
|
||||
safe_atoi32(t, &n);
|
||||
r = read_one_line_file("/proc/self/oom_score_adj", &t);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read /proc/self/oom_score_adj, ignoring: %m");
|
||||
else {
|
||||
r = safe_atoi32(t, &n);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse \"%s\" from /proc/self/oom_score_adj, ignoring: %m", t);
|
||||
}
|
||||
}
|
||||
|
||||
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 +790,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),
|
||||
|
@ -2190,6 +2234,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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -374,6 +374,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;
|
||||
|
|
74
src/shared/coredump-util.c
Normal file
74
src/shared/coredump-util.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#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] = {
|
||||
[COREDUMP_FILTER_PRIVATE_ANONYMOUS] = "private-anonymous",
|
||||
[COREDUMP_FILTER_SHARED_ANONYMOUS] = "shared-anonymous",
|
||||
[COREDUMP_FILTER_PRIVATE_FILE_BACKED] = "private-file-backed",
|
||||
[COREDUMP_FILTER_SHARED_FILE_BACKED] = "shared-file-backed",
|
||||
[COREDUMP_FILTER_ELF_HEADERS] = "elf-headers",
|
||||
[COREDUMP_FILTER_PRIVATE_HUGE] = "private-huge",
|
||||
[COREDUMP_FILTER_SHARED_HUGE] = "shared-huge",
|
||||
[COREDUMP_FILTER_PRIVATE_DAX] = "private-dax",
|
||||
[COREDUMP_FILTER_SHARED_DAX] = "shared-dax",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(coredump_filter, CoredumpFilter);
|
||||
|
||||
int coredump_filter_mask_from_string(const char *s, uint64_t *ret) {
|
||||
uint64_t m = 0;
|
||||
|
||||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
CoredumpFilter v;
|
||||
int r;
|
||||
|
||||
r = extract_first_word(&s, &n, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (streq(n, "default")) {
|
||||
m |= COREDUMP_FILTER_MASK_DEFAULT;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (streq(n, "all")) {
|
||||
m = UINT64_MAX;
|
||||
continue;
|
||||
}
|
||||
|
||||
v = coredump_filter_from_string(n);
|
||||
if (v >= 0) {
|
||||
m |= 1u << v;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t x;
|
||||
r = safe_atoux64(n, &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m |= x;
|
||||
}
|
||||
|
||||
*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);
|
||||
}
|
29
src/shared/coredump-util.h
Normal file
29
src/shared/coredump-util.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
typedef enum CoredumpFilter {
|
||||
COREDUMP_FILTER_PRIVATE_ANONYMOUS = 0,
|
||||
COREDUMP_FILTER_SHARED_ANONYMOUS,
|
||||
COREDUMP_FILTER_PRIVATE_FILE_BACKED,
|
||||
COREDUMP_FILTER_SHARED_FILE_BACKED,
|
||||
COREDUMP_FILTER_ELF_HEADERS,
|
||||
COREDUMP_FILTER_PRIVATE_HUGE,
|
||||
COREDUMP_FILTER_SHARED_HUGE,
|
||||
COREDUMP_FILTER_PRIVATE_DAX,
|
||||
COREDUMP_FILTER_SHARED_DAX,
|
||||
_COREDUMP_FILTER_MAX,
|
||||
_COREDUMP_FILTER_INVALID = -1,
|
||||
} CoredumpFilter;
|
||||
|
||||
#define COREDUMP_FILTER_MASK_DEFAULT (1u << COREDUMP_FILTER_PRIVATE_ANONYMOUS | \
|
||||
1u << COREDUMP_FILTER_SHARED_ANONYMOUS | \
|
||||
1u << COREDUMP_FILTER_ELF_HEADERS | \
|
||||
1u << COREDUMP_FILTER_PRIVATE_HUGE)
|
||||
|
||||
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);
|
|
@ -51,6 +51,8 @@ shared_sources = files('''
|
|||
condition.h
|
||||
conf-parser.c
|
||||
conf-parser.h
|
||||
coredump-util.c
|
||||
coredump-util.h
|
||||
cpu-set-util.c
|
||||
cpu-set-util.h
|
||||
crypt-util.c
|
||||
|
|
|
@ -588,6 +588,10 @@ tests += [
|
|||
[],
|
||||
[]],
|
||||
|
||||
[['src/test/test-coredump-util.c'],
|
||||
[],
|
||||
[]],
|
||||
|
||||
[['src/test/test-daemon.c'],
|
||||
[],
|
||||
[]],
|
||||
|
|
78
src/test/test-coredump-util.c
Normal file
78
src/test/test-coredump-util.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "coredump-util.h"
|
||||
#include "macro.h"
|
||||
#include "tests.h"
|
||||
|
||||
static void test_coredump_filter_to_from_string(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
for (CoredumpFilter i = 0; i < _COREDUMP_FILTER_MAX; i++) {
|
||||
const char *n;
|
||||
|
||||
assert_se(n = coredump_filter_to_string(i));
|
||||
log_info("0x%x\t%s", 1<<i, n);
|
||||
assert_se(coredump_filter_from_string(n) == i);
|
||||
|
||||
uint64_t f;
|
||||
assert_se(coredump_filter_mask_from_string(n, &f) == 0);
|
||||
assert_se(f == 1u << i);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_coredump_filter_mask_from_string(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
uint64_t f;
|
||||
assert_se(coredump_filter_mask_from_string("default", &f) == 0);
|
||||
assert_se(f == COREDUMP_FILTER_MASK_DEFAULT);
|
||||
|
||||
assert_se(coredump_filter_mask_from_string(" default\tdefault\tdefault ", &f) == 0);
|
||||
assert_se(f == COREDUMP_FILTER_MASK_DEFAULT);
|
||||
|
||||
assert_se(coredump_filter_mask_from_string("defaulta", &f) < 0);
|
||||
assert_se(coredump_filter_mask_from_string("default defaulta default", &f) < 0);
|
||||
assert_se(coredump_filter_mask_from_string("default default defaulta", &f) < 0);
|
||||
|
||||
assert_se(coredump_filter_mask_from_string("private-anonymous default", &f) == 0);
|
||||
assert_se(f == COREDUMP_FILTER_MASK_DEFAULT);
|
||||
|
||||
assert_se(coredump_filter_mask_from_string("shared-file-backed shared-dax", &f) == 0);
|
||||
assert_se(f == (1 << COREDUMP_FILTER_SHARED_FILE_BACKED |
|
||||
1 << COREDUMP_FILTER_SHARED_DAX));
|
||||
|
||||
assert_se(coredump_filter_mask_from_string("private-file-backed private-dax 0xF", &f) == 0);
|
||||
assert_se(f == (1 << COREDUMP_FILTER_PRIVATE_FILE_BACKED |
|
||||
1 << COREDUMP_FILTER_PRIVATE_DAX |
|
||||
0xF));
|
||||
|
||||
assert_se(coredump_filter_mask_from_string("11", &f) == 0);
|
||||
assert_se(f == 0x11);
|
||||
|
||||
assert_se(coredump_filter_mask_from_string("0x1101", &f) == 0);
|
||||
assert_se(f == 0x1101);
|
||||
|
||||
assert_se(coredump_filter_mask_from_string("0", &f) == 0);
|
||||
assert_se(f == 0);
|
||||
|
||||
assert_se(coredump_filter_mask_from_string("all", &f) == 0);
|
||||
assert_se(FLAGS_SET(f, (1 << COREDUMP_FILTER_PRIVATE_ANONYMOUS |
|
||||
1 << COREDUMP_FILTER_SHARED_ANONYMOUS |
|
||||
1 << COREDUMP_FILTER_PRIVATE_FILE_BACKED |
|
||||
1 << COREDUMP_FILTER_SHARED_FILE_BACKED |
|
||||
1 << COREDUMP_FILTER_ELF_HEADERS |
|
||||
1 << COREDUMP_FILTER_PRIVATE_HUGE |
|
||||
1 << COREDUMP_FILTER_SHARED_HUGE |
|
||||
1 << COREDUMP_FILTER_PRIVATE_DAX |
|
||||
1 << COREDUMP_FILTER_SHARED_DAX)));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
test_coredump_filter_to_from_string();
|
||||
test_coredump_filter_mask_from_string();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -561,6 +561,44 @@ static void test_safe_atoi64(void) {
|
|||
assert_se(r == -EINVAL);
|
||||
}
|
||||
|
||||
static void test_safe_atoux64(void) {
|
||||
int r;
|
||||
uint64_t l;
|
||||
|
||||
r = safe_atoux64("12345", &l);
|
||||
assert_se(r == 0);
|
||||
assert_se(l == 0x12345);
|
||||
|
||||
r = safe_atoux64(" 12345", &l);
|
||||
assert_se(r == 0);
|
||||
assert_se(l == 0x12345);
|
||||
|
||||
r = safe_atoux64("0x12345", &l);
|
||||
assert_se(r == 0);
|
||||
assert_se(l == 0x12345);
|
||||
|
||||
r = safe_atoux64("18446744073709551617", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
r = safe_atoux64("-1", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
r = safe_atoux64(" -1", &l);
|
||||
assert_se(r == -ERANGE);
|
||||
|
||||
r = safe_atoux64("junk", &l);
|
||||
assert_se(r == -EINVAL);
|
||||
|
||||
r = safe_atoux64("123x", &l);
|
||||
assert_se(r == -EINVAL);
|
||||
|
||||
r = safe_atoux64("12.3", &l);
|
||||
assert_se(r == -EINVAL);
|
||||
|
||||
r = safe_atoux64("", &l);
|
||||
assert_se(r == -EINVAL);
|
||||
}
|
||||
|
||||
static void test_safe_atod(void) {
|
||||
int r;
|
||||
double d;
|
||||
|
@ -838,6 +876,7 @@ int main(int argc, char *argv[]) {
|
|||
test_safe_atoux16();
|
||||
test_safe_atou64();
|
||||
test_safe_atoi64();
|
||||
test_safe_atoux64();
|
||||
test_safe_atod();
|
||||
test_parse_percent();
|
||||
test_parse_percent_unbounded();
|
||||
|
|
|
@ -44,6 +44,7 @@ BlockIOWeight=
|
|||
BlockIOWriteBandwidth=
|
||||
Broadcast=
|
||||
BusName=
|
||||
CoredumpFilter=
|
||||
CPUAccounting=
|
||||
CPUQuota=
|
||||
CPUShares=
|
||||
|
|
Loading…
Reference in a new issue