tree-wide: invoke rlimit_nofile_safe() before various exec{v,ve,l}() invocations

Whenever we invoke external, foreign code from code that has
RLIMIT_NOFILE's soft limit bumped to high values, revert it to 1024
first. This is a safety precaution for compatibility with programs using
select() which cannot operate with fds > 1024.

This commit adds the call to rlimit_nofile_safe() to all invocations of
exec{v,ve,l}() and friends that either are in code that we know runs
with RLIMIT_NOFILE bumped up (which is PID 1 and all journal code for
starters) or that is part of shared code that might end up there.

The calls are placed as early as we can in processes invoking a flavour
of execve(), but after the last time we do fd manipulations, so that we
can still take benefit of the high fd limits for that.
This commit is contained in:
Lennart Poettering
2018-12-01 12:50:45 +01:00
parent 909106ebdf
commit 595225af7a
12 changed files with 28 additions and 0 deletions
+2
View File
@@ -1521,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++)
+2
View File
@@ -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;
+3
View File
@@ -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,6 +444,8 @@ 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) {
+3
View File
@@ -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);
}
+3
View File
@@ -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
+2
View File
@@ -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);
+3
View File
@@ -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 {
+3
View File
@@ -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);
+3
View File
@@ -16,6 +16,7 @@
#include "hashmap.h"
#include "macro.h"
#include "process-util.h"
#include "rlimit-util.h"
#include "serialize.h"
#include "set.h"
#include "signal-util.h"
@@ -50,6 +51,8 @@ static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
_exit(EXIT_FAILURE);
}
(void) rlimit_nofile_safe();
if (!argv) {
_argv[0] = (char*) path;
_argv[1] = NULL;
+1
View File
@@ -19,6 +19,7 @@
#include "macro.h"
#include "pager.h"
#include "process-util.h"
#include "rlimit-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "strv.h"
+1
View File
@@ -8302,6 +8302,7 @@ static int parse_argv(int argc, char *argv[]) {
/* Hmm, so some other init system is running, we need to forward this request to
* it. For now we simply guess that it is Upstart. */
(void) rlimit_nofile_safe();
execv(TELINIT, argv);
return log_error_errno(SYNTHETIC_ERRNO(EIO),
+2
View File
@@ -20,6 +20,7 @@
#include "netlink-util.h"
#include "path-util.h"
#include "process-util.h"
#include "rlimit-util.h"
#include "signal-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -654,6 +655,7 @@ int udev_event_spawn(struct udev_event *event,
_exit(EXIT_FAILURE);
(void) close_all_fds(NULL, 0);
(void) rlimit_nofile_safe();
execve(argv[0], argv, envp);
_exit(EXIT_FAILURE);