X Tutup
Skip to content

Commit 871fa29

Browse files
committed
Merge pull request systemd#10935 from poettering/rlimit-nofile-safe
Merged by hand to resolve a trivial conflict in TODO.
2 parents f0a43eb + 707b3fb commit 871fa29

File tree

29 files changed

+124
-41
lines changed

29 files changed

+124
-41
lines changed

TODO

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ Features:
2929

3030
* when we fork off generators and such, lower LIMIT_NOFILE soft limit to 1K
3131

32+
* Maybe introduce a helper safe_exec() or so, which is to execve() which
33+
safe_fork() is to fork(). And then make revert the RLIMIT_NOFILE soft limit
34+
to 1K implicitly, unless explicitly opted-out.
35+
3236
* rework seccomp/nnp logic that that even if User= is used in combination with
3337
a seccomp option we don't have to set NNP. For that, change uid first whil
3438
keeping CAP_SYS_ADMIN, then apply seccomp, the drop cap.

src/activate/activate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ static int fork_and_exec_process(const char* child, char** argv, char **env, int
249249
if (!joined)
250250
return log_oom();
251251

252-
r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &child_pid);
252+
r = safe_fork("(activate)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &child_pid);
253253
if (r < 0)
254254
return r;
255255
if (r == 0) {

src/basic/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ basic_sources = files('''
149149
refcnt.h
150150
replace-var.c
151151
replace-var.h
152+
rlimit-util.c
153+
rlimit-util.h
152154
rm-rf.c
153155
rm-rf.h
154156
selinux-util.c

src/basic/process-util.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "missing.h"
3636
#include "process-util.h"
3737
#include "raw-clone.h"
38+
#include "rlimit-util.h"
3839
#include "signal-util.h"
3940
#include "stat-util.h"
4041
#include "string-table.h"
@@ -1401,6 +1402,14 @@ int safe_fork_full(
14011402
}
14021403
}
14031404

1405+
if (flags & FORK_RLIMIT_NOFILE_SAFE) {
1406+
r = rlimit_nofile_safe();
1407+
if (r < 0) {
1408+
log_full_errno(prio, r, "Failed to lower RLIMIT_NOFILE's soft limit to 1K: %m");
1409+
_exit(EXIT_FAILURE);
1410+
}
1411+
}
1412+
14041413
if (ret_pid)
14051414
*ret_pid = getpid_cached();
14061415

@@ -1512,6 +1521,8 @@ int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret
15121521
safe_close_above_stdio(fd);
15131522
}
15141523

1524+
(void) rlimit_nofile_safe();
1525+
15151526
/* Count arguments */
15161527
va_start(ap, path);
15171528
for (n = 0; va_arg(ap, char*); n++)

src/basic/process-util.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,16 @@ void reset_cached_pid(void);
142142
int must_be_root(void);
143143

144144
typedef enum ForkFlags {
145-
FORK_RESET_SIGNALS = 1 << 0,
146-
FORK_CLOSE_ALL_FDS = 1 << 1,
147-
FORK_DEATHSIG = 1 << 2,
148-
FORK_NULL_STDIO = 1 << 3,
149-
FORK_REOPEN_LOG = 1 << 4,
150-
FORK_LOG = 1 << 5,
151-
FORK_WAIT = 1 << 6,
152-
FORK_NEW_MOUNTNS = 1 << 7,
153-
FORK_MOUNTNS_SLAVE = 1 << 8,
145+
FORK_RESET_SIGNALS = 1 << 0, /* Reset all signal handlers and signal mask */
146+
FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */
147+
FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child */
148+
FORK_NULL_STDIO = 1 << 3, /* Connect 0,1,2 to /dev/null */
149+
FORK_REOPEN_LOG = 1 << 4, /* Reopen log connection */
150+
FORK_LOG = 1 << 5, /* Log above LOG_DEBUG log level about failures */
151+
FORK_WAIT = 1 << 6, /* Wait until child exited */
152+
FORK_NEW_MOUNTNS = 1 << 7, /* Run child in its own mount namespace */
153+
FORK_MOUNTNS_SLAVE = 1 << 8, /* Make child's mount namespace MS_SLAVE */
154+
FORK_RLIMIT_NOFILE_SAFE = 1 << 9, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
154155
} ForkFlags;
155156

156157
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,3 +389,22 @@ int rlimit_nofile_bump(int limit) {
389389

390390
return 0;
391391
}
392+
393+
int rlimit_nofile_safe(void) {
394+
struct rlimit rl;
395+
396+
/* Resets RLIMIT_NOFILE's soft limit FD_SETSIZE (i.e. 1024), for compatibility with software still using
397+
* select() */
398+
399+
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
400+
return log_debug_errno(errno, "Failed to query RLIMIT_NOFILE: %m");
401+
402+
if (rl.rlim_cur <= FD_SETSIZE)
403+
return 0;
404+
405+
rl.rlim_cur = FD_SETSIZE;
406+
if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
407+
return log_debug_errno(errno, "Failed to lower RLIMIT_NOFILE's soft limit to " RLIM_FMT ": %m", rl.rlim_cur);
408+
409+
return 1;
410+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ void rlimit_free_all(struct rlimit **rl);
2222
#define RLIMIT_MAKE_CONST(lim) ((struct rlimit) { lim, lim })
2323

2424
int rlimit_nofile_bump(int limit);
25+
int rlimit_nofile_safe(void);

src/core/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ _noreturn_ static void crash(int sig) {
236236
else if (pid == 0) {
237237
(void) setsid();
238238
(void) make_console_stdio();
239+
(void) rlimit_nofile_safe();
239240
(void) execle("/bin/sh", "/bin/sh", NULL, environ);
240241

241242
log_emergency_errno(errno, "execle() failed: %m");
@@ -1733,6 +1734,7 @@ static void do_reexecute(
17331734
/* Reenable any blocked signals, especially important if we switch from initial ramdisk to init=... */
17341735
(void) reset_all_signal_handlers();
17351736
(void) reset_signal_mask();
1737+
(void) rlimit_nofile_safe();
17361738

17371739
if (switch_root_init) {
17381740
args[0] = switch_root_init;

src/core/shutdown.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "parse-util.h"
2929
#include "process-util.h"
3030
#include "reboot-util.h"
31+
#include "rlimit-util.h"
3132
#include "signal-util.h"
3233
#include "string-util.h"
3334
#include "switch-root.h"
@@ -443,13 +444,15 @@ int main(int argc, char *argv[]) {
443444
arguments[2] = NULL;
444445
execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
445446

447+
(void) rlimit_nofile_safe();
448+
446449
if (can_initrd) {
447450
r = switch_root_initramfs();
448451
if (r >= 0) {
449452
argv[0] = (char*) "/shutdown";
450453

451-
setsid();
452-
make_console_stdio();
454+
(void) setsid();
455+
(void) make_console_stdio();
453456

454457
log_info("Successfully changed into root pivot.\n"
455458
"Returning to initrd...");

src/coredump/coredumpctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ static int run_debug(int argc, char **argv, void *userdata) {
968968

969969
fork_name = strjoina("(", arg_debugger, ")");
970970

971-
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_LOG, &pid);
971+
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
972972
if (r < 0)
973973
goto finish;
974974
if (r == 0) {

0 commit comments

Comments
 (0)
X Tutup