socket-proxyd: raise RLIMIT_NOFILE at startup

Each proxied connection uses eight file descriptors: the accepted and the
outgoing socket, a duplicate of each, and a pipe for each direction. With
the default soft RLIMIT_NOFILE of 1024, setting up forwarding fails with
"Too many open files" at about 127 concurrent connections, well before
the default --connections-max=256, and the connection is closed right
after being accepted.

socket-proxyd's I/O is sd-event based and handles fds above 1023, so it
does not need the select()-compatible soft limit. Call
rlimit_nofile_bump(-1) at startup to raise RLIMIT_NOFILE as far as
permitted, like udevd does.

(cherry picked from commit 98752540be47778e253cbafe51c7ccdd30f4995e)
This commit is contained in:
Kamil Monicz
2026-10-16 11:36:32 +01:00
committed by Luca Boccassi
parent c74f6f85ed
commit bcf0a9ac58
2 changed files with 14 additions and 0 deletions
+5
View File
@@ -21,6 +21,7 @@
#include "main-func.h"
#include "parse-util.h"
#include "resolve-private.h"
#include "rlimit-util.h"
#include "set.h"
#include "socket-forward.h"
#include "socket-util.h"
@@ -563,6 +564,10 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
return r;
/* Each connection holds several fds (two sockets, their duplicates and a pipe per direction), so
* the default soft limit of 1024 would run out well before the default connection limit. */
(void) rlimit_nofile_bump(-1);
r = sd_event_default(&context.event);
if (r < 0)
return log_error_errno(r, "Failed to allocate event loop: %m");
@@ -38,6 +38,8 @@ EOF
cat >/run/systemd/system/test-proxyd.service <<EOF
[Service]
ExecStart=/usr/lib/systemd/systemd-socket-proxyd $BACKEND_SOCK
LimitNOFILE=1024:4096
CapabilityBoundingSet=~CAP_SYS_RESOURCE
EOF
systemctl daemon-reload
@@ -56,3 +58,10 @@ assert_eq "$(echo -n world | proxy_echo)" "world"
# Test with larger data (64KB random, base64-encoded)
LARGE_DATA="$(dd if=/dev/urandom bs=1024 count=64 status=none | base64)"
assert_eq "$(echo -n "$LARGE_DATA" | proxy_echo)" "$LARGE_DATA"
# Every connection costs the proxy several fds, so it raises its soft RLIMIT_NOFILE. Without
# CAP_SYS_RESOURCE it cannot raise the hard limit, so the result is exactly the unit's hard limit.
PROXY_PID="$(systemctl show -P MainPID test-proxyd.service)"
read -r _ _ _ SOFT HARD _ < <(grep '^Max open files' "/proc/$PROXY_PID/limits")
assert_eq "$SOFT" 4096
assert_eq "$HARD" 4096