Merge pull request #7767 from poettering/fork-wait

A variety of smaller improvements all over the place
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2018-01-04 15:25:07 +01:00
committed by GitHub
56 changed files with 556 additions and 414 deletions
+7 -2
View File
@@ -24,6 +24,13 @@ Janitorial Clean-ups:
Features:
* be stricter with fds we receive for the fdstore: close them asynchronously
* be stricter with pid file and notify pids: don't allow them to be outside of cgroup, except if sender is privileged
* calenderspec: add support for week numbers and day numbers within a
year. This would allow us to define "bi-weekly" triggers safely.
* add support for recursive bpf firewalling as supported by the newest kernel
* add bpf-based implementation of devices cgroup controller logic for compat with cgroupsv2 as supported by newest kernel
@@ -49,8 +56,6 @@ Features:
the runtime dir as we maintain for the fdstore: i.e. keep it around as long
as the unit is running or has a job queued.
* hook up sd-bus' creds stuff with SO_PEERGROUPS
* add async version of sd_bus_add_match and make use of that
* support projid-based quota in machinectl for containers, and then drop
+2 -2
View File
@@ -274,9 +274,9 @@ static int fork_and_exec_process(const char* child, char** argv, char **env, int
if (!joined)
return log_oom();
r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child_pid);
r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
/* In the child */
exec_process(child, argv, env, fd, 1);
+31 -11
View File
@@ -32,32 +32,52 @@
#include "util.h"
int asynchronous_job(void* (*func)(void *p), void *arg) {
sigset_t ss, saved_ss;
pthread_attr_t a;
pthread_t t;
int r;
int r, k;
/* It kinda sucks that we have to resort to threads to
* implement an asynchronous sync(), but well, such is
* life.
*
* Note that issuing this command right before exiting a
* process will cause the process to wait for the sync() to
* complete. This function hence is nicely asynchronous really
* only in long running processes. */
/* It kinda sucks that we have to resort to threads to implement an asynchronous close(), but well, such is
* life. */
r = pthread_attr_init(&a);
if (r > 0)
return -r;
r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
if (r > 0)
if (r > 0) {
r = -r;
goto finish;
}
if (sigfillset(&ss) < 0) {
r = -errno;
goto finish;
}
/* Block all signals before forking off the thread, so that the new thread is started with all signals
* blocked. This way the existence of the new thread won't affect signal handling in other threads. */
r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
if (r > 0) {
r = -r;
goto finish;
}
r = pthread_create(&t, &a, func, arg);
k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
if (r > 0)
r = -r;
else if (k > 0)
r = -k;
else
r = 0;
finish:
pthread_attr_destroy(&a);
return -r;
return r;
}
int asynchronous_sync(pid_t *ret_pid) {
+7 -9
View File
@@ -156,6 +156,11 @@ static void fix_year(CalendarComponent *c) {
int calendar_spec_normalize(CalendarSpec *c) {
assert(c);
if (streq_ptr(c->timezone, "UTC")) {
c->utc = true;
c->timezone = mfree(c->timezone);
}
if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS)
c->weekdays_bits = -1;
@@ -1349,7 +1354,6 @@ typedef struct SpecNextResult {
int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next) {
SpecNextResult *shared, tmp;
pid_t pid;
int r;
if (isempty(spec->timezone))
@@ -1359,7 +1363,7 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
if (shared == MAP_FAILED)
return negative_errno();
r = safe_fork("(sd-calendar)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG, &pid);
r = safe_fork("(sd-calendar)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
@@ -1377,14 +1381,8 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(pid, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
}
tmp = *shared;
if (munmap(shared, sizeof *shared) != 0)
if (munmap(shared, sizeof *shared) < 0)
return negative_errno();
if (tmp.return_value == 0)
+7 -18
View File
@@ -55,9 +55,9 @@ static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
return 0;
}
r = safe_fork("(direxec)", FORK_DEATHSIG, &_pid);
r = safe_fork("(direxec)", FORK_DEATHSIG|FORK_LOG, &_pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
char *_argv[2];
@@ -82,7 +82,6 @@ static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
_exit(EXIT_FAILURE);
}
log_debug("Spawned %s as " PID_FMT ".", path, _pid);
*pid = _pid;
return 1;
}
@@ -147,7 +146,7 @@ static int do_execute(
return log_oom();
t = NULL;
} else {
r = wait_for_terminate_and_warn(t, pid, true);
r = wait_for_terminate_and_check(t, pid, WAIT_LOG);
if (r < 0)
continue;
@@ -177,7 +176,7 @@ static int do_execute(
t = hashmap_remove(pids, PID_TO_PTR(pid));
assert(t);
wait_for_terminate_and_warn(t, pid, true);
(void) wait_for_terminate_and_check(t, pid, WAIT_LOG);
}
return 0;
@@ -190,10 +189,9 @@ int execute_directories(
void* const callback_args[_STDOUT_CONSUME_MAX],
char *argv[]) {
pid_t executor_pid;
char *name;
char **dirs = (char**) directories;
_cleanup_close_ int fd = -1;
char *name;
int r;
assert(!strv_isempty(dirs));
@@ -216,23 +214,14 @@ int execute_directories(
* them to finish. Optionally a timeout is applied. If a file with the same name
* exists in more than one directory, the earliest one wins. */
r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &executor_pid);
r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv);
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
r = wait_for_terminate_and_warn(name, executor_pid, true);
if (r < 0)
return log_error_errno(r, "Execution failed: %m");
if (r > 0) {
/* non-zero return code from child */
log_error("Forker process failed.");
return -EREMOTEIO;
}
if (!callbacks)
return 0;
+17 -3
View File
@@ -62,16 +62,28 @@ int write_string_stream_ts(
WriteStringFileFlags flags,
struct timespec *ts) {
bool needs_nl;
assert(f);
assert(line);
if (ferror(f))
return -EIO;
needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n");
if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) {
/* If STDIO buffering was disabled, then let's append the newline character to the string itself, so
* that the write goes out in one go, instead of two */
line = strjoina(line, "\n");
needs_nl = false;
}
if (fputs(line, f) == EOF)
return -errno;
if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"))
if (needs_nl)
if (fputc('\n', f) == EOF)
return -errno;
@@ -914,14 +926,16 @@ int write_env_file(const char *fname, char **l) {
}
int executable_is_script(const char *path, char **interpreter) {
int r;
_cleanup_free_ char *line = NULL;
int len;
size_t len;
char *ans;
int r;
assert(path);
r = read_one_line_file(path, &line);
if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */
return 0;
if (r < 0)
return r;
+4
View File
@@ -621,6 +621,10 @@ struct btrfs_ioctl_quota_ctl_args {
# define SO_REUSEPORT 15
#endif
#ifndef SO_PEERGROUPS
# define SO_PEERGROUPS 59
#endif
#ifndef EVIOCREVOKE
# define EVIOCREVOKE _IOW('E', 0x91, int)
#endif
+69 -31
View File
@@ -687,32 +687,43 @@ int wait_for_terminate(pid_t pid, siginfo_t *status) {
* A warning is emitted if the process terminates abnormally,
* and also if it returns non-zero unless check_exit_code is true.
*/
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
int r;
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
_cleanup_free_ char *buffer = NULL;
siginfo_t status;
int r, prio;
assert(name);
assert(pid > 1);
if (!name) {
r = get_process_comm(pid, &buffer);
if (r < 0)
log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pid);
else
name = buffer;
}
prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG;
r = wait_for_terminate(pid, &status);
if (r < 0)
return log_warning_errno(r, "Failed to wait for %s: %m", name);
return log_full_errno(prio, r, "Failed to wait for %s: %m", strna(name));
if (status.si_code == CLD_EXITED) {
if (status.si_status != 0)
log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
"%s failed with error code %i.", name, status.si_status);
if (status.si_status != EXIT_SUCCESS)
log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG,
"%s failed with exit status %i.", strna(name), status.si_status);
else
log_debug("%s succeeded.", name);
return status.si_status;
} else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) {
log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
log_full(prio, "%s terminated by signal %s.", strna(name), signal_to_string(status.si_status));
return -EPROTO;
}
log_warning("%s failed due to unknown reason.", name);
log_full(prio, "%s failed due to unknown reason.", strna(name));
return -EPROTO;
}
@@ -1083,7 +1094,7 @@ int ioprio_parse_priority(const char *s, int *ret) {
static pid_t cached_pid = CACHED_PID_UNSET;
static void reset_cached_pid(void) {
void reset_cached_pid(void) {
/* Invoked in the child after a fork(), i.e. at the first moment the PID changed */
cached_pid = CACHED_PID_UNSET;
}
@@ -1150,46 +1161,72 @@ int safe_fork_full(
pid_t *ret_pid) {
pid_t original_pid, pid;
sigset_t saved_ss;
sigset_t saved_ss, ss;
bool block_signals;
int r;
int prio, r;
/* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always
* returns the child's PID in *ret_pid. Returns == 0 in the child, and > 0 in the parent. */
prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG;
original_pid = getpid_cached();
block_signals = flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG);
if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG)) {
if (block_signals) {
sigset_t ss;
/* We temporarily block all signals, so that the new child has them blocked initially. This way, we can
* be sure that SIGTERMs are not lost we might send to the child. */
/* We temporarily block all signals, so that the new child has them blocked initially. This way, we can be sure
* that SIGTERMs are not lost we might send to the child. */
if (sigfillset(&ss) < 0)
return log_debug_errno(errno, "Failed to reset signal set: %m");
return log_full_errno(prio, errno, "Failed to reset signal set: %m");
if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
return log_debug_errno(errno, "Failed to reset signal mask: %m");
block_signals = true;
} else if (flags & FORK_WAIT) {
/* Let's block SIGCHLD at least, so that we can safely watch for the child process */
if (sigemptyset(&ss) < 0)
return log_full_errno(prio, errno, "Failed to clear signal set: %m");
if (sigaddset(&ss, SIGCHLD) < 0)
return log_full_errno(prio, errno, "Failed to add SIGCHLD to signal set: %m");
block_signals = true;
}
pid = fork();
if (block_signals)
if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
return log_full_errno(prio, errno, "Failed to set signal mask: %m");
if (flags & FORK_NEW_MOUNTNS)
pid = raw_clone(SIGCHLD|CLONE_NEWNS);
else
pid = fork();
if (pid < 0) {
r = -errno;
if (block_signals) /* undo what we did above */
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
return log_debug_errno(r, "Failed to fork: %m");
return log_full_errno(prio, r, "Failed to fork: %m");
}
if (pid > 0) {
/* We are in the parent process */
log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
if (flags & FORK_WAIT) {
r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
if (r < 0)
return r;
if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
return -EPROTO;
}
if (block_signals) /* undo what we did above */
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
log_debug("Sucessfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
if (ret_pid)
*ret_pid = pid;
@@ -1207,31 +1244,32 @@ int safe_fork_full(
if (name) {
r = rename_process(name);
if (r < 0)
log_debug_errno(r, "Failed to rename process, ignoring: %m");
log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG,
r, "Failed to rename process, ignoring: %m");
}
if (flags & FORK_DEATHSIG)
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) {
log_debug_errno(errno, "Failed to set death signal: %m");
log_full_errno(prio, errno, "Failed to set death signal: %m");
_exit(EXIT_FAILURE);
}
if (flags & FORK_RESET_SIGNALS) {
r = reset_all_signal_handlers();
if (r < 0) {
log_debug_errno(r, "Failed to reset signal handlers: %m");
log_full_errno(prio, r, "Failed to reset signal handlers: %m");
_exit(EXIT_FAILURE);
}
/* This implicitly undoes the signal mask stuff we did before the fork()ing above */
r = reset_signal_mask();
if (r < 0) {
log_debug_errno(r, "Failed to reset signal mask: %m");
log_full_errno(prio, r, "Failed to reset signal mask: %m");
_exit(EXIT_FAILURE);
}
} else if (block_signals) { /* undo what we did above */
if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
log_debug_errno(errno, "Failed to restore signal mask: %m");
log_full_errno(prio, errno, "Failed to restore signal mask: %m");
_exit(EXIT_FAILURE);
}
}
@@ -1257,7 +1295,7 @@ int safe_fork_full(
r = close_all_fds(except_fds, n_except_fds);
if (r < 0) {
log_debug_errno(r, "Failed to close all file descriptors: %m");
log_full_errno(prio, r, "Failed to close all file descriptors: %m");
_exit(EXIT_FAILURE);
}
}
@@ -1271,7 +1309,7 @@ int safe_fork_full(
if (flags & FORK_NULL_STDIO) {
r = make_null_stdio();
if (r < 0) {
log_debug_errno(r, "Failed to connect stdin/stdout to /dev/null: %m");
log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
_exit(EXIT_FAILURE);
}
}
+14 -1
View File
@@ -61,7 +61,16 @@ int get_process_environ(pid_t pid, char **environ);
int get_process_ppid(pid_t pid, pid_t *ppid);
int wait_for_terminate(pid_t pid, siginfo_t *status);
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
typedef enum WaitFlags {
WAIT_LOG_ABNORMAL = 1U << 0,
WAIT_LOG_NON_ZERO_EXIT_STATUS = 1U << 1,
/* A shortcut for requesting the most complete logging */
WAIT_LOG = WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS,
} WaitFlags;
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags);
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout);
void sigkill_wait(pid_t pid);
@@ -147,6 +156,7 @@ static inline int sched_policy_to_string_alloc_with_check(int n, char **s) {
int ioprio_parse_priority(const char *s, int *ret);
pid_t getpid_cached(void);
void reset_cached_pid(void);
int must_be_root(void);
@@ -156,6 +166,9 @@ typedef enum ForkFlags {
FORK_DEATHSIG = 1U << 2,
FORK_NULL_STDIO = 1U << 3,
FORK_REOPEN_LOG = 1U << 4,
FORK_LOG = 1U << 5,
FORK_WAIT = 1U << 6,
FORK_NEW_MOUNTNS = 1U << 7,
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
+22 -20
View File
@@ -30,28 +30,27 @@
* raw_clone() - uses clone to create a new process with clone flags
* @flags: Flags to pass to the clone system call
*
* Uses the clone system call to create a new process with the cloning
* flags and termination signal passed in the flags parameter. Opposed
* to glibc's clone funtion, using this function does not set up a
* separate stack for the child, but relies on copy-on-write semantics
* on the one stack at a common virtual address, just as fork does.
* Uses the clone system call to create a new process with the cloning flags and termination signal passed in the flags
* parameter. Opposed to glibc's clone funtion, using this function does not set up a separate stack for the child, but
* relies on copy-on-write semantics on the one stack at a common virtual address, just as fork does.
*
* To obtain copy-on-write semantics, flags must not contain CLONE_VM,
* and thus CLONE_THREAD and CLONE_SIGHAND (which require CLONE_VM) are
* not usabale.
* Additionally, as this function does not pass the ptid, newtls and ctid
* parameters to the kernel, flags must not contain CLONE_PARENT_SETTID,
* CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
* To obtain copy-on-write semantics, flags must not contain CLONE_VM, and thus CLONE_THREAD and CLONE_SIGHAND (which
* require CLONE_VM) are not usable.
*
* Additionally, as this function does not pass the ptid, newtls and ctid parameters to the kernel, flags must not
* contain CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
*
* Returns: 0 in the child process and the child process id in the parent.
*/
static inline int raw_clone(unsigned long flags) {
static inline pid_t raw_clone(unsigned long flags) {
pid_t ret;
assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
/* On s390/s390x and cris the order of the first and second arguments
* of the raw clone() system call is reversed. */
return (int) syscall(__NR_clone, NULL, flags);
ret = (pid_t) syscall(__NR_clone, NULL, flags);
#elif defined(__sparc__) && defined(__arch64__)
{
/**
@@ -60,8 +59,8 @@ static inline int raw_clone(unsigned long flags) {
* %o1. Inline assembly is needed to get the flag returned
* in %o1.
*/
int in_child;
int child_pid;
int in_child, child_pid;
asm volatile("mov %2, %%g1\n\t"
"mov %3, %%o0\n\t"
"mov 0 , %%o1\n\t"
@@ -71,12 +70,15 @@ static inline int raw_clone(unsigned long flags) {
"=r"(in_child), "=r"(child_pid) :
"i"(__NR_clone), "r"(flags) :
"%o1", "%o0", "%g1" );
if (in_child)
return 0;
else
return child_pid;
ret = in_child ? 0 : child_pid;
}
#else
return (int) syscall(__NR_clone, flags, NULL);
ret = (pid_t) syscall(__NR_clone, flags, NULL);
#endif
if (ret == 0)
reset_cached_pid();
return ret;
}
+49 -27
View File
@@ -967,58 +967,80 @@ int getpeercred(int fd, struct ucred *ucred) {
if (n != sizeof(struct ucred))
return -EIO;
/* Check if the data is actually useful and not suppressed due
* to namespacing issues */
if (u.pid <= 0)
return -ENODATA;
if (u.uid == UID_INVALID)
return -ENODATA;
if (u.gid == GID_INVALID)
/* Check if the data is actually useful and not suppressed due to namespacing issues */
if (!pid_is_valid(u.pid))
return -ENODATA;
/* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
* receiving in "invalid" user/group we get the overflow UID/GID. */
*ucred = u;
return 0;
}
int getpeersec(int fd, char **ret) {
_cleanup_free_ char *s = NULL;
socklen_t n = 64;
char *s;
int r;
assert(fd >= 0);
assert(ret);
s = new0(char, n);
if (!s)
return -ENOMEM;
for (;;) {
s = new0(char, n+1);
if (!s)
return -ENOMEM;
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
if (r < 0) {
free(s);
if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0)
break;
if (errno != ERANGE)
return -errno;
s = new0(char, n);
if (!s)
return -ENOMEM;
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
if (r < 0) {
free(s);
return -errno;
}
s = mfree(s);
}
if (isempty(s)) {
free(s);
if (isempty(s))
return -EOPNOTSUPP;
}
*ret = s;
s = NULL;
return 0;
}
int getpeergroups(int fd, gid_t **ret) {
socklen_t n = sizeof(gid_t) * 64;
_cleanup_free_ gid_t *d = NULL;
assert(fd);
assert(ret);
for (;;) {
d = malloc(n);
if (!d)
return -ENOMEM;
if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0)
break;
if (errno != ERANGE)
return -errno;
d = mfree(d);
}
assert_se(n % sizeof(gid_t) == 0);
n /= sizeof(gid_t);
if ((socklen_t) (int) n != n)
return -E2BIG;
*ret = d;
d = NULL;
return (int) n;
}
int send_one_fd_sa(
int transport_fd,
int fd,
+1
View File
@@ -138,6 +138,7 @@ bool address_label_valid(const char *p);
int getpeercred(int fd, struct ucred *ucred);
int getpeersec(int fd, char **ret);
int getpeergroups(int fd, gid_t **ret);
int send_one_fd_sa(int transport_fd,
int fd,
+4 -6
View File
@@ -1093,7 +1093,6 @@ int ptsname_namespace(int pty, char **ret) {
int openpt_in_namespace(pid_t pid, int flags) {
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
siginfo_t si;
pid_t child;
int r;
@@ -1133,10 +1132,10 @@ int openpt_in_namespace(pid_t pid, int flags) {
pair[1] = safe_close(pair[1]);
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-openpt)", child, 0);
if (r < 0)
return r;
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
if (r != EXIT_SUCCESS)
return -EIO;
return receive_one_fd(pair[0], 0);
@@ -1145,7 +1144,6 @@ int openpt_in_namespace(pid_t pid, int flags) {
int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
siginfo_t si;
pid_t child;
int r;
@@ -1180,10 +1178,10 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
pair[1] = safe_close(pair[1]);
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-terminal)", child, 0);
if (r < 0)
return r;
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
if (r != EXIT_SUCCESS)
return -EIO;
return receive_one_fd(pair[0], 0);
+1 -8
View File
@@ -886,7 +886,6 @@ typedef struct ParseTimestampResult {
int parse_timestamp(const char *t, usec_t *usec) {
char *last_space, *tz = NULL;
ParseTimestampResult *shared, tmp;
pid_t pid;
int r;
last_space = strrchr(t, ' ');
@@ -900,7 +899,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
if (shared == MAP_FAILED)
return negative_errno();
r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG, &pid);
r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
@@ -928,12 +927,6 @@ int parse_timestamp(const char *t, usec_t *usec) {
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(pid, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
}
tmp = *shared;
if (munmap(shared, sizeof *shared) != 0)
return negative_errno();
+3 -2
View File
@@ -358,8 +358,9 @@ char* gid_to_name(gid_t gid) {
}
int in_gid(gid_t gid) {
long ngroups_max;
gid_t *gids;
int ngroups_max, r, i;
int r, i;
if (getgid() == gid)
return 1;
@@ -373,7 +374,7 @@ int in_gid(gid_t gid) {
ngroups_max = sysconf(_SC_NGROUPS_MAX);
assert(ngroups_max > 0);
gids = alloca(sizeof(gid_t) * ngroups_max);
gids = newa(gid_t, ngroups_max);
r = getgroups(ngroups_max, gids);
if (r < 0)
+3 -6
View File
@@ -1823,7 +1823,6 @@ static int setup_private_users(uid_t uid, gid_t gid) {
_cleanup_close_ int unshare_ready_fd = -1;
_cleanup_(sigkill_waitp) pid_t pid = 0;
uint64_t c = 1;
siginfo_t si;
ssize_t n;
int r;
@@ -1963,13 +1962,11 @@ static int setup_private_users(uid_t uid, gid_t gid) {
if (n != 0) /* on success we should have read 0 bytes */
return -EIO;
r = wait_for_terminate(pid, &si);
r = wait_for_terminate_and_check("(sd-userns)", pid, 0);
pid = 0;
if (r < 0)
return r;
pid = 0;
/* If something strange happened with the child, let's consider this fatal, too */
if (si.si_code != CLD_EXITED || si.si_status != 0)
if (r != EXIT_SUCCESS) /* If something strange happened with the child, let's consider this fatal, too */
return -EIO;
return 0;
+2 -7
View File
@@ -483,15 +483,10 @@ int main(int argc, char *argv[]) {
if (!in_container) {
/* We cheat and exec kexec to avoid doing all its work */
pid_t pid;
log_info("Rebooting with kexec.");
r = safe_fork("(sd-kexec)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &pid);
if (r < 0)
log_error_errno(r, "Failed to fork: %m");
r = safe_fork("(sd-kexec)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_WAIT, NULL);
if (r == 0) {
const char * const args[] = {
KEXEC, "-e", NULL
};
@@ -502,7 +497,7 @@ int main(int argc, char *argv[]) {
_exit(EXIT_FAILURE);
}
(void) wait_for_terminate_and_warn("kexec", pid, true);
/* If we are still running, then the kexec can't have worked, let's fall through */
}
cmd = RB_AUTOBOOT;
+2 -2
View File
@@ -1554,7 +1554,7 @@ static int socket_address_listen_in_cgroup(
fd = receive_one_fd(pair[0], 0);
/* We synchronously wait for the helper, as it shouldn't be slow */
r = wait_for_terminate_and_warn("listen-cgroup-helper", pid, false);
r = wait_for_terminate_and_check("(sd-listen)", pid, WAIT_LOG_ABNORMAL);
if (r < 0) {
safe_close(fd);
return r;
@@ -2898,7 +2898,7 @@ static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) {
cfd = receive_one_fd(pair[0], 0);
/* We synchronously wait for the helper, as it shouldn't be slow */
r = wait_for_terminate_and_warn("accept-cgroup-helper", pid, false);
r = wait_for_terminate_and_check("(sd-accept)", pid, WAIT_LOG_ABNORMAL);
if (r < 0) {
safe_close(cfd);
return r;
+4 -4
View File
@@ -389,9 +389,9 @@ static int remount_with_timeout(MountPoint *m, char *options, int *n_failed) {
* fork a child process and set a timeout. If the timeout
* lapses, the assumption is that that particular remount
* failed. */
r = safe_fork("(sd-remount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &pid);
r = safe_fork("(sd-remount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
log_info("Remounting '%s' read-only in with options '%s'.", m->path, options);
@@ -423,9 +423,9 @@ static int umount_with_timeout(MountPoint *m, bool *changed) {
* fork a child process and set a timeout. If the timeout
* lapses, the assumption is that that particular umount
* failed. */
r = safe_fork("(sd-umount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &pid);
r = safe_fork("(sd-umount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
log_info("Unmounting '%s'.", m->path);
+3 -12
View File
@@ -885,7 +885,6 @@ static int run_gdb(sd_journal *j) {
_cleanup_free_ char *exe = NULL, *path = NULL;
bool unlink_path = false;
const char *data;
siginfo_t st;
size_t len;
pid_t pid;
int r;
@@ -928,24 +927,16 @@ static int run_gdb(sd_journal *j) {
/* Don't interfere with gdb and its handling of SIGINT. */
(void) ignore_signals(SIGINT, -1);
r = safe_fork("(gdb)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS, &pid);
if (r < 0) {
log_error_errno(r, "Failed to fork(): %m");
r = safe_fork("(gdb)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
goto finish;
}
if (r == 0) {
execlp("gdb", "gdb", exe, path, NULL);
log_error_errno(errno, "Failed to invoke gdb: %m");
_exit(EXIT_FAILURE);
}
r = wait_for_terminate(pid, &st);
if (r < 0) {
log_error_errno(r, "Failed to wait for gdb: %m");
goto finish;
}
r = st.si_code == CLD_EXITED ? st.si_status : 255;
r = wait_for_terminate_and_check("gdb", pid, WAIT_LOG_ABNORMAL);
finish:
(void) default_signals(SIGINT, -1);
+3 -3
View File
@@ -186,16 +186,16 @@ static int found_override(const char *top, const char *bottom) {
fflush(stdout);
r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS, &pid);
r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(pid, "Failed to fork off diff: %m");
return r;
if (r == 0) {
execlp("diff", "diff", "-us", "--", bottom, top, NULL);
log_error_errno(errno, "Failed to execute diff: %m");
_exit(EXIT_FAILURE);
}
wait_for_terminate_and_warn("diff", pid, false);
(void) wait_for_terminate_and_check("diff", pid, WAIT_LOG_ABNORMAL);
putchar('\n');
return r;
+14 -25
View File
@@ -284,9 +284,8 @@ int main(int argc, char *argv[]) {
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
const char *device, *type;
bool root_directory;
siginfo_t status;
struct stat st;
int r;
int r, exit_status;
pid_t pid;
if (argc > 2) {
@@ -392,11 +391,9 @@ int main(int argc, char *argv[]) {
}
}
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
if (r < 0) {
log_error_errno(r, "fork(): %m");
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
goto finish;
}
if (r == 0) {
char dash_c[STRLEN("-C") + DECIMAL_STR_MAX(int) + 1];
int progress_socket = -1;
@@ -451,38 +448,30 @@ int main(int argc, char *argv[]) {
(void) process_progress(progress_pipe[0]);
progress_pipe[0] = -1;
r = wait_for_terminate(pid, &status);
if (r < 0) {
log_error_errno(r, "waitid(): %m");
exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL);
if (exit_status < 0) {
r = exit_status;
goto finish;
}
if (exit_status & ~1) {
log_error("fsck failed with exit status %i.", exit_status);
if (status.si_code != CLD_EXITED || (status.si_status & ~1)) {
if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED))
log_error("fsck terminated by signal %s.", signal_to_string(status.si_status));
else if (status.si_code == CLD_EXITED)
log_error("fsck failed with error code %i.", status.si_status);
else
log_error("fsck failed due to unknown reason.");
r = -EINVAL;
if (status.si_code == CLD_EXITED && (status.si_status & FSCK_SYSTEM_SHOULD_REBOOT) && root_directory)
if ((exit_status & FSCK_SYSTEM_SHOULD_REBOOT) && root_directory) {
/* System should be rebooted. */
start_target(SPECIAL_REBOOT_TARGET, "replace-irreversibly");
else if (status.si_code == CLD_EXITED && (status.si_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED)))
r = -EINVAL;
} else if (exit_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED)) {
/* Some other problem */
start_target(SPECIAL_EMERGENCY_TARGET, "replace");
else {
r = -EINVAL;
} else {
log_warning("Ignoring error.");
r = 0;
}
} else
r = 0;
if (status.si_code == CLD_EXITED && (status.si_status & FSCK_ERROR_CORRECTED))
if (exit_status & FSCK_ERROR_CORRECTED)
(void) touch("/run/systemd/quotacheck");
finish:
+4 -4
View File
@@ -82,9 +82,9 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
if (pipe2(pipefd, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to create pipe for tar: %m");
r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork off tar: %m");
return r;
if (r == 0) {
int null_fd;
uint64_t retain =
@@ -151,9 +151,9 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
if (pipe2(pipefd, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to create pipe for tar: %m");
r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork off tar: %m");
return r;
if (r == 0) {
int null_fd;
uint64_t retain = (1ULL << CAP_DAC_OVERRIDE);
+1 -1
View File
@@ -190,7 +190,7 @@ static int tar_import_finish(TarImport *i) {
i->tar_fd = safe_close(i->tar_fd);
if (i->tar_pid > 0) {
r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
r = wait_for_terminate_and_check("tar", i->tar_pid, WAIT_LOG);
i->tar_pid = 0;
if (r < 0)
return r;
+4 -4
View File
@@ -463,9 +463,9 @@ int pull_verify(PullJob *main_job,
gpg_home_created = true;
r = safe_fork("(gpg)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(gpg)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork off gpg: %m");
return r;
if (r == 0) {
const char *cmd[] = {
"gpg",
@@ -542,11 +542,11 @@ int pull_verify(PullJob *main_job,
gpg_pipe[1] = safe_close(gpg_pipe[1]);
r = wait_for_terminate_and_warn("gpg", pid, true);
r = wait_for_terminate_and_check("gpg", pid, WAIT_LOG_ABNORMAL);
pid = 0;
if (r < 0)
goto finish;
if (r > 0) {
if (r != EXIT_SUCCESS) {
log_error("DOWNLOAD INVALID: Signature verification failed.");
r = -EBADMSG;
} else {
+2 -2
View File
@@ -333,11 +333,11 @@ static void tar_pull_job_on_finished(PullJob *j) {
goto finish;
if (i->tar_pid > 0) {
r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
r = wait_for_terminate_and_check("tar", i->tar_pid, WAIT_LOG);
i->tar_pid = 0;
if (r < 0)
goto finish;
if (r > 0) {
if (r != EXIT_SUCCESS) {
r = -EIO;
goto finish;
}
+2 -2
View File
@@ -87,10 +87,10 @@ static int spawn_child(const char* child, char** argv) {
if (pipe(fd) < 0)
return log_error_errno(errno, "Failed to create pager pipe: %m");
r = safe_fork("(remote)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child_pid);
r = safe_fork("(remote)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid);
if (r < 0) {
safe_close_pair(fd);
return log_error_errno(r, "Failed to fork: %m");
return r;
}
/* In the child */
+14
View File
@@ -247,11 +247,25 @@ int journal_file_set_offline(JournalFile *f, bool wait) {
if (wait) /* Without using a thread if waiting. */
journal_file_set_offline_internal(f);
else {
sigset_t ss, saved_ss;
int k;
if (sigfillset(&ss) < 0)
return -errno;
r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
if (r > 0)
return -r;
r = pthread_create(&f->offline_thread, NULL, journal_file_set_offline_thread, f);
k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
if (r > 0) {
f->offline_state = OFFLINE_JOINED;
return -r;
}
if (k > 0)
return -k;
}
return 0;
+9 -2
View File
@@ -241,6 +241,13 @@ void server_space_usage_message(Server *s, JournalStorage *storage) {
NULL);
}
static bool uid_for_system_journal(uid_t uid) {
/* Returns true if the specified UID shall get its data stored in the system journal*/
return uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY;
}
static void server_add_acls(JournalFile *f, uid_t uid) {
#if HAVE_ACL
int r;
@@ -248,7 +255,7 @@ static void server_add_acls(JournalFile *f, uid_t uid) {
assert(f);
#if HAVE_ACL
if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
if (uid_for_system_journal(uid))
return;
r = add_acls_for_user(f->fd, uid);
@@ -406,7 +413,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
if (s->runtime_journal)
return s->runtime_journal;
if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
if (uid_for_system_journal(uid))
return s->system_journal;
r = sd_id128_get_machine(&machine);
+6 -14
View File
@@ -31,9 +31,8 @@
int bus_container_connect_socket(sd_bus *b) {
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
pid_t child;
siginfo_t si;
int r, error_buf = 0;
pid_t child;
ssize_t n;
assert(b);
@@ -97,21 +96,20 @@ int bus_container_connect_socket(sd_bus *b) {
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(grandchild, &si);
r = wait_for_terminate_and_check("(sd-buscntr2)", grandchild, 0);
if (r < 0)
_exit(EXIT_FAILURE);
if (si.si_code != CLD_EXITED)
_exit(EXIT_FAILURE);
_exit(si.si_status);
_exit(r);
}
pair[1] = safe_close(pair[1]);
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-buscntr)", child, 0);
if (r < 0)
return r;
if (r != EXIT_SUCCESS)
return -EPROTO;
n = read(pair[0], &error_buf, sizeof(error_buf));
if (n < 0)
@@ -131,11 +129,5 @@ int bus_container_connect_socket(sd_bus *b) {
return -error_buf;
}
if (si.si_code != CLD_EXITED)
return -EIO;
if (si.si_status != EXIT_SUCCESS)
return -EIO;
return bus_socket_start_auth(b);
}
+16 -5
View File
@@ -555,15 +555,16 @@ _public_ int sd_bus_get_name_creds(
static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
pid_t pid = 0;
bool do_label;
bool do_label, do_groups;
int r;
assert(bus);
do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS);
/* Avoid allocating anything if we have no chance of returning useful data */
if (!bus->ucred_valid && !do_label)
if (!bus->ucred_valid && !do_label && !do_groups)
return -ENODATA;
c = bus_creds_new();
@@ -571,17 +572,17 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **
return -ENOMEM;
if (bus->ucred_valid) {
if (bus->ucred.pid > 0) {
if (pid_is_valid(bus->ucred.pid)) {
pid = c->pid = bus->ucred.pid;
c->mask |= SD_BUS_CREDS_PID & mask;
}
if (bus->ucred.uid != UID_INVALID) {
if (uid_is_valid(bus->ucred.uid)) {
c->euid = bus->ucred.uid;
c->mask |= SD_BUS_CREDS_EUID & mask;
}
if (bus->ucred.gid != GID_INVALID) {
if (gid_is_valid(bus->ucred.gid)) {
c->egid = bus->ucred.gid;
c->mask |= SD_BUS_CREDS_EGID & mask;
}
@@ -595,6 +596,16 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
}
if (do_groups) {
c->supplementary_gids = newdup(gid_t, bus->groups, bus->n_groups);
if (!c->supplementary_gids)
return -ENOMEM;
c->n_supplementary_gids = bus->n_groups;
c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
}
r = bus_creds_add_more(c, mask, pid, 0);
if (r < 0)
return r;
+2
View File
@@ -261,6 +261,8 @@ struct sd_bus {
struct ucred ucred;
char *label;
gid_t *groups;
size_t n_groups;
uint64_t creds_mask;
+14 -1
View File
@@ -603,14 +603,27 @@ static void bus_get_peercred(sd_bus *b) {
int r;
assert(b);
assert(!b->ucred_valid);
assert(!b->label);
assert(b->n_groups == (size_t) -1);
/* Get the peer for socketpair() sockets */
b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
/* Get the SELinux context of the peer */
r = getpeersec(b->input_fd, &b->label);
if (r < 0 && r != -EOPNOTSUPP)
if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
log_debug_errno(r, "Failed to determine peer security context: %m");
/* Get the list of auxiliary groups of the peer */
r = getpeergroups(b->input_fd, &b->groups);
if (r < 0) {
if (!IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
log_debug_errno(r, "Failed to determine peer groups list: %m");
b->n_groups = (size_t) -1;
} else
b->n_groups = (size_t) r;
}
static int bus_socket_start_auth_client(sd_bus *b) {
+3 -2
View File
@@ -134,6 +134,7 @@ static void bus_free(sd_bus *b) {
bus_close_fds(b);
free(b->label);
free(b->groups);
free(b->rbuffer);
free(b->unique_name);
free(b->auth_buffer);
@@ -185,6 +186,7 @@ _public_ int sd_bus_new(sd_bus **ret) {
r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
r->attach_flags |= KDBUS_ATTACH_NAMES;
r->original_pid = getpid_cached();
r->n_groups = (size_t) -1;
assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
@@ -3483,8 +3485,7 @@ _public_ int sd_bus_path_decode_many(const char *path, const char *path_template
}
va_end(list);
free(labels);
labels = NULL;
labels = mfree(labels);
return 1;
}
+23 -9
View File
@@ -398,11 +398,6 @@ static int handle_request(int out_fd, const Packet *packet, size_t length) {
static void* thread_worker(void *p) {
sd_resolve *resolve = p;
sigset_t fullset;
/* No signals in this thread please */
assert_se(sigfillset(&fullset) == 0);
assert_se(pthread_sigmask(SIG_BLOCK, &fullset, NULL) == 0);
/* Assign a pretty name to this thread */
(void) pthread_setname_np(pthread_self(), "sd-resolve");
@@ -437,8 +432,18 @@ static void* thread_worker(void *p) {
}
static int start_threads(sd_resolve *resolve, unsigned extra) {
sigset_t ss, saved_ss;
unsigned n;
int r;
int r, k;
if (sigfillset(&ss) < 0)
return -errno;
/* No signals in forked off threads please. We set the mask before forking, so that the threads never exist
* with a different mask than a fully blocked one */
r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
if (r > 0)
return -r;
n = resolve->n_outstanding + extra;
n = CLAMP(n, WORKERS_MIN, WORKERS_MAX);
@@ -446,13 +451,22 @@ static int start_threads(sd_resolve *resolve, unsigned extra) {
while (resolve->n_valid_workers < n) {
r = pthread_create(&resolve->workers[resolve->n_valid_workers], NULL, thread_worker, resolve);
if (r != 0)
return -r;
if (r > 0) {
r = -r;
goto finish;
}
resolve->n_valid_workers++;
}
return 0;
r = 0;
finish:
k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
if (k > 0 && r >= 0)
r = -k;
return r;
}
static bool resolve_pid_changed(sd_resolve *r) {
+3 -5
View File
@@ -266,11 +266,9 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS, &pid);
if (r < 0) {
log_error_errno(r, "Failed to fork: %m");
r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
return EXIT_FAILURE;
}
if (r == 0) {
/* Child */
execvp(argv[optind], argv + optind);
@@ -278,7 +276,7 @@ int main(int argc, char *argv[]) {
_exit(EXIT_FAILURE);
}
r = wait_for_terminate_and_warn(argv[optind], pid, true);
r = wait_for_terminate_and_check(argv[optind], pid, WAIT_LOG);
return r < 0 ? EXIT_FAILURE : r;
}
+9 -18
View File
@@ -228,7 +228,6 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
_cleanup_free_ char *us = NULL, *them = NULL;
_cleanup_close_ int netns_fd = -1;
const char *p;
siginfo_t si;
pid_t child;
r = readlink_malloc("/proc/self/ns/net", &us);
@@ -337,10 +336,10 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
return r;
}
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-addr)", child, 0);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
if (r != EXIT_SUCCESS)
return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
break;
}
@@ -379,7 +378,6 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
_cleanup_close_ int mntns_fd = -1, root_fd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_fclose_ FILE *f = NULL;
siginfo_t si;
pid_t child;
r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
@@ -429,12 +427,12 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
if (r < 0)
return r;
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-osrel)", child, 0);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
if (si.si_code == CLD_EXITED && si.si_status == EXIT_NOT_FOUND)
if (r == EXIT_NOT_FOUND)
return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information");
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
if (r != EXIT_SUCCESS)
return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
break;
@@ -840,7 +838,6 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
const char *dest, *src;
Machine *m = userdata;
struct stat st;
siginfo_t si;
pid_t child;
uid_t uid;
int r;
@@ -1046,17 +1043,12 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-bindmnt)", child, 0);
if (r < 0) {
r = sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
goto finish;
}
if (si.si_code != CLD_EXITED) {
r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
goto finish;
}
if (si.si_status != EXIT_SUCCESS) {
if (r != EXIT_SUCCESS) {
if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r))
r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m");
else
@@ -1268,7 +1260,6 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
case MACHINE_CONTAINER: {
_cleanup_close_ int mntns_fd = -1, root_fd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
siginfo_t si;
pid_t child;
r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
@@ -1304,10 +1295,10 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
pair[1] = safe_close(pair[1]);
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-openroot)", child, 0);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
if (r != EXIT_SUCCESS)
return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
fd = receive_one_fd(pair[0], MSG_DONTWAIT);
+4 -4
View File
@@ -43,9 +43,9 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
if (pipe2(pipe_fds, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to allocate pipe: %m");
r = safe_fork("(getent)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(getent)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork getent child: %m");
return r;
if (r == 0) {
int nullfd;
char *empty_env = NULL;
@@ -133,7 +133,7 @@ int change_uid_gid(const char *user, char **_home) {
truncate_nl(line);
wait_for_terminate_and_warn("getent passwd", pid, true);
(void) wait_for_terminate_and_check("getent passwd", pid, WAIT_LOG);
x = strchr(line, ':');
if (!x) {
@@ -216,7 +216,7 @@ int change_uid_gid(const char *user, char **_home) {
truncate_nl(line);
wait_for_terminate_and_warn("getent initgroups", pid, true);
(void) wait_for_terminate_and_check("getent initgroups", pid, WAIT_LOG);
/* Skip over the username and subsequent separator whitespace */
x = line;
+5 -3
View File
@@ -3516,9 +3516,11 @@ static int run(int master,
}
/* Wait for the outer child. */
r = wait_for_terminate_and_warn("namespace helper", *pid, NULL);
if (r != 0)
return r < 0 ? r : -EIO;
r = wait_for_terminate_and_check("(sd-namespace)", *pid, WAIT_LOG_ABNORMAL);
if (r < 0)
return r;
if (r != EXIT_SUCCESS)
return -EIO;
/* And now retrieve the PID of the inner child. */
l = recv(pid_socket_pair[0], pid, sizeof *pid, 0);
+3 -3
View File
@@ -43,9 +43,9 @@ static int makefs(const char *type, const char *device) {
if (access(mkfs, X_OK) != 0)
return log_error_errno(errno, "%s is not executable: %m", mkfs);
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "fork(): %m");
return r;
if (r == 0) {
const char *cmdline[3] = { mkfs, device, NULL };
@@ -55,7 +55,7 @@ static int makefs(const char *type, const char *device) {
_exit(EXIT_FAILURE);
}
return wait_for_terminate_and_warn(mkfs, pid, true);
return wait_for_terminate_and_check(mkfs, pid, WAIT_LOG);
}
int main(int argc, char *argv[]) {
+7 -14
View File
@@ -71,14 +71,6 @@ static void test_files(void) {
}
int main(int argc, char *argv[]) {
static const char * const cmdline[] = {
QUOTACHECK,
"-anug",
NULL
};
pid_t pid;
int r;
if (argc > 1) {
@@ -106,12 +98,15 @@ int main(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
if (r < 0) {
log_error_errno(r, "fork(): %m");
r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
if (r < 0)
goto finish;
}
if (r == 0) {
static const char * const cmdline[] = {
QUOTACHECK,
"-anug",
NULL
};
/* Child */
@@ -119,8 +114,6 @@ int main(int argc, char *argv[]) {
_exit(EXIT_FAILURE); /* Operational error */
}
r = wait_for_terminate_and_warn("quotacheck", pid, true);
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
+2 -4
View File
@@ -87,11 +87,9 @@ int main(int argc, char *argv[]) {
log_debug("Remounting %s", me->mnt_dir);
r = safe_fork("(remount)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
if (r < 0) {
log_error_errno(r, "Failed to fork: %m");
r = safe_fork("(remount)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
goto finish;
}
if (r == 0) {
/* Child */
+4 -8
View File
@@ -560,8 +560,7 @@ void bus_verify_polkit_async_registry_free(Hashmap *registry) {
int bus_check_peercred(sd_bus *c) {
struct ucred ucred;
socklen_t l;
int fd;
int fd, r;
assert(c);
@@ -569,12 +568,9 @@ int bus_check_peercred(sd_bus *c) {
if (fd < 0)
return fd;
l = sizeof(struct ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
return -errno;
if (l != sizeof(struct ucred))
return -E2BIG;
r = getpeercred(fd, &ucred);
if (r < 0)
return r;
if (ucred.uid != 0 && ucred.uid != geteuid())
return -EPERM;
+7 -19
View File
@@ -1244,7 +1244,6 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
_cleanup_free_ char *hostname = NULL;
unsigned n_meta_initialized = 0, k;
int fds[2 * _META_MAX], r;
siginfo_t si;
BLOCK_SIGNALS(SIGCHLD);
@@ -1260,18 +1259,10 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
if (r < 0)
goto finish;
child = raw_clone(SIGCHLD|CLONE_NEWNS);
if (child < 0) {
r = -errno;
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS, &child);
if (r < 0)
goto finish;
}
if (child == 0) {
(void) reset_all_signal_handlers();
(void) reset_signal_mask();
assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
if (r == 0) {
/* Make sure we never propagate to the host */
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0)
_exit(EXIT_FAILURE);
@@ -1366,15 +1357,12 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
}
}
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-dissect)", child, 0);
child = 0;
if (r < 0)
goto finish;
child = 0;
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) {
r = -EPROTO;
goto finish;
}
if (r != EXIT_SUCCESS)
return -EPROTO;
free_and_replace(m->hostname, hostname);
m->machine_id = machine_id;
+5 -4
View File
@@ -1256,7 +1256,6 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, rootfd = -1;
pid_t pid, child;
siginfo_t si;
char buf[37];
ssize_t k;
int r;
@@ -1308,9 +1307,11 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
pair[1] = safe_close(pair[1]);
r = wait_for_terminate(child, &si);
if (r < 0 || si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
return r < 0 ? r : -EIO;
r = wait_for_terminate_and_check("(sd-bootid)", child, 0);
if (r < 0)
return r;
if (r != EXIT_SUCCESS)
return -EIO;
k = recv(pair[0], buf, 36, 0);
if (k != 36)
+6 -12
View File
@@ -79,7 +79,6 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) {
_cleanup_close_ int fd = -1;
struct statvfs ss;
pid_t pid = 0;
siginfo_t si;
int r;
/* We want to be able to make use of btrfs-specific file
@@ -141,24 +140,19 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) {
_exit(EXIT_FAILURE);
}
r = wait_for_terminate(pid, &si);
r = wait_for_terminate_and_check("mkfs", pid, 0);
pid = 0;
if (r < 0) {
sd_bus_error_set_errnof(error, r, "Failed to wait for mkfs.btrfs: %m");
goto fail;
}
pid = 0;
if (si.si_code != CLD_EXITED) {
r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs died abnormally.");
goto fail;
}
if (si.si_status == 99) {
if (r == 99) {
r = sd_bus_error_set_errnof(error, ENOENT, "Cannot set up /var/lib/machines, mkfs.btrfs is missing");
goto fail;
}
if (si.si_status != 0) {
r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs failed with error code %i", si.si_status);
if (r != EXIT_SUCCESS) {
r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "mkfs.btrfs failed with error code %i", r);
goto fail;
}
+13 -16
View File
@@ -42,6 +42,11 @@
static pid_t pager_pid = 0;
static int stored_stdout = -1;
static int stored_stderr = -1;
static bool stdout_redirected = false;
static bool stderr_redirected = false;
noreturn static void pager_fallback(void) {
int r;
@@ -54,11 +59,6 @@ noreturn static void pager_fallback(void) {
_exit(EXIT_SUCCESS);
}
static int stored_stdout = -1;
static int stored_stderr = -1;
static bool stdout_redirected = false;
static bool stderr_redirected = false;
int pager_open(bool no_pager, bool jump_to_end) {
_cleanup_close_pair_ int fd[2] = { -1, -1 };
const char *pager;
@@ -73,6 +73,9 @@ int pager_open(bool no_pager, bool jump_to_end) {
if (terminal_is_dumb())
return 0;
if (!is_main_thread())
return -EPERM;
pager = getenv("SYSTEMD_PAGER");
if (!pager)
pager = getenv("PAGER");
@@ -89,9 +92,9 @@ int pager_open(bool no_pager, bool jump_to_end) {
if (pipe2(fd, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to create pager pipe: %m");
r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pager_pid);
r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pager_pid);
if (r < 0)
return log_error_errno(r, "Failed to fork pager: %m");
return r;
if (r == 0) {
const char* less_opts, *less_charset;
@@ -190,7 +193,6 @@ int show_man_page(const char *desc, bool null_stdio) {
pid_t pid;
size_t k;
int r;
siginfo_t status;
k = strlen(desc);
@@ -208,9 +210,9 @@ int show_man_page(const char *desc, bool null_stdio) {
} else
args[1] = desc;
r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0), &pid);
r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
/* Child */
execvp(args[0], (char**) args);
@@ -218,10 +220,5 @@ int show_man_page(const char *desc, bool null_stdio) {
_exit(EXIT_FAILURE);
}
r = wait_for_terminate(pid, &status);
if (r < 0)
return r;
log_debug("Exit code %i status %i", status.si_code, status.si_status);
return status.si_status;
return wait_for_terminate_and_check(NULL, pid, 0);
}
+3
View File
@@ -40,6 +40,9 @@ int ask_password_agent_open(void) {
if (!isatty(STDIN_FILENO))
return 0;
if (!is_main_thread())
return -EPERM;
r = fork_agent("(sd-askpwagent)",
NULL, 0,
&agent_pid,
+3
View File
@@ -52,6 +52,9 @@ int polkit_agent_open(void) {
if (!isatty(STDIN_FILENO))
return 0;
if (!is_main_thread())
return -EPERM;
if (pipe2(pipe_fd, 0) < 0)
return -errno;
+3 -3
View File
@@ -83,9 +83,9 @@ static int fork_wait(const char* const cmdline[]) {
pid_t pid;
int r;
r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "fork(): %m");
return r;
if (r == 0) {
/* Child */
execv(cmdline[0], (char**) cmdline);
@@ -93,7 +93,7 @@ static int fork_wait(const char* const cmdline[]) {
_exit(EXIT_FAILURE); /* Operational error */
}
return wait_for_terminate_and_warn(cmdline[0], pid, false);
return wait_for_terminate_and_check(cmdline[0], pid, WAIT_LOG_ABNORMAL);
}
static void print_mode(const char* mode) {
+20 -32
View File
@@ -3539,9 +3539,9 @@ static int load_kexec_kernel(void) {
if (arg_dry_run)
return 0;
r = safe_fork("(kexec)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(kexec)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
const char* const args[] = {
@@ -3556,7 +3556,7 @@ static int load_kexec_kernel(void) {
_exit(EXIT_FAILURE);
}
return wait_for_terminate_and_warn("kexec", pid, true);
return wait_for_terminate_and_check("kexec", pid, WAIT_LOG);
}
static int set_exit_code(uint8_t code) {
@@ -6065,7 +6065,6 @@ static int enable_sysv_units(const char *verb, char **args) {
_cleanup_free_ char *p = NULL, *q = NULL, *l = NULL;
bool found_native = false, found_sysv;
siginfo_t status;
const char *name;
unsigned c = 1;
pid_t pid;
@@ -6119,9 +6118,9 @@ static int enable_sysv_units(const char *verb, char **args) {
if (!arg_quiet)
log_info("Executing: %s", l);
j = safe_fork("(sysv)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
if (j < 0)
return log_error_errno(j, "Failed to fork: %m");
return j;
if (j == 0) {
/* Child */
execv(argv[0], (char**) argv);
@@ -6129,27 +6128,21 @@ static int enable_sysv_units(const char *verb, char **args) {
_exit(EXIT_FAILURE);
}
j = wait_for_terminate(pid, &status);
j = wait_for_terminate_and_check("sysv-install", pid, WAIT_LOG_ABNORMAL);
if (j < 0)
return log_error_errno(j, "Failed to wait for child: %m");
return j;
if (streq(verb, "is-enabled")) {
if (j == EXIT_SUCCESS) {
if (!arg_quiet)
puts("enabled");
r = 1;
} else {
if (!arg_quiet)
puts("disabled");
}
if (status.si_code == CLD_EXITED) {
if (streq(verb, "is-enabled")) {
if (status.si_status == 0) {
if (!arg_quiet)
puts("enabled");
r = 1;
} else {
if (!arg_quiet)
puts("disabled");
}
} else if (status.si_status != 0)
return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */
} else {
log_error("Unexpected waitid() result.");
return -EPROTO;
}
} else if (j != EXIT_SUCCESS)
return -EBADE; /* We don't warn here, under the assumption the script already showed an explanation */
if (found_native)
continue;
@@ -6987,14 +6980,13 @@ static int unit_file_create_copy(
}
static int run_editor(char **paths) {
pid_t pid;
int r;
assert(paths);
r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
const char **args;
char *editor, **editor_args = NULL;
@@ -7057,10 +7049,6 @@ static int run_editor(char **paths) {
_exit(EXIT_FAILURE);
}
r = wait_for_terminate_and_warn("editor", pid, true);
if (r < 0)
return log_error_errno(r, "Failed to wait for child: %m");
return 0;
}
+10 -10
View File
@@ -141,7 +141,7 @@ static void test_filter_sets(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn(syscall_filter_sets[i].name, pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check(syscall_filter_sets[i].name, pid, WAIT_LOG) == EXIT_SUCCESS);
}
}
@@ -227,7 +227,7 @@ static void test_restrict_namespace(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("nsseccomp", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("nsseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_protect_sysctl(void) {
@@ -260,7 +260,7 @@ static void test_protect_sysctl(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("sysctlseccomp", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("sysctlseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_restrict_address_families(void) {
@@ -343,7 +343,7 @@ static void test_restrict_address_families(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("socketseccomp", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("socketseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_restrict_realtime(void) {
@@ -381,7 +381,7 @@ static void test_restrict_realtime(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("realtimeseccomp", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("realtimeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_memory_deny_write_execute_mmap(void) {
@@ -424,7 +424,7 @@ static void test_memory_deny_write_execute_mmap(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("memoryseccomp-mmap", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("memoryseccomp-mmap", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_memory_deny_write_execute_shmat(void) {
@@ -471,7 +471,7 @@ static void test_memory_deny_write_execute_shmat(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("memoryseccomp-shmat", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("memoryseccomp-shmat", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_restrict_archs(void) {
@@ -505,7 +505,7 @@ static void test_restrict_archs(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("archseccomp", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("archseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_load_syscall_filter_set_raw(void) {
@@ -596,7 +596,7 @@ static void test_load_syscall_filter_set_raw(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("syscallrawseccomp", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("syscallrawseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_lock_personality(void) {
@@ -643,7 +643,7 @@ static void test_lock_personality(void) {
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_warn("lockpersonalityseccomp", pid, true) == EXIT_SUCCESS);
assert_se(wait_for_terminate_and_check("lockpersonalityseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_filter_sets_ordered(void) {
+68
View File
@@ -18,6 +18,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include "alloc-util.h"
#include "async.h"
#include "fd-util.h"
@@ -474,6 +478,68 @@ static void test_in_addr_is_multicast(void) {
assert_se(in_addr_is_multicast(f, &b) == 0);
}
static void test_getpeercred_getpeergroups(void) {
int r;
r = safe_fork("(getpeercred)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
static const gid_t gids[] = { 3, 4, 5, 6, 7 };
gid_t *test_gids;
gid_t *peer_groups = NULL;
size_t n_test_gids;
uid_t test_uid;
gid_t test_gid;
struct ucred ucred;
int pair[2];
if (geteuid() == 0) {
test_uid = 1;
test_gid = 2;
test_gids = (gid_t*) gids;
n_test_gids = ELEMENTSOF(gids);
assert_se(setgroups(n_test_gids, test_gids) >= 0);
assert_se(setresgid(test_gid, test_gid, test_gid) >= 0);
assert_se(setresuid(test_uid, test_uid, test_uid) >= 0);
} else {
long ngroups_max;
test_uid = getuid();
test_gid = getgid();
ngroups_max = sysconf(_SC_NGROUPS_MAX);
assert(ngroups_max > 0);
test_gids = newa(gid_t, ngroups_max);
r = getgroups(ngroups_max, test_gids);
assert_se(r >= 0);
n_test_gids = (size_t) r;
}
assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0);
assert_se(getpeercred(pair[0], &ucred) >= 0);
assert_se(ucred.uid == test_uid);
assert_se(ucred.gid == test_gid);
assert_se(ucred.pid == getpid_cached());
r = getpeergroups(pair[0], &peer_groups);
assert_se(r >= 0 || IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT));
if (r >= 0) {
assert_se((size_t) r == n_test_gids);
assert_se(memcmp(peer_groups, test_gids, sizeof(gid_t) * n_test_gids) == 0);
}
safe_close_pair(pair);
}
}
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
@@ -502,5 +568,7 @@ int main(int argc, char *argv[]) {
test_in_addr_is_multicast();
test_getpeercred_getpeergroups();
return 0;
}
@@ -709,9 +709,9 @@ static int ask_on_this_console(const char *tty, pid_t *ret_pid, int argc, char *
sig.sa_handler = SIG_DFL;
assert_se(sigaction(SIGHUP, &sig, NULL) >= 0);
r = safe_fork("(sd-passwd)", FORK_RESET_SIGNALS, &pid);
r = safe_fork("(sd-passwd)", FORK_RESET_SIGNALS|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork process: %m");
return r;
if (r == 0) {
int ac;
+2 -4
View File
@@ -774,11 +774,9 @@ int udev_event_spawn(struct udev_event *event,
}
}
err = safe_fork("(spawn)", FORK_RESET_SIGNALS, &pid);
if (err < 0) {
log_error_errno(err, "fork of '%s' failed: %m", cmd);
err = safe_fork("(spawn)", FORK_RESET_SIGNALS|FORK_LOG, &pid);
if (err < 0)
goto out;
}
if (err == 0) {
char arg[UTIL_PATH_SIZE];
char *argv[128];
+8 -8
View File
@@ -153,15 +153,15 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m
log_debug("Executing \"%s\"...",
strnull((cmd = strv_join((char**) args, " "))));
r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &pid);
r = safe_fork("(loadkeys)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
execv(args[0], (char **) args);
_exit(EXIT_FAILURE);
}
return wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true);
return wait_for_terminate_and_check(KBD_LOADKEYS, pid, WAIT_LOG);
}
static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) {
@@ -193,15 +193,15 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
log_debug("Executing \"%s\"...",
strnull((cmd = strv_join((char**) args, " "))));
r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS, &pid);
r = safe_fork("(setfont)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
execv(args[0], (char **) args);
_exit(EXIT_FAILURE);
}
return wait_for_terminate_and_warn(KBD_SETFONT, pid, true);
return wait_for_terminate_and_check(KBD_SETFONT, pid, WAIT_LOG);
}
/*
@@ -452,8 +452,8 @@ int main(int argc, char **argv) {
log_warning_errno(r, "Failed to read /proc/cmdline: %m");
}
toggle_utf8_sysfs(utf8);
toggle_utf8(vc, fd, utf8);
(void) toggle_utf8_sysfs(utf8);
(void) toggle_utf8(vc, fd, utf8);
r = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap);
keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) == 0;