diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/machine-pool.c | 4 | ||||
-rw-r--r-- | src/shared/pager.c | 8 | ||||
-rw-r--r-- | src/shared/path-util.c | 16 | ||||
-rw-r--r-- | src/shared/pty.c | 2 | ||||
-rw-r--r-- | src/shared/signal-util.c | 104 | ||||
-rw-r--r-- | src/shared/signal-util.h | 2 | ||||
-rw-r--r-- | src/shared/util.c | 8 |
7 files changed, 101 insertions, 43 deletions
diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c index d27931cb4a..8c64908b1a 100644 --- a/src/shared/machine-pool.c +++ b/src/shared/machine-pool.c @@ -109,8 +109,8 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) { /* Child */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); fd = safe_close(fd); diff --git a/src/shared/pager.c b/src/shared/pager.c index 58b62fdccf..13f03e798b 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -30,6 +30,7 @@ #include "process-util.h" #include "macro.h" #include "terminal-util.h" +#include "signal-util.h" static pid_t pager_pid = 0; @@ -85,6 +86,9 @@ int pager_open(bool jump_to_end) { if (pager_pid == 0) { const char* less_opts; + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + dup2(fd[0], STDIN_FILENO); safe_close_pair(fd); @@ -178,6 +182,10 @@ int show_man_page(const char *desc, bool null_stdio) { if (pid == 0) { /* Child */ + + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); + if (null_stdio) { r = make_null_stdio(); if (r < 0) { diff --git a/src/shared/path-util.c b/src/shared/path-util.c index be50a1865d..537705446a 100644 --- a/src/shared/path-util.c +++ b/src/shared/path-util.c @@ -640,7 +640,7 @@ fallback_fstat: /* flags can be AT_SYMLINK_FOLLOW or 0 */ int path_is_mount_point(const char *t, int flags) { _cleanup_close_ int fd = -1; - _cleanup_free_ char *parent = NULL; + _cleanup_free_ char *canonical = NULL, *parent = NULL; int r; assert(t); @@ -648,7 +648,17 @@ int path_is_mount_point(const char *t, int flags) { if (path_equal(t, "/")) return 1; - r = path_get_parent(t, &parent); + /* we need to resolve symlinks manually, we can't just rely on + * fd_is_mount_point() to do that for us; if we have a structure like + * /bin -> /usr/bin/ and /usr is a mount point, then the parent that we + * look at needs to be /usr, not /. */ + if (flags & AT_SYMLINK_FOLLOW) { + canonical = canonicalize_file_name(t); + if (!canonical) + return -errno; + } + + r = path_get_parent(canonical ?: t, &parent); if (r < 0) return r; @@ -656,7 +666,7 @@ int path_is_mount_point(const char *t, int flags) { if (fd < 0) return -errno; - return fd_is_mount_point(fd, basename(t), flags); + return fd_is_mount_point(fd, basename(canonical ?: t), flags); } int path_is_read_only_fs(const char *path) { diff --git a/src/shared/pty.c b/src/shared/pty.c index 119d66e9a2..a87b3ce6f0 100644 --- a/src/shared/pty.c +++ b/src/shared/pty.c @@ -239,7 +239,7 @@ int pty_setup_child(Pty *pty) { assert_return(pty_is_child(pty), -EINVAL); assert_return(pty_is_open(pty), -EALREADY); - r = sigprocmask_many(SIG_SETMASK, -1); + r = reset_signal_mask(); if (r < 0) return r; diff --git a/src/shared/signal-util.c b/src/shared/signal-util.c index 9a2973b6fd..84cf42b285 100644 --- a/src/shared/signal-util.c +++ b/src/shared/signal-util.c @@ -23,13 +23,13 @@ #include "signal-util.h" int reset_all_signal_handlers(void) { + static const struct sigaction sa = { + .sa_handler = SIG_DFL, + .sa_flags = SA_RESTART, + }; int sig, r = 0; for (sig = 1; sig < _NSIG; sig++) { - static const struct sigaction sa = { - .sa_handler = SIG_DFL, - .sa_flags = SA_RESTART, - }; /* These two cannot be caught... */ if (sig == SIGKILL || sig == SIGSTOP) @@ -38,7 +38,7 @@ int reset_all_signal_handlers(void) { /* On Linux the first two RT signals are reserved by * glibc, and sigaction() will return EINVAL for them. */ if ((sigaction(sig, &sa, NULL) < 0)) - if (errno != EINVAL && r == 0) + if (errno != EINVAL && r >= 0) r = -errno; } @@ -57,83 +57,123 @@ int reset_signal_mask(void) { return 0; } +static int sigaction_many_ap(const struct sigaction *sa, int sig, va_list ap) { + int r = 0; + + /* negative signal ends the list. 0 signal is skipped. */ + + if (sig < 0) + return 0; + + if (sig > 0) { + if (sigaction(sig, sa, NULL) < 0) + r = -errno; + } + + while ((sig = va_arg(ap, int)) >= 0) { + + if (sig == 0) + continue; + + if (sigaction(sig, sa, NULL) < 0) { + if (r >= 0) + r = -errno; + } + } + + return r; +} + int sigaction_many(const struct sigaction *sa, ...) { va_list ap; - int r = 0, sig; + int r; va_start(ap, sa); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, sa, NULL) < 0) - r = -errno; + r = sigaction_many_ap(sa, 0, ap); va_end(ap); return r; } int ignore_signals(int sig, ...) { + static const struct sigaction sa = { .sa_handler = SIG_IGN, .sa_flags = SA_RESTART, }; - va_list ap; - int r = 0; - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; + va_list ap; + int r; va_start(ap, sig); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; + r = sigaction_many_ap(&sa, sig, ap); va_end(ap); return r; } int default_signals(int sig, ...) { + static const struct sigaction sa = { .sa_handler = SIG_DFL, .sa_flags = SA_RESTART, }; - va_list ap; - int r = 0; - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; + va_list ap; + int r; va_start(ap, sig); - while ((sig = va_arg(ap, int)) > 0) - if (sigaction(sig, &sa, NULL) < 0) - r = -errno; + r = sigaction_many_ap(&sa, sig, ap); va_end(ap); return r; } -void sigset_add_many(sigset_t *ss, ...) { - va_list ap; - int sig; +static int sigset_add_many_ap(sigset_t *ss, va_list ap) { + int sig, r = 0; assert(ss); + while ((sig = va_arg(ap, int)) >= 0) { + + if (sig == 0) + continue; + + if (sigaddset(ss, sig) < 0) { + if (r >= 0) + r = -errno; + } + } + + return r; +} + +int sigset_add_many(sigset_t *ss, ...) { + va_list ap; + int r; + va_start(ap, ss); - while ((sig = va_arg(ap, int)) > 0) - assert_se(sigaddset(ss, sig) == 0); + r = sigset_add_many_ap(ss, ap); va_end(ap); + + return r; } int sigprocmask_many(int how, ...) { va_list ap; sigset_t ss; - int sig; + int r; - assert_se(sigemptyset(&ss) == 0); + if (sigemptyset(&ss) < 0) + return -errno; va_start(ap, how); - while ((sig = va_arg(ap, int)) > 0) - assert_se(sigaddset(&ss, sig) == 0); + r = sigset_add_many_ap(&ss, ap); va_end(ap); + if (r < 0) + return r; + if (sigprocmask(how, &ss, NULL) < 0) return -errno; diff --git a/src/shared/signal-util.h b/src/shared/signal-util.h index ddf64cda76..9dc8a28726 100644 --- a/src/shared/signal-util.h +++ b/src/shared/signal-util.h @@ -32,7 +32,7 @@ int ignore_signals(int sig, ...); int default_signals(int sig, ...); int sigaction_many(const struct sigaction *sa, ...); -void sigset_add_many(sigset_t *ss, ...); +int sigset_add_many(sigset_t *ss, ...); int sigprocmask_many(int how, ...); const char *signal_to_string(int i) _const_; diff --git a/src/shared/util.c b/src/shared/util.c index dc5e938796..a20e7bb2ef 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2301,8 +2301,8 @@ static int do_execute(char **directories, usec_t timeout, char *argv[]) { /* We fork this all off from a child process so that we can * somewhat cleanly make use of SIGALRM to set a time limit */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); @@ -3344,8 +3344,8 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa /* Make sure we actually can kill the agent, if we need to, in * case somebody invoked us from a shell script that trapped * SIGTERM or so... */ - reset_all_signal_handlers(); - reset_signal_mask(); + (void) reset_all_signal_handlers(); + (void) reset_signal_mask(); /* Check whether our parent died before we were able * to set the death signal and unblock the signals */ |