Compare commits
22 Commits
876acda0ed
...
611cb82612
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 611cb82612 | |
Lennart Poettering | f58921bde3 | |
Jian-Hong Pan | e58cd39f63 | |
Franck Bui | 5e37d1930b | |
Zbigniew Jędrzejewski-Szmek | b94fb74bae | |
Zbigniew Jędrzejewski-Szmek | ad21e542b2 | |
Lennart Poettering | 4d1f2c621f | |
Zbigniew Jędrzejewski-Szmek | b34612bd5a | |
Luca Boccassi | a1db42eb0b | |
Luca Boccassi | fe78538cab | |
Zbigniew Jędrzejewski-Szmek | ce51632a35 | |
Lennart Poettering | 0ed4b54e05 | |
Zbigniew Jędrzejewski-Szmek | 302dc5b913 | |
Wen Yang | f74349d88b | |
Zbigniew Jędrzejewski-Szmek | 241c4b6ada | |
Zbigniew Jędrzejewski-Szmek | 2b99f645c6 | |
Zbigniew Jędrzejewski-Szmek | ca03142040 | |
Marc-André Lureau | 2c7039b316 | |
Lennart Poettering | ba45534917 | |
Lennart Poettering | a45aced09a | |
Lennart Poettering | a851ba0795 | |
Vito Caputo | 219ab1fbd0 |
|
@ -114,6 +114,7 @@ All execution-related settings are available for transient units.
|
||||||
✓ SupplementaryGroups=
|
✓ SupplementaryGroups=
|
||||||
✓ Nice=
|
✓ Nice=
|
||||||
✓ OOMScoreAdjust=
|
✓ OOMScoreAdjust=
|
||||||
|
✓ CoredumpFilter=
|
||||||
✓ IOSchedulingClass=
|
✓ IOSchedulingClass=
|
||||||
✓ IOSchedulingPriority=
|
✓ IOSchedulingPriority=
|
||||||
✓ CPUSchedulingPolicy=
|
✓ CPUSchedulingPolicy=
|
||||||
|
|
|
@ -160,6 +160,11 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*8930:*
|
||||||
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*7750G:pvr*
|
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnAspire*7750G:pvr*
|
||||||
KEYBOARD_KEY_e0=!pageup
|
KEYBOARD_KEY_e0=!pageup
|
||||||
|
|
||||||
|
# Predator PH 315-52
|
||||||
|
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnPredator*PH*315-52:pvr*
|
||||||
|
KEYBOARD_KEY_ef=kbdillumup # Fn+F10
|
||||||
|
KEYBOARD_KEY_f0=kbdillumdown # Fn+F9
|
||||||
|
|
||||||
# Travelmate C300
|
# Travelmate C300
|
||||||
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*C3[01]0*:pvr*
|
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnAcer*:pnTravelMate*C3[01]0*:pvr*
|
||||||
KEYBOARD_KEY_67=f24 # FIXME: rotate screen
|
KEYBOARD_KEY_67=f24 # FIXME: rotate screen
|
||||||
|
|
|
@ -146,8 +146,24 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--slice=</option></term>
|
<term><option>--slice=</option></term>
|
||||||
|
|
||||||
<listitem><para>Make the new <filename>.service</filename> or <filename>.scope</filename> unit part of the
|
<listitem><para>Make the new <filename>.service</filename> or <filename>.scope</filename> unit part
|
||||||
specified slice, instead of <filename>system.slice</filename>.</para>
|
of the specified slice, instead of <filename>system.slice</filename> (when running in
|
||||||
|
<option>--system</option> mode) or the root slice (when running in <option>--user</option>
|
||||||
|
mode).</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--slice-inherit</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Make the new <filename>.service</filename> or <filename>.scope</filename> unit part
|
||||||
|
of the inherited slice. This option can be combined with <option>--slice=</option>.</para>
|
||||||
|
|
||||||
|
<para>An inherited slice is located within <command>systemd-run</command> slice. Example: if
|
||||||
|
<command>systemd-run</command> slice is <filename>foo.slice</filename>, and the
|
||||||
|
<option>--slice=</option> argument is <filename>bar</filename>, the unit will be placed under the
|
||||||
|
<filename>foo-bar.slice</filename>.</para>
|
||||||
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
|
|
@ -652,8 +652,39 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||||
<term><varname>UMask=</varname></term>
|
<term><varname>UMask=</varname></term>
|
||||||
|
|
||||||
<listitem><para>Controls the file mode creation mask. Takes an access mode in octal notation. See
|
<listitem><para>Controls the file mode creation mask. Takes an access mode in octal notation. See
|
||||||
<citerefentry><refentrytitle>umask</refentrytitle><manvolnum>2</manvolnum></citerefentry> for details. Defaults
|
<citerefentry><refentrytitle>umask</refentrytitle><manvolnum>2</manvolnum></citerefentry> for
|
||||||
to 0022.</para></listitem>
|
details. Defaults to 0022 for system units. For units of the user service manager the default value
|
||||||
|
is inherited from the user instance (whose default is inherited from the system service manager, and
|
||||||
|
thus also is 0022). Hence changing the default value of a user instance, either via
|
||||||
|
<varname>UMask=</varname> or via a PAM module, will affect the user instance itself and all user
|
||||||
|
units started by the user instance unless a user unit has specified its own
|
||||||
|
<varname>UMask=</varname>.</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>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|
|
@ -423,6 +423,9 @@
|
||||||
<varname>ExecStart=</varname>, or <varname>ExecStartPost=</varname> fail (and are not prefixed with
|
<varname>ExecStart=</varname>, or <varname>ExecStartPost=</varname> fail (and are not prefixed with
|
||||||
<literal>-</literal>, see above) or time out before the service is fully up, execution continues with commands
|
<literal>-</literal>, see above) or time out before the service is fully up, execution continues with commands
|
||||||
specified in <varname>ExecStopPost=</varname>, the commands in <varname>ExecStop=</varname> are skipped.</para>
|
specified in <varname>ExecStopPost=</varname>, the commands in <varname>ExecStop=</varname> are skipped.</para>
|
||||||
|
|
||||||
|
<para>Note that the execution of <varname>ExecStartPost=</varname> is taken into account for the purpose of
|
||||||
|
<varname>Before=</varname>/<varname>After=</varname> ordering constraints.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
@ -534,7 +537,10 @@
|
||||||
service, as well as the main process' exit code and status, set in the <varname>$SERVICE_RESULT</varname>,
|
service, as well as the main process' exit code and status, set in the <varname>$SERVICE_RESULT</varname>,
|
||||||
<varname>$EXIT_CODE</varname> and <varname>$EXIT_STATUS</varname> environment variables, see
|
<varname>$EXIT_CODE</varname> and <varname>$EXIT_STATUS</varname> environment variables, see
|
||||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||||
details.</para></listitem>
|
details.</para>
|
||||||
|
|
||||||
|
<para>Note that the execution of <varname>ExecStopPost=</varname> is taken into account for the purpose of
|
||||||
|
<varname>Before=</varname>/<varname>After=</varname> ordering constraints.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|
|
@ -750,7 +750,8 @@
|
||||||
type when precisely a unit has finished starting up. Most importantly, for service units start-up is
|
type when precisely a unit has finished starting up. Most importantly, for service units start-up is
|
||||||
considered completed for the purpose of <varname>Before=</varname>/<varname>After=</varname> when all
|
considered completed for the purpose of <varname>Before=</varname>/<varname>After=</varname> when all
|
||||||
its configured start-up commands have been invoked and they either failed or reported start-up
|
its configured start-up commands have been invoked and they either failed or reported start-up
|
||||||
success.</para>
|
success. Note that this does includes <varname>ExecStartPost=</varname> (or
|
||||||
|
<varname>ExecStopPost=</varname> for the shutdown case).</para>
|
||||||
|
|
||||||
<para>Note that those settings are independent of and orthogonal to the requirement dependencies as
|
<para>Note that those settings are independent of and orthogonal to the requirement dependencies as
|
||||||
configured by <varname>Requires=</varname>, <varname>Wants=</varname>, <varname>Requisite=</varname>,
|
configured by <varname>Requires=</varname>, <varname>Wants=</varname>, <varname>Requisite=</varname>,
|
||||||
|
|
|
@ -518,22 +518,28 @@ char* shell_maybe_quote(const char *s, EscapeStyle style) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
t = r;
|
t = r;
|
||||||
if (style == ESCAPE_BACKSLASH)
|
switch (style) {
|
||||||
|
case ESCAPE_BACKSLASH:
|
||||||
|
case ESCAPE_BACKSLASH_ONELINE:
|
||||||
*(t++) = '"';
|
*(t++) = '"';
|
||||||
else if (style == ESCAPE_POSIX) {
|
break;
|
||||||
|
case ESCAPE_POSIX:
|
||||||
*(t++) = '$';
|
*(t++) = '$';
|
||||||
*(t++) = '\'';
|
*(t++) = '\'';
|
||||||
} else
|
break;
|
||||||
|
default:
|
||||||
assert_not_reached("Bad EscapeStyle");
|
assert_not_reached("Bad EscapeStyle");
|
||||||
|
}
|
||||||
|
|
||||||
t = mempcpy(t, s, p - s);
|
t = mempcpy(t, s, p - s);
|
||||||
|
|
||||||
if (style == ESCAPE_BACKSLASH)
|
if (IN_SET(style, ESCAPE_BACKSLASH, ESCAPE_BACKSLASH_ONELINE))
|
||||||
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE, false);
|
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE,
|
||||||
|
style == ESCAPE_BACKSLASH_ONELINE);
|
||||||
else
|
else
|
||||||
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true);
|
t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE_POSIX, true);
|
||||||
|
|
||||||
if (style == ESCAPE_BACKSLASH)
|
if (IN_SET(style, ESCAPE_BACKSLASH, ESCAPE_BACKSLASH_ONELINE))
|
||||||
*(t++) = '"';
|
*(t++) = '"';
|
||||||
else
|
else
|
||||||
*(t++) = '\'';
|
*(t++) = '\'';
|
||||||
|
|
|
@ -34,8 +34,13 @@ typedef enum UnescapeFlags {
|
||||||
} UnescapeFlags;
|
} UnescapeFlags;
|
||||||
|
|
||||||
typedef enum EscapeStyle {
|
typedef enum EscapeStyle {
|
||||||
ESCAPE_BACKSLASH = 1,
|
ESCAPE_BACKSLASH = 1, /* Add shell quotes ("") so the shell will consider this a single
|
||||||
ESCAPE_POSIX = 2,
|
argument, possibly multiline. Tabs and newlines are not escaped. */
|
||||||
|
ESCAPE_BACKSLASH_ONELINE = 2, /* Similar to ESCAPE_BACKSLASH, but always produces a single-line
|
||||||
|
string instead. Shell escape sequences are produced for tabs and
|
||||||
|
newlines. */
|
||||||
|
ESCAPE_POSIX = 3, /* Similar to ESCAPE_BACKSLASH_ONELINE, but uses POSIX shell escape
|
||||||
|
* syntax (a string enclosed in $'') instead of plain quotes. */
|
||||||
} EscapeStyle;
|
} EscapeStyle;
|
||||||
|
|
||||||
char *cescape(const char *s);
|
char *cescape(const char *s);
|
||||||
|
|
|
@ -395,7 +395,7 @@ int safe_atoi(const char *s, int *ret_i) {
|
||||||
return 0;
|
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;
|
char *x = NULL;
|
||||||
unsigned long long l;
|
unsigned long long l;
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
||||||
s += strspn(s, WHITESPACE);
|
s += strspn(s, WHITESPACE);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = strtoull(s, &x, 0);
|
l = strtoull(s, &x, base);
|
||||||
if (errno > 0)
|
if (errno > 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
if (!x || x == s || *x != 0)
|
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_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_atolli(const char *s, long long int *ret_i);
|
||||||
|
|
||||||
int safe_atou8(const char *s, uint8_t *ret);
|
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);
|
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) {
|
static inline int safe_atou64(const char *s, uint64_t *ret_u) {
|
||||||
assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
|
assert_cc(sizeof(uint64_t) == sizeof(unsigned long long));
|
||||||
return safe_atollu(s, (unsigned long long*) ret_u);
|
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);
|
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
|
#if LONG_MAX == INT_MAX
|
||||||
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
|
static inline int safe_atolu(const char *s, unsigned long *ret_u) {
|
||||||
assert_cc(sizeof(unsigned long) == sizeof(unsigned));
|
assert_cc(sizeof(unsigned long) == sizeof(unsigned));
|
||||||
|
|
|
@ -628,6 +628,23 @@ int get_process_ppid(pid_t pid, pid_t *_ppid) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_process_umask(pid_t pid, mode_t *umask) {
|
||||||
|
_cleanup_free_ char *m = NULL;
|
||||||
|
const char *p;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(umask);
|
||||||
|
assert(pid >= 0);
|
||||||
|
|
||||||
|
p = procfs_file_alloca(pid, "status");
|
||||||
|
|
||||||
|
r = get_proc_field(p, "Umask", WHITESPACE, &m);
|
||||||
|
if (r == -ENOENT)
|
||||||
|
return -ESRCH;
|
||||||
|
|
||||||
|
return parse_mode(m, umask);
|
||||||
|
}
|
||||||
|
|
||||||
int wait_for_terminate(pid_t pid, siginfo_t *status) {
|
int wait_for_terminate(pid_t pid, siginfo_t *status) {
|
||||||
siginfo_t dummy;
|
siginfo_t dummy;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ int get_process_cwd(pid_t pid, char **cwd);
|
||||||
int get_process_root(pid_t pid, char **root);
|
int get_process_root(pid_t pid, char **root);
|
||||||
int get_process_environ(pid_t pid, char **environ);
|
int get_process_environ(pid_t pid, char **environ);
|
||||||
int get_process_ppid(pid_t pid, pid_t *ppid);
|
int get_process_ppid(pid_t pid, pid_t *ppid);
|
||||||
|
int get_process_umask(pid_t pid, mode_t *umask);
|
||||||
|
|
||||||
int wait_for_terminate(pid_t pid, siginfo_t *status);
|
int wait_for_terminate(pid_t pid, siginfo_t *status);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
/* Underlined */
|
/* Underlined */
|
||||||
#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
|
#define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
|
||||||
#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
|
#define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
|
||||||
#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;33m"
|
#define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;38;5;185m"
|
||||||
#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
|
#define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
|
||||||
#define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
|
#define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
|
||||||
#define ANSI_HIGHLIGHT_GREY_UNDERLINE "\x1B[0;1;4;38;5;245m"
|
#define ANSI_HIGHLIGHT_GREY_UNDERLINE "\x1B[0;1;4;38;5;245m"
|
||||||
|
|
|
@ -102,6 +102,7 @@ static int property_get_oom_score_adjust(
|
||||||
|
|
||||||
ExecContext *c = userdata;
|
ExecContext *c = userdata;
|
||||||
int32_t n;
|
int32_t n;
|
||||||
|
int r;
|
||||||
|
|
||||||
assert(bus);
|
assert(bus);
|
||||||
assert(reply);
|
assert(reply);
|
||||||
|
@ -113,13 +114,55 @@ static int property_get_oom_score_adjust(
|
||||||
_cleanup_free_ char *t = NULL;
|
_cleanup_free_ char *t = NULL;
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
|
r = read_one_line_file("/proc/self/oom_score_adj", &t);
|
||||||
safe_atoi32(t, &n);
|
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);
|
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(
|
static int property_get_nice(
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
const char *path,
|
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("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("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("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("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("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),
|
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;
|
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")) {
|
} else if (streq(name, "EnvironmentFiles")) {
|
||||||
|
|
||||||
_cleanup_free_ char *joined = NULL;
|
_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) {
|
if (context->nice_set) {
|
||||||
r = setpriority_closest(context->nice);
|
r = setpriority_closest(context->nice);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -4614,6 +4622,11 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||||
"%sOOMScoreAdjust: %i\n",
|
"%sOOMScoreAdjust: %i\n",
|
||||||
prefix, c->oom_score_adjust);
|
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++)
|
for (i = 0; i < RLIM_NLIMITS; i++)
|
||||||
if (c->rlimit[i]) {
|
if (c->rlimit[i]) {
|
||||||
fprintf(f, "%sLimit%s: " RLIM_FMT "\n",
|
fprintf(f, "%sLimit%s: " RLIM_FMT "\n",
|
||||||
|
|
|
@ -14,6 +14,7 @@ typedef struct Manager Manager;
|
||||||
#include <sys/capability.h>
|
#include <sys/capability.h>
|
||||||
|
|
||||||
#include "cgroup-util.h"
|
#include "cgroup-util.h"
|
||||||
|
#include "coredump-util.h"
|
||||||
#include "cpu-set-util.h"
|
#include "cpu-set-util.h"
|
||||||
#include "exec-util.h"
|
#include "exec-util.h"
|
||||||
#include "fdset.h"
|
#include "fdset.h"
|
||||||
|
@ -161,6 +162,7 @@ struct ExecContext {
|
||||||
bool working_directory_home:1;
|
bool working_directory_home:1;
|
||||||
|
|
||||||
bool oom_score_adjust_set:1;
|
bool oom_score_adjust_set:1;
|
||||||
|
bool coredump_filter_set:1;
|
||||||
bool nice_set:1;
|
bool nice_set:1;
|
||||||
bool ioprio_set:1;
|
bool ioprio_set:1;
|
||||||
bool cpu_sched_set:1;
|
bool cpu_sched_set:1;
|
||||||
|
@ -179,6 +181,7 @@ struct ExecContext {
|
||||||
int ioprio;
|
int ioprio;
|
||||||
int cpu_sched_policy;
|
int cpu_sched_policy;
|
||||||
int cpu_sched_priority;
|
int cpu_sched_priority;
|
||||||
|
uint64_t coredump_filter;
|
||||||
|
|
||||||
CPUSet cpu_set;
|
CPUSet cpu_set;
|
||||||
NUMAPolicy numa_policy;
|
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.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.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context)
|
||||||
$1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 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.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context)
|
||||||
$1.IOSchedulingPriority, config_parse_exec_io_priority, 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)
|
$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;
|
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(
|
int config_parse_exec(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
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_socket_bind);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_nice);
|
CONFIG_PARSER_PROTOTYPE(config_parse_exec_nice);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_oom_score_adjust);
|
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_exec);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout);
|
CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_abort);
|
CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_abort);
|
||||||
|
|
|
@ -2581,7 +2581,7 @@ int main(int argc, char *argv[]) {
|
||||||
if (!skip_setup)
|
if (!skip_setup)
|
||||||
kmod_setup();
|
kmod_setup();
|
||||||
|
|
||||||
r = mount_setup(loaded_policy);
|
r = mount_setup(loaded_policy, skip_setup);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
error_message = "Failed to mount API filesystems";
|
error_message = "Failed to mount API filesystems";
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
|
@ -478,7 +478,7 @@ static int relabel_extra(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int mount_setup(bool loaded_policy) {
|
int mount_setup(bool loaded_policy, bool leave_propagation) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy);
|
r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy);
|
||||||
|
@ -524,7 +524,7 @@ int mount_setup(bool loaded_policy) {
|
||||||
* needed. Note that we set this only when we are invoked directly by the kernel. If we are invoked by a
|
* needed. Note that we set this only when we are invoked directly by the kernel. If we are invoked by a
|
||||||
* container manager we assume the container manager knows what it is doing (for example, because it set up
|
* container manager we assume the container manager knows what it is doing (for example, because it set up
|
||||||
* some directories with different propagation modes). */
|
* some directories with different propagation modes). */
|
||||||
if (detect_container() <= 0)
|
if (detect_container() <= 0 && !leave_propagation)
|
||||||
if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
|
if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0)
|
||||||
log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m");
|
log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m");
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
int mount_setup_early(void);
|
int mount_setup_early(void);
|
||||||
int mount_setup(bool loaded_policy);
|
int mount_setup(bool loaded_policy, bool leave_propagation);
|
||||||
|
|
||||||
int mount_cgroup_controllers(void);
|
int mount_cgroup_controllers(void);
|
||||||
|
|
||||||
|
|
|
@ -187,8 +187,16 @@ static void unit_init(Unit *u) {
|
||||||
if (ec) {
|
if (ec) {
|
||||||
exec_context_init(ec);
|
exec_context_init(ec);
|
||||||
|
|
||||||
ec->keyring_mode = MANAGER_IS_SYSTEM(u->manager) ?
|
if (MANAGER_IS_SYSTEM(u->manager))
|
||||||
EXEC_KEYRING_SHARED : EXEC_KEYRING_INHERIT;
|
ec->keyring_mode = EXEC_KEYRING_SHARED;
|
||||||
|
else {
|
||||||
|
ec->keyring_mode = EXEC_KEYRING_INHERIT;
|
||||||
|
|
||||||
|
/* User manager might have its umask redefined by PAM or UMask=. In this
|
||||||
|
* case let the units it manages inherit this value by default. They can
|
||||||
|
* still tune this value through their own unit file */
|
||||||
|
(void) get_process_umask(getpid_cached(), &ec->umask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kc = unit_get_kill_context(u);
|
kc = unit_get_kill_context(u);
|
||||||
|
|
|
@ -41,6 +41,7 @@ static bool arg_wait = false;
|
||||||
static const char *arg_unit = NULL;
|
static const char *arg_unit = NULL;
|
||||||
static const char *arg_description = NULL;
|
static const char *arg_description = NULL;
|
||||||
static const char *arg_slice = NULL;
|
static const char *arg_slice = NULL;
|
||||||
|
static bool arg_slice_inherit = false;
|
||||||
static bool arg_send_sighup = false;
|
static bool arg_send_sighup = false;
|
||||||
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
|
static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
|
||||||
static const char *arg_host = NULL;
|
static const char *arg_host = NULL;
|
||||||
|
@ -97,6 +98,7 @@ static int help(void) {
|
||||||
" -p --property=NAME=VALUE Set service or scope unit property\n"
|
" -p --property=NAME=VALUE Set service or scope unit property\n"
|
||||||
" --description=TEXT Description for unit\n"
|
" --description=TEXT Description for unit\n"
|
||||||
" --slice=SLICE Run in the specified slice\n"
|
" --slice=SLICE Run in the specified slice\n"
|
||||||
|
" --slice-inherit Inherit the slice\n"
|
||||||
" --no-block Do not wait until operation finished\n"
|
" --no-block Do not wait until operation finished\n"
|
||||||
" -r --remain-after-exit Leave service around until explicitly stopped\n"
|
" -r --remain-after-exit Leave service around until explicitly stopped\n"
|
||||||
" --wait Wait until service stopped again\n"
|
" --wait Wait until service stopped again\n"
|
||||||
|
@ -162,6 +164,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
ARG_SCOPE,
|
ARG_SCOPE,
|
||||||
ARG_DESCRIPTION,
|
ARG_DESCRIPTION,
|
||||||
ARG_SLICE,
|
ARG_SLICE,
|
||||||
|
ARG_SLICE_INHERIT,
|
||||||
ARG_SEND_SIGHUP,
|
ARG_SEND_SIGHUP,
|
||||||
ARG_SERVICE_TYPE,
|
ARG_SERVICE_TYPE,
|
||||||
ARG_EXEC_USER,
|
ARG_EXEC_USER,
|
||||||
|
@ -194,6 +197,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
{ "unit", required_argument, NULL, 'u' },
|
{ "unit", required_argument, NULL, 'u' },
|
||||||
{ "description", required_argument, NULL, ARG_DESCRIPTION },
|
{ "description", required_argument, NULL, ARG_DESCRIPTION },
|
||||||
{ "slice", required_argument, NULL, ARG_SLICE },
|
{ "slice", required_argument, NULL, ARG_SLICE },
|
||||||
|
{ "slice-inherit", no_argument, NULL, ARG_SLICE_INHERIT },
|
||||||
{ "remain-after-exit", no_argument, NULL, 'r' },
|
{ "remain-after-exit", no_argument, NULL, 'r' },
|
||||||
{ "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
|
{ "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
|
||||||
{ "host", required_argument, NULL, 'H' },
|
{ "host", required_argument, NULL, 'H' },
|
||||||
|
@ -273,6 +277,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
arg_slice = optarg;
|
arg_slice = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_SLICE_INHERIT:
|
||||||
|
arg_slice_inherit = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case ARG_SEND_SIGHUP:
|
case ARG_SEND_SIGHUP:
|
||||||
arg_send_sighup = true;
|
arg_send_sighup = true;
|
||||||
break;
|
break;
|
||||||
|
@ -637,23 +645,50 @@ static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **p
|
||||||
}
|
}
|
||||||
|
|
||||||
static int transient_cgroup_set_properties(sd_bus_message *m) {
|
static int transient_cgroup_set_properties(sd_bus_message *m) {
|
||||||
|
_cleanup_free_ char *name = NULL;
|
||||||
|
_cleanup_free_ char *slice = NULL;
|
||||||
int r;
|
int r;
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
if (!isempty(arg_slice)) {
|
if (arg_slice_inherit) {
|
||||||
_cleanup_free_ char *slice = NULL;
|
char *end;
|
||||||
|
|
||||||
r = unit_name_mangle_with_suffix(arg_slice, "as slice",
|
if (arg_user)
|
||||||
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
r = cg_pid_get_user_slice(0, &name);
|
||||||
".slice", &slice);
|
else
|
||||||
|
r = cg_pid_get_slice(0, &name);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to mangle name '%s': %m", arg_slice);
|
return log_error_errno(r, "Failed to get PID slice: %m");
|
||||||
|
|
||||||
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
|
end = endswith(name, ".slice");
|
||||||
if (r < 0)
|
if (!end)
|
||||||
return bus_log_create_error(r);
|
return -ENXIO;
|
||||||
|
*end = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isempty(arg_slice)) {
|
||||||
|
if (name) {
|
||||||
|
char *j = strjoin(name, "-", arg_slice);
|
||||||
|
free_and_replace(name, j);
|
||||||
|
} else
|
||||||
|
name = strdup(arg_slice);
|
||||||
|
if (!name)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = unit_name_mangle_with_suffix(name, "as slice",
|
||||||
|
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
||||||
|
".slice", &slice);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to mangle name '%s': %m", arg_slice);
|
||||||
|
|
||||||
|
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
|
||||||
|
if (r < 0)
|
||||||
|
return bus_log_create_error(r);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "cgroup-setup.h"
|
#include "cgroup-setup.h"
|
||||||
#include "cgroup-util.h"
|
#include "cgroup-util.h"
|
||||||
#include "condition.h"
|
#include "condition.h"
|
||||||
|
#include "coredump-util.h"
|
||||||
#include "cpu-set-util.h"
|
#include "cpu-set-util.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
#include "exec-util.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, mode_t, parse_mode);
|
||||||
DEFINE_BUS_APPEND_PARSE_PTR("u", uint32_t, unsigned, safe_atou);
|
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("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) {
|
static int bus_append_string(sd_bus_message *m, const char *field, const char *eq) {
|
||||||
int r;
|
int r;
|
||||||
|
@ -898,6 +900,9 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
||||||
"OOMScoreAdjust"))
|
"OOMScoreAdjust"))
|
||||||
return bus_append_safe_atoi(m, field, eq);
|
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"))
|
if (streq(field, "Nice"))
|
||||||
return bus_append_parse_nice(m, field, eq);
|
return bus_append_parse_nice(m, field, eq);
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "bus-util.h"
|
#include "bus-util.h"
|
||||||
#include "cap-list.h"
|
#include "cap-list.h"
|
||||||
#include "cgroup-util.h"
|
#include "cgroup-util.h"
|
||||||
|
#include "escape.h"
|
||||||
#include "mountpoint-util.h"
|
#include "mountpoint-util.h"
|
||||||
#include "nsflags.h"
|
#include "nsflags.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
|
@ -373,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);
|
(void) format_timespan(timespan, sizeof(timespan), u, 0);
|
||||||
bus_print_property_value(name, expected_value, value, timespan);
|
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")) {
|
} else if (streq(name, "RestrictNamespaces")) {
|
||||||
_cleanup_free_ char *s = NULL;
|
_cleanup_free_ char *s = NULL;
|
||||||
const char *result;
|
const char *result;
|
||||||
|
@ -500,18 +507,20 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
|
while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
|
||||||
bool good;
|
_cleanup_free_ char *e = NULL;
|
||||||
|
|
||||||
if (first && !value)
|
e = shell_maybe_quote(str, ESCAPE_BACKSLASH_ONELINE);
|
||||||
printf("%s=", name);
|
if (!e)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* This property has multiple space-separated values, so
|
if (first) {
|
||||||
* neither spaces nor newlines can be allowed in a value. */
|
if (!value)
|
||||||
good = str[strcspn(str, " \n")] == '\0';
|
printf("%s=", name);
|
||||||
|
first = false;
|
||||||
|
} else
|
||||||
|
fputs(" ", stdout);
|
||||||
|
|
||||||
printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
|
fputs(e, stdout);
|
||||||
|
|
||||||
first = false;
|
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -1390,3 +1399,142 @@ const struct hash_ops bus_message_hash_ops = {
|
||||||
.compare = trivial_compare_func,
|
.compare = trivial_compare_func,
|
||||||
.free_value = bus_message_unref_wrapper,
|
.free_value = bus_message_unref_wrapper,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Shorthand flavors of the sd-bus convenience helpers with destination,path,interface
|
||||||
|
* strings encapsulated within a single struct.
|
||||||
|
*/
|
||||||
|
int bus_call_method_async(
|
||||||
|
sd_bus *bus,
|
||||||
|
sd_bus_slot **slot,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_message_handler_t callback,
|
||||||
|
void *userdata,
|
||||||
|
const char *types, ...) {
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
va_start(ap, types);
|
||||||
|
r = sd_bus_call_method_asyncv(bus, slot, address->destination, address->path, address->interface, member, callback, userdata, types, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bus_call_method(
|
||||||
|
sd_bus *bus,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_error *error,
|
||||||
|
sd_bus_message **reply,
|
||||||
|
const char *types, ...) {
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
va_start(ap, types);
|
||||||
|
r = sd_bus_call_methodv(bus, address->destination, address->path, address->interface, member, error, reply, types, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bus_get_property(
|
||||||
|
sd_bus *bus,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_error *error,
|
||||||
|
sd_bus_message **reply,
|
||||||
|
const char *type) {
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
return sd_bus_get_property(bus, address->destination, address->path, address->interface, member, error, reply, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bus_get_property_trivial(
|
||||||
|
sd_bus *bus,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_error *error,
|
||||||
|
char type, void *ptr) {
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
return sd_bus_get_property_trivial(bus, address->destination, address->path, address->interface, member, error, type, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bus_get_property_string(
|
||||||
|
sd_bus *bus,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_error *error,
|
||||||
|
char **ret) {
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
return sd_bus_get_property_string(bus, address->destination, address->path, address->interface, member, error, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bus_get_property_strv(
|
||||||
|
sd_bus *bus,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_error *error,
|
||||||
|
char ***ret) {
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
return sd_bus_get_property_strv(bus, address->destination, address->path, address->interface, member, error, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bus_set_property(
|
||||||
|
sd_bus *bus,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_error *error,
|
||||||
|
const char *type, ...) {
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
va_start(ap, type);
|
||||||
|
r = sd_bus_set_propertyv(bus, address->destination, address->path, address->interface, member, error, type, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bus_match_signal(
|
||||||
|
sd_bus *bus,
|
||||||
|
sd_bus_slot **ret,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_message_handler_t callback,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
return sd_bus_match_signal(bus, ret, address->destination, address->path, address->interface, member, callback, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bus_match_signal_async(
|
||||||
|
sd_bus *bus,
|
||||||
|
sd_bus_slot **ret,
|
||||||
|
const BusAddress *address,
|
||||||
|
const char *member,
|
||||||
|
sd_bus_message_handler_t callback,
|
||||||
|
sd_bus_message_handler_t install_callback,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
assert(address);
|
||||||
|
|
||||||
|
return sd_bus_match_signal_async(bus, ret, address->destination, address->path, address->interface, member, callback, install_callback, userdata);
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,12 @@ typedef enum BusTransport {
|
||||||
_BUS_TRANSPORT_INVALID = -1
|
_BUS_TRANSPORT_INVALID = -1
|
||||||
} BusTransport;
|
} BusTransport;
|
||||||
|
|
||||||
|
typedef struct BusAddress {
|
||||||
|
const char *destination;
|
||||||
|
const char *path;
|
||||||
|
const char *interface;
|
||||||
|
} BusAddress;
|
||||||
|
|
||||||
typedef int (*bus_property_set_t) (sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata);
|
typedef int (*bus_property_set_t) (sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata);
|
||||||
|
|
||||||
struct bus_properties_map {
|
struct bus_properties_map {
|
||||||
|
@ -179,3 +185,16 @@ static inline int bus_open_system_watch_bind(sd_bus **ret) {
|
||||||
int bus_reply_pair_array(sd_bus_message *m, char **l);
|
int bus_reply_pair_array(sd_bus_message *m, char **l);
|
||||||
|
|
||||||
extern const struct hash_ops bus_message_hash_ops;
|
extern const struct hash_ops bus_message_hash_ops;
|
||||||
|
|
||||||
|
/* Shorthand flavors of the sd-bus convenience helpers with destination,path,interface
|
||||||
|
* strings encapsulated within a single struct.
|
||||||
|
*/
|
||||||
|
int bus_call_method_async(sd_bus *bus, sd_bus_slot **slot, const BusAddress *address, const char *member, sd_bus_message_handler_t callback, void *userdata, const char *types, ...);
|
||||||
|
int bus_call_method(sd_bus *bus, const BusAddress *address, const char *member, sd_bus_error *error, sd_bus_message **reply, const char *types, ...);
|
||||||
|
int bus_get_property(sd_bus *bus, const BusAddress *address, const char *member, sd_bus_error *error, sd_bus_message **reply, const char *type);
|
||||||
|
int bus_get_property_trivial(sd_bus *bus, const BusAddress *address, const char *member, sd_bus_error *error, char type, void *ptr);
|
||||||
|
int bus_get_property_string(sd_bus *bus, const BusAddress *address, const char *member, sd_bus_error *error, char **ret);
|
||||||
|
int bus_get_property_strv(sd_bus *bus, const BusAddress *address, const char *member, sd_bus_error *error, char ***ret);
|
||||||
|
int bus_set_property(sd_bus *bus, const BusAddress *address, const char *member, sd_bus_error *error, const char *type, ...);
|
||||||
|
int bus_match_signal(sd_bus *bus, sd_bus_slot **ret, const BusAddress *address, const char *member, sd_bus_message_handler_t callback, void *userdata);
|
||||||
|
int bus_match_signal_async(sd_bus *bus, sd_bus_slot **ret, const BusAddress *address, const char *member, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
condition.h
|
||||||
conf-parser.c
|
conf-parser.c
|
||||||
conf-parser.h
|
conf-parser.h
|
||||||
|
coredump-util.c
|
||||||
|
coredump-util.h
|
||||||
cpu-set-util.c
|
cpu-set-util.c
|
||||||
cpu-set-util.h
|
cpu-set-util.h
|
||||||
crypt-util.c
|
crypt-util.c
|
||||||
|
|
|
@ -223,7 +223,7 @@ static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offse
|
||||||
|
|
||||||
fd = open(swap->device, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
fd = open(swap->device, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(errno, "Failed to open %s: %m", swap->device);
|
return log_error_errno(errno, "Failed to open swap file %s to determine on-disk offset: %m", swap->device);
|
||||||
|
|
||||||
if (fstat(fd, &sb) < 0)
|
if (fstat(fd, &sb) < 0)
|
||||||
return log_error_errno(errno, "Failed to stat %s: %m", swap->device);
|
return log_error_errno(errno, "Failed to stat %s: %m", swap->device);
|
||||||
|
|
|
@ -588,6 +588,10 @@ tests += [
|
||||||
[],
|
[],
|
||||||
[]],
|
[]],
|
||||||
|
|
||||||
|
[['src/test/test-coredump-util.c'],
|
||||||
|
[],
|
||||||
|
[]],
|
||||||
|
|
||||||
[['src/test/test-daemon.c'],
|
[['src/test/test-daemon.c'],
|
||||||
[],
|
[],
|
||||||
[]],
|
[]],
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -142,31 +142,42 @@ static void test_shell_maybe_quote_one(const char *s,
|
||||||
static void test_shell_maybe_quote(void) {
|
static void test_shell_maybe_quote(void) {
|
||||||
|
|
||||||
test_shell_maybe_quote_one("", ESCAPE_BACKSLASH, "");
|
test_shell_maybe_quote_one("", ESCAPE_BACKSLASH, "");
|
||||||
|
test_shell_maybe_quote_one("", ESCAPE_BACKSLASH_ONELINE, "");
|
||||||
test_shell_maybe_quote_one("", ESCAPE_POSIX, "");
|
test_shell_maybe_quote_one("", ESCAPE_POSIX, "");
|
||||||
test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH, "\"\\\\\"");
|
test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH, "\"\\\\\"");
|
||||||
|
test_shell_maybe_quote_one("\\", ESCAPE_BACKSLASH_ONELINE, "\"\\\\\"");
|
||||||
test_shell_maybe_quote_one("\\", ESCAPE_POSIX, "$'\\\\'");
|
test_shell_maybe_quote_one("\\", ESCAPE_POSIX, "$'\\\\'");
|
||||||
test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH, "\"\\\"\"");
|
test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH, "\"\\\"\"");
|
||||||
|
test_shell_maybe_quote_one("\"", ESCAPE_BACKSLASH_ONELINE, "\"\\\"\"");
|
||||||
test_shell_maybe_quote_one("\"", ESCAPE_POSIX, "$'\"'");
|
test_shell_maybe_quote_one("\"", ESCAPE_POSIX, "$'\"'");
|
||||||
test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH, "foobar");
|
test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH, "foobar");
|
||||||
|
test_shell_maybe_quote_one("foobar", ESCAPE_BACKSLASH_ONELINE, "foobar");
|
||||||
test_shell_maybe_quote_one("foobar", ESCAPE_POSIX, "foobar");
|
test_shell_maybe_quote_one("foobar", ESCAPE_POSIX, "foobar");
|
||||||
test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH, "\"foo bar\"");
|
test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH, "\"foo bar\"");
|
||||||
|
test_shell_maybe_quote_one("foo bar", ESCAPE_BACKSLASH_ONELINE, "\"foo bar\"");
|
||||||
test_shell_maybe_quote_one("foo bar", ESCAPE_POSIX, "$'foo bar'");
|
test_shell_maybe_quote_one("foo bar", ESCAPE_POSIX, "$'foo bar'");
|
||||||
test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH, "\"foo\tbar\"");
|
test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH, "\"foo\tbar\"");
|
||||||
|
test_shell_maybe_quote_one("foo\tbar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\tbar\"");
|
||||||
test_shell_maybe_quote_one("foo\tbar", ESCAPE_POSIX, "$'foo\\tbar'");
|
test_shell_maybe_quote_one("foo\tbar", ESCAPE_POSIX, "$'foo\\tbar'");
|
||||||
test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH, "\"foo\nbar\"");
|
test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH, "\"foo\nbar\"");
|
||||||
|
test_shell_maybe_quote_one("foo\nbar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\nbar\"");
|
||||||
test_shell_maybe_quote_one("foo\nbar", ESCAPE_POSIX, "$'foo\\nbar'");
|
test_shell_maybe_quote_one("foo\nbar", ESCAPE_POSIX, "$'foo\\nbar'");
|
||||||
test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH, "\"foo \\\"bar\\\" waldo\"");
|
test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH, "\"foo \\\"bar\\\" waldo\"");
|
||||||
|
test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_BACKSLASH_ONELINE, "\"foo \\\"bar\\\" waldo\"");
|
||||||
test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_POSIX, "$'foo \"bar\" waldo'");
|
test_shell_maybe_quote_one("foo \"bar\" waldo", ESCAPE_POSIX, "$'foo \"bar\" waldo'");
|
||||||
test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH, "\"foo\\$bar\"");
|
test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH, "\"foo\\$bar\"");
|
||||||
|
test_shell_maybe_quote_one("foo$bar", ESCAPE_BACKSLASH_ONELINE, "\"foo\\$bar\"");
|
||||||
test_shell_maybe_quote_one("foo$bar", ESCAPE_POSIX, "$'foo$bar'");
|
test_shell_maybe_quote_one("foo$bar", ESCAPE_POSIX, "$'foo$bar'");
|
||||||
|
|
||||||
/* Note that current users disallow control characters, so this "test"
|
/* Note that current users disallow control characters, so this "test"
|
||||||
* is here merely to establish current behaviour. If control characters
|
* is here merely to establish current behaviour. If control characters
|
||||||
* were allowed, they should be quoted, i.e. \001 should become \\001. */
|
* were allowed, they should be quoted, i.e. \001 should become \\001. */
|
||||||
test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH, "\"a\nb\001\"");
|
test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH, "\"a\nb\001\"");
|
||||||
|
test_shell_maybe_quote_one("a\nb\001", ESCAPE_BACKSLASH_ONELINE, "\"a\\nb\001\"");
|
||||||
test_shell_maybe_quote_one("a\nb\001", ESCAPE_POSIX, "$'a\\nb\001'");
|
test_shell_maybe_quote_one("a\nb\001", ESCAPE_POSIX, "$'a\\nb\001'");
|
||||||
|
|
||||||
test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH, "\"foo!bar\"");
|
test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH, "\"foo!bar\"");
|
||||||
|
test_shell_maybe_quote_one("foo!bar", ESCAPE_BACKSLASH_ONELINE, "\"foo!bar\"");
|
||||||
test_shell_maybe_quote_one("foo!bar", ESCAPE_POSIX, "$'foo!bar'");
|
test_shell_maybe_quote_one("foo!bar", ESCAPE_POSIX, "$'foo!bar'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -561,6 +561,44 @@ static void test_safe_atoi64(void) {
|
||||||
assert_se(r == -EINVAL);
|
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) {
|
static void test_safe_atod(void) {
|
||||||
int r;
|
int r;
|
||||||
double d;
|
double d;
|
||||||
|
@ -838,6 +876,7 @@ int main(int argc, char *argv[]) {
|
||||||
test_safe_atoux16();
|
test_safe_atoux16();
|
||||||
test_safe_atou64();
|
test_safe_atou64();
|
||||||
test_safe_atoi64();
|
test_safe_atoi64();
|
||||||
|
test_safe_atoux64();
|
||||||
test_safe_atod();
|
test_safe_atod();
|
||||||
test_parse_percent();
|
test_parse_percent();
|
||||||
test_parse_percent_unbounded();
|
test_parse_percent_unbounded();
|
||||||
|
|
|
@ -88,7 +88,7 @@ static void test_colors(void) {
|
||||||
test_one_color("green", ansi_green());
|
test_one_color("green", ansi_green());
|
||||||
test_one_color("yellow", ansi_yellow());
|
test_one_color("yellow", ansi_yellow());
|
||||||
test_one_color("blue", ansi_blue());
|
test_one_color("blue", ansi_blue());
|
||||||
test_one_color("megenta", ansi_magenta());
|
test_one_color("magenta", ansi_magenta());
|
||||||
test_one_color("grey", ansi_grey());
|
test_one_color("grey", ansi_grey());
|
||||||
test_one_color("highlight-red", ansi_highlight_red());
|
test_one_color("highlight-red", ansi_highlight_red());
|
||||||
test_one_color("highlight-green", ansi_highlight_green());
|
test_one_color("highlight-green", ansi_highlight_green());
|
||||||
|
|
|
@ -44,6 +44,7 @@ BlockIOWeight=
|
||||||
BlockIOWriteBandwidth=
|
BlockIOWriteBandwidth=
|
||||||
Broadcast=
|
Broadcast=
|
||||||
BusName=
|
BusName=
|
||||||
|
CoredumpFilter=
|
||||||
CPUAccounting=
|
CPUAccounting=
|
||||||
CPUQuota=
|
CPUQuota=
|
||||||
CPUShares=
|
CPUShares=
|
||||||
|
|
Loading…
Reference in New Issue