From bb9947be2fa308d198b63b30e494ade5d68e5109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 29 Mar 2018 16:19:33 +0200 Subject: [PATCH 1/2] tmpfiles: add a new return code for "operational failure" when processing Things can fail, and we have no control over it: - file system issues (immutable bits, file system errors, MAC refusals, etc) - kernel refusing certain arguments when writing to /proc/sys or /sys Let's add a new code for the case where we parsed configuration but failed to execute it because of external errors. --- man/systemd-tmpfiles.xml | 12 ++++++++---- src/basic/fd-util.h | 4 ++++ src/tmpfiles/tmpfiles.c | 20 ++++++++++---------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/man/systemd-tmpfiles.xml b/man/systemd-tmpfiles.xml index a6ae5e4f97..7c64dfaf58 100644 --- a/man/systemd-tmpfiles.xml +++ b/man/systemd-tmpfiles.xml @@ -225,11 +225,15 @@ Exit status - On success, 0 is returned. If the configuration was invalid (invalid syntax, missing - arguments, …), so some lines had to be ignored, but no other errors occurred, + On success, 0 is returned. If the configuration was syntactically invalid (syntax errors, + missing arguments, …), so some lines had to be ignored, but no other errors occurred, 65 is returned (EX_DATAERR from - /usr/include/sysexits.h). Otherwise, 1 is returned - (EXIT_FAILURE from /usr/include/stdlib.h). + /usr/include/sysexits.h). If the configuration was syntactically valid, but + could not be executed (lack of permissions, creation of files in missing directories, invalid + contents when writing to /sys/ values, …), 73 is + returned (EX_DATAERR from /usr/include/sysexits.h). + Otherwise, 1 is returned (EXIT_FAILURE from + /usr/include/stdlib.h). diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h index 007580b48f..a87d8bdb41 100644 --- a/src/basic/fd-util.h +++ b/src/basic/fd-util.h @@ -98,6 +98,10 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags); #define ERRNO_IS_DISCONNECT(r) \ IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH) +/* Resource exhaustion, could be our fault or general system trouble */ +#define ERRNO_IS_RESOURCE(r) \ + IN_SET(r, ENOMEM, EMFILE, ENFILE) + int fd_move_above_stdio(int fd); int rearrange_stdio(int original_input_fd, int original_output_fd, int original_error_fd); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 61e76570b1..9bb6a4f7e6 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1292,7 +1292,7 @@ static int write_one_file(Item *i, const char *path) { fd = safe_close(fd); -done: + done: if (stat(path, &st) < 0) return log_error_errno(errno, "stat(%s) failed: %m", path); @@ -2728,7 +2728,7 @@ static int read_config_files(char **config_dirs, char **args, bool *invalid_conf } int main(int argc, char *argv[]) { - int r, k; + int r, k, r_process = 0; ItemArray *a; Iterator iterator; _cleanup_strv_free_ char **config_dirs = NULL; @@ -2775,7 +2775,7 @@ int main(int argc, char *argv[]) { t = strv_join(config_dirs, "\n\t"); if (t) - log_debug("Looking for configuration files in (higher priority first:\n\t%s", t); + log_debug("Looking for configuration files in (higher priority first):\n\t%s", t); } /* If command line arguments are specified along with --replace, read all @@ -2791,22 +2791,20 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - - /* The non-globbing ones usually create things, hence we apply * them first */ ORDERED_HASHMAP_FOREACH(a, items, iterator) { k = process_item_array(a); - if (k < 0 && r == 0) - r = k; + if (k < 0 && r_process == 0) + r_process = k; } /* The globbing ones usually alter things, hence we apply them * second. */ ORDERED_HASHMAP_FOREACH(a, globs, iterator) { k = process_item_array(a); - if (k < 0 && r == 0) - r = k; + if (k < 0 && r_process == 0) + r_process = k; } finish: @@ -2821,10 +2819,12 @@ finish: mac_selinux_finish(); - if (r < 0) + if (r < 0 || ERRNO_IS_RESOURCE(-r_process)) return EXIT_FAILURE; else if (invalid_config) return EX_DATAERR; + else if (r_process < 0) + return EX_CANTCREAT; else return EXIT_SUCCESS; } From c79b89e6eb5efaa69b7d8358c43373fb9fab0af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 29 Mar 2018 16:37:21 +0200 Subject: [PATCH 2/2] tmpfiles: ignore "operational" errors during setup We still get the errors logged, but we don't fail the service. This is better for users because rerunning tmpfiles-setup.service a second time is dangerous (c.f. cd9f5b68ce08375eb1d68a4ddaa7a24a5092d7ba). Note that this only touches sd-tmpfiles-setup.service and sd-tmpfiles-setup-dev.service. sd-tmpfiles-clean.service is as before. https://bugzilla.redhat.com/show_bug.cgi?id=1539341 --- units/systemd-tmpfiles-setup-dev.service.in | 2 +- units/systemd-tmpfiles-setup.service.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/units/systemd-tmpfiles-setup-dev.service.in b/units/systemd-tmpfiles-setup-dev.service.in index 6a6ebed955..1d06b369d4 100644 --- a/units/systemd-tmpfiles-setup-dev.service.in +++ b/units/systemd-tmpfiles-setup-dev.service.in @@ -20,4 +20,4 @@ ConditionCapability=CAP_SYS_MODULE Type=oneshot RemainAfterExit=yes ExecStart=@rootbindir@/systemd-tmpfiles --prefix=/dev --create --boot -SuccessExitStatus=65 +SuccessExitStatus=65 73 diff --git a/units/systemd-tmpfiles-setup.service.in b/units/systemd-tmpfiles-setup.service.in index 0410d0bfd8..384be59481 100644 --- a/units/systemd-tmpfiles-setup.service.in +++ b/units/systemd-tmpfiles-setup.service.in @@ -20,4 +20,4 @@ RefuseManualStop=yes Type=oneshot RemainAfterExit=yes ExecStart=@rootbindir@/systemd-tmpfiles --create --remove --boot --exclude-prefix=/dev -SuccessExitStatus=65 +SuccessExitStatus=65 73