mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #10935 from poettering/rlimit-nofile-safe
Merged by hand to resolve a trivial conflict in TODO.
This commit is contained in:
4
TODO
4
TODO
@@ -29,6 +29,10 @@ Features:
|
||||
|
||||
* when we fork off generators and such, lower LIMIT_NOFILE soft limit to 1K
|
||||
|
||||
* Maybe introduce a helper safe_exec() or so, which is to execve() which
|
||||
safe_fork() is to fork(). And then make revert the RLIMIT_NOFILE soft limit
|
||||
to 1K implicitly, unless explicitly opted-out.
|
||||
|
||||
* rework seccomp/nnp logic that that even if User= is used in combination with
|
||||
a seccomp option we don't have to set NNP. For that, change uid first whil
|
||||
keeping CAP_SYS_ADMIN, then apply seccomp, the drop cap.
|
||||
|
||||
@@ -249,7 +249,7 @@ 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|FORK_LOG, &child_pid);
|
||||
r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &child_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
||||
@@ -149,6 +149,8 @@ basic_sources = files('''
|
||||
refcnt.h
|
||||
replace-var.c
|
||||
replace-var.h
|
||||
rlimit-util.c
|
||||
rlimit-util.h
|
||||
rm-rf.c
|
||||
rm-rf.h
|
||||
selinux-util.c
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "missing.h"
|
||||
#include "process-util.h"
|
||||
#include "raw-clone.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-table.h"
|
||||
@@ -1401,6 +1402,14 @@ int safe_fork_full(
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FORK_RLIMIT_NOFILE_SAFE) {
|
||||
r = rlimit_nofile_safe();
|
||||
if (r < 0) {
|
||||
log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret_pid)
|
||||
*ret_pid = getpid_cached();
|
||||
|
||||
@@ -1512,6 +1521,8 @@ int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret
|
||||
safe_close_above_stdio(fd);
|
||||
}
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
/* Count arguments */
|
||||
va_start(ap, path);
|
||||
for (n = 0; va_arg(ap, char*); n++)
|
||||
|
||||
@@ -142,15 +142,16 @@ void reset_cached_pid(void);
|
||||
int must_be_root(void);
|
||||
|
||||
typedef enum ForkFlags {
|
||||
FORK_RESET_SIGNALS = 1 << 0,
|
||||
FORK_CLOSE_ALL_FDS = 1 << 1,
|
||||
FORK_DEATHSIG = 1 << 2,
|
||||
FORK_NULL_STDIO = 1 << 3,
|
||||
FORK_REOPEN_LOG = 1 << 4,
|
||||
FORK_LOG = 1 << 5,
|
||||
FORK_WAIT = 1 << 6,
|
||||
FORK_NEW_MOUNTNS = 1 << 7,
|
||||
FORK_MOUNTNS_SLAVE = 1 << 8,
|
||||
FORK_RESET_SIGNALS = 1 << 0, /* Reset all signal handlers and signal mask */
|
||||
FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */
|
||||
FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child */
|
||||
FORK_NULL_STDIO = 1 << 3, /* Connect 0,1,2 to /dev/null */
|
||||
FORK_REOPEN_LOG = 1 << 4, /* Reopen log connection */
|
||||
FORK_LOG = 1 << 5, /* Log above LOG_DEBUG log level about failures */
|
||||
FORK_WAIT = 1 << 6, /* Wait until child exited */
|
||||
FORK_NEW_MOUNTNS = 1 << 7, /* Run child in its own mount namespace */
|
||||
FORK_MOUNTNS_SLAVE = 1 << 8, /* Make child's mount namespace MS_SLAVE */
|
||||
FORK_RLIMIT_NOFILE_SAFE = 1 << 9, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
|
||||
} ForkFlags;
|
||||
|
||||
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
|
||||
|
||||
@@ -389,3 +389,22 @@ int rlimit_nofile_bump(int limit) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rlimit_nofile_safe(void) {
|
||||
struct rlimit rl;
|
||||
|
||||
/* Resets RLIMIT_NOFILE's soft limit FD_SETSIZE (i.e. 1024), for compatibility with software still using
|
||||
* select() */
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
|
||||
return log_debug_errno(errno, "Failed to query RLIMIT_NOFILE: %m");
|
||||
|
||||
if (rl.rlim_cur <= FD_SETSIZE)
|
||||
return 0;
|
||||
|
||||
rl.rlim_cur = FD_SETSIZE;
|
||||
if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
|
||||
return log_debug_errno(errno, "Failed to lower RLIMIT_NOFILE's soft limit to " RLIM_FMT ": %m", rl.rlim_cur);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -22,3 +22,4 @@ void rlimit_free_all(struct rlimit **rl);
|
||||
#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
|
||||
|
||||
int rlimit_nofile_bump(int limit);
|
||||
int rlimit_nofile_safe(void);
|
||||
@@ -236,6 +236,7 @@ _noreturn_ static void crash(int sig) {
|
||||
else if (pid == 0) {
|
||||
(void) setsid();
|
||||
(void) make_console_stdio();
|
||||
(void) rlimit_nofile_safe();
|
||||
(void) execle("/bin/sh", "/bin/sh", NULL, environ);
|
||||
|
||||
log_emergency_errno(errno, "execle() failed: %m");
|
||||
@@ -1733,6 +1734,7 @@ static void do_reexecute(
|
||||
/* Reenable any blocked signals, especially important if we switch from initial ramdisk to init=... */
|
||||
(void) reset_all_signal_handlers();
|
||||
(void) reset_signal_mask();
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
if (switch_root_init) {
|
||||
args[0] = switch_root_init;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "reboot-util.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "string-util.h"
|
||||
#include "switch-root.h"
|
||||
@@ -443,13 +444,15 @@ int main(int argc, char *argv[]) {
|
||||
arguments[2] = NULL;
|
||||
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
if (can_initrd) {
|
||||
r = switch_root_initramfs();
|
||||
if (r >= 0) {
|
||||
argv[0] = (char*) "/shutdown";
|
||||
|
||||
setsid();
|
||||
make_console_stdio();
|
||||
(void) setsid();
|
||||
(void) make_console_stdio();
|
||||
|
||||
log_info("Successfully changed into root pivot.\n"
|
||||
"Returning to initrd...");
|
||||
|
||||
@@ -968,7 +968,7 @@ static int run_debug(int argc, char **argv, void *userdata) {
|
||||
|
||||
fork_name = strjoina("(", arg_debugger, ")");
|
||||
|
||||
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
|
||||
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
if (r == 0) {
|
||||
|
||||
@@ -169,7 +169,7 @@ 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|FORK_LOG, &pid);
|
||||
r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "path-util.h"
|
||||
#include "proc-cmdline.h"
|
||||
#include "process-util.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "special.h"
|
||||
@@ -401,6 +402,8 @@ static int run(int argc, char *argv[]) {
|
||||
cmdline[i++] = device;
|
||||
cmdline[i++] = NULL;
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
execv(cmdline[0], (char**) cmdline);
|
||||
_exit(FSCK_OPERATIONAL_ERROR);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "process-util.h"
|
||||
#include "pull-common.h"
|
||||
#include "pull-job.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "signal-util.h"
|
||||
#include "siphash24.h"
|
||||
@@ -472,6 +473,8 @@ int pull_verify(PullJob *main_job,
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
cmd[k++] = strjoina("--homedir=", gpg_home);
|
||||
|
||||
/* We add the user keyring only to the command line
|
||||
|
||||
@@ -81,6 +81,8 @@ static int spawn_child(const char* child, char** argv) {
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
execvp(child, argv);
|
||||
log_error_errno(errno, "Failed to exec child %s: %m", child);
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "missing.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "stdio-util.h"
|
||||
@@ -932,6 +933,8 @@ int bus_socket_exec(sd_bus *b) {
|
||||
if (rearrange_stdio(s[1], s[1], STDERR_FILENO) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
if (b->exec_argv)
|
||||
execvp(b->exec_path, b->exec_argv);
|
||||
else {
|
||||
|
||||
@@ -303,7 +303,7 @@ static int run(int argc, char *argv[]) {
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to inhibit: %s", bus_error_message(&error, fd));
|
||||
|
||||
r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
|
||||
r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
||||
@@ -170,7 +170,7 @@ int bus_image_method_clone(
|
||||
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
|
||||
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
|
||||
|
||||
r = safe_fork("(imgclone)", FORK_RESET_SIGNALS, &child);
|
||||
r = safe_fork("(sd-imgclone)", FORK_RESET_SIGNALS, &child);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
||||
if (r == 0) {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "mkdir.h"
|
||||
#include "nspawn-setuid.h"
|
||||
#include "process-util.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
@@ -44,6 +45,8 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
|
||||
|
||||
close_all_fds(NULL, 0);
|
||||
|
||||
(void) rlimit_nofile_safe();
|
||||
|
||||
execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env);
|
||||
execle("/bin/getent", "getent", database, key, NULL, &empty_env);
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
@@ -28,7 +28,7 @@ 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|FORK_LOG, &pid);
|
||||
r = safe_fork("(mkfs)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
||||
@@ -78,7 +78,7 @@ static int run(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
|
||||
r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_WAIT|FORK_LOG, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user