Compare commits
2 Commits
a54105a458
...
52dd6900e2
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 52dd6900e2 | |
Lennart Poettering | 319c8e3189 |
|
@ -1457,11 +1457,20 @@ int safe_fork_full(
|
||||||
sigset_t saved_ss, ss;
|
sigset_t saved_ss, ss;
|
||||||
_unused_ _cleanup_(restore_sigsetp) sigset_t *saved_ssp = NULL;
|
_unused_ _cleanup_(restore_sigsetp) sigset_t *saved_ssp = NULL;
|
||||||
bool block_signals = false, block_all = false, intermediary = false;
|
bool block_signals = false, block_all = false, intermediary = false;
|
||||||
|
_cleanup_free_ char *prefixed_name = NULL;
|
||||||
int prio, r;
|
int prio, r;
|
||||||
|
|
||||||
assert(!FLAGS_SET(flags, FORK_DETACH) || !ret_pid);
|
assert(!FLAGS_SET(flags, FORK_DETACH) || !ret_pid);
|
||||||
assert(!FLAGS_SET(flags, FORK_DETACH|FORK_WAIT));
|
assert(!FLAGS_SET(flags, FORK_DETACH|FORK_WAIT));
|
||||||
|
|
||||||
|
if (name && FLAGS_SET(flags, FORK_ARGV00_AT)) {
|
||||||
|
/* Optionally, ensure argv[0][0] is '@', in order to implement https://systemd.io/ROOT_STORAGE_DAEMONS */
|
||||||
|
prefixed_name = strjoin("@", name);
|
||||||
|
if (!prefixed_name)
|
||||||
|
return -ENOMEM;
|
||||||
|
name = prefixed_name;
|
||||||
|
}
|
||||||
|
|
||||||
/* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always
|
/* 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. */
|
* returns the child's PID in *ret_pid. Returns == 0 in the child, and > 0 in the parent. */
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,7 @@ typedef enum ForkFlags {
|
||||||
FORK_DETACH = 1 << 18, /* Double fork if needed to ensure PID1/subreaper is parent */
|
FORK_DETACH = 1 << 18, /* Double fork if needed to ensure PID1/subreaper is parent */
|
||||||
FORK_NEW_NETNS = 1 << 19, /* Run child in its own network namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */
|
FORK_NEW_NETNS = 1 << 19, /* Run child in its own network namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */
|
||||||
FORK_PACK_FDS = 1 << 20, /* Rearrange the passed FDs to be FD 3,4,5,etc. Updates the array in place (combine with FORK_CLOSE_ALL_FDS!) */
|
FORK_PACK_FDS = 1 << 20, /* Rearrange the passed FDs to be FD 3,4,5,etc. Updates the array in place (combine with FORK_CLOSE_ALL_FDS!) */
|
||||||
|
FORK_ARGV00_AT = 1 << 21, /* Prefix supplied name with '@', to exclude child process from final killing spree */
|
||||||
} ForkFlags;
|
} ForkFlags;
|
||||||
|
|
||||||
int safe_fork_full(
|
int safe_fork_full(
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "argv-util.h"
|
||||||
#include "async.h"
|
#include "async.h"
|
||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
@ -22,7 +23,14 @@ int asynchronous_sync(pid_t *ret_pid) {
|
||||||
* original process ever, and a thread would do that as the process can't exit with threads hanging in blocking
|
* original process ever, and a thread would do that as the process can't exit with threads hanging in blocking
|
||||||
* syscalls. */
|
* syscalls. */
|
||||||
|
|
||||||
r = safe_fork("(sd-sync)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|(ret_pid ? 0 : FORK_DETACH), ret_pid);
|
/* Note that we set argv[0][0] = '@' here if we are called from PID 1, which tells the
|
||||||
|
* switch-root/soft-reboot/shutdown killing spree to leave this process around. After all the killing
|
||||||
|
* is likely not going to work anyway, and given the limited scope of the child it's really not worth
|
||||||
|
* killing it. */
|
||||||
|
|
||||||
|
r = safe_fork("(sd-sync)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|(ret_pid ? 0 : FORK_DETACH)|(getpid_cached() == 1 ? FORK_ARGV00_AT : 0),
|
||||||
|
ret_pid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
|
@ -63,12 +71,23 @@ int asynchronous_fsync(int fd, pid_t *ret_pid) {
|
||||||
static int close_func(void *p) {
|
static int close_func(void *p) {
|
||||||
unsigned v = PTR_TO_UINT(p);
|
unsigned v = PTR_TO_UINT(p);
|
||||||
|
|
||||||
(void) prctl(PR_SET_NAME, (unsigned long*) "(sd-close)");
|
|
||||||
|
|
||||||
/* Note: 💣 This function is invoked in a child process created via glibc's clone() wrapper. In such
|
/* Note: 💣 This function is invoked in a child process created via glibc's clone() wrapper. In such
|
||||||
* children memory allocation is not allowed, since glibc does not release malloc mutexes in
|
* children memory allocation is not allowed, since glibc does not release malloc mutexes in
|
||||||
* clone() 💣 */
|
* clone() 💣 */
|
||||||
|
|
||||||
|
/* This is a poor man's version of rename_process(). We don't use the real thing to avoid any memory
|
||||||
|
* allocations. We set argv[0][0] to '@' if invoked by PID 1 to exclude us from the
|
||||||
|
* switch-root/soft-reboot/shutdown killing spree, since it would likely fail anyway, and with a
|
||||||
|
* process of such minimal scope is not really worh the effort anyway. */
|
||||||
|
const char *comm;
|
||||||
|
if (getppid() == 1) {
|
||||||
|
if (saved_argc >= 1 && !isempty(saved_argv[0]))
|
||||||
|
saved_argv[0][0] = '@';
|
||||||
|
comm = "@(sd-close)";
|
||||||
|
} else
|
||||||
|
comm = "(sd-close)";
|
||||||
|
(void) prctl(PR_SET_NAME, comm);
|
||||||
|
|
||||||
if (v & NEED_DOUBLE_FORK) {
|
if (v & NEED_DOUBLE_FORK) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
@ -139,9 +158,15 @@ int asynchronous_rm_rf(const char *p, RemoveFlags flags) {
|
||||||
assert(p);
|
assert(p);
|
||||||
|
|
||||||
/* Forks off a child that destroys the specified path. This will be best effort only, i.e. the child
|
/* Forks off a child that destroys the specified path. This will be best effort only, i.e. the child
|
||||||
* will attempt to do its thing, but we won't wait for it or check its success. */
|
* will attempt to do its thing, but we won't wait for it or check its success.
|
||||||
|
*
|
||||||
|
* We do set argv[0][0] = '@' here however (if we are invoked as PID 1), to ensure that the this is
|
||||||
|
* excluded from the switch-root/soft-reboot/poweroff killing spree, and can definitely complete it's
|
||||||
|
* job. */
|
||||||
|
|
||||||
r = safe_fork("(sd-rmrf)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DETACH, NULL);
|
r = safe_fork("(sd-rmrf)",
|
||||||
|
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DETACH|(getpid_cached() == 1 ? FORK_ARGV00_AT : 0),
|
||||||
|
/* ret_pid= */ NULL);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue