summaryrefslogtreecommitdiffstats
path: root/debian/patches/systemd-socket-activation.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/systemd-socket-activation.patch')
-rw-r--r--debian/patches/systemd-socket-activation.patch138
1 files changed, 138 insertions, 0 deletions
diff --git a/debian/patches/systemd-socket-activation.patch b/debian/patches/systemd-socket-activation.patch
new file mode 100644
index 0000000..73afb88
--- /dev/null
+++ b/debian/patches/systemd-socket-activation.patch
@@ -0,0 +1,138 @@
+From 7fa10262be3c7d9fd2fca9c9710ac4ef3f788b08 Mon Sep 17 00:00:00 2001
+From: Steve Langasek <steve.langasek@ubuntu.com>
+Date: Thu, 1 Sep 2022 16:03:37 +0100
+Subject: Support systemd socket activation
+
+Unlike inetd socket activation, with systemd socket activation the
+supervisor passes the listened-on socket to the child process and lets
+the child process handle the accept(). This lets us do delayed start
+of the sshd daemon without becoming incompatible with config options
+like ClientAliveCountMax.
+
+Last-Update: 2022-09-01
+
+Patch-Name: systemd-socket-activation.patch
+---
+ sshd.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 75 insertions(+), 14 deletions(-)
+
+diff --git a/sshd.c b/sshd.c
+index 356bd6c02..6dfa5fffe 100644
+--- a/sshd.c
++++ b/sshd.c
+@@ -140,10 +140,16 @@ int deny_severity;
+ #endif /* LIBWRAP */
+
+ /* Re-exec fds */
+-#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
+-#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
+-#define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3)
+-#define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4)
++#ifdef HAVE_SYSTEMD
++#define SYSTEMD_OFFSET sd_listen_fds(0)
++#else
++#define SYSTEMD_OFFSET 0
++#endif
++
++#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1 + SYSTEMD_OFFSET)
++#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2 + SYSTEMD_OFFSET)
++#define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3 + SYSTEMD_OFFSET)
++#define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4 + SYSTEMD_OFFSET)
+
+ extern char *__progname;
+
+@@ -1020,6 +1026,48 @@ server_accept_inetd(int *sock_in, int *sock_out)
+ debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
+ }
+
++#ifdef HAVE_SYSTEMD
++/*
++ * Configure our socket fds that were passed from systemd
++ */
++static void
++setup_systemd_socket(int listen_sock)
++{
++ int ret;
++ struct sockaddr_storage addr;
++ socklen_t len = sizeof(addr);
++ char ntop[NI_MAXHOST], strport[NI_MAXSERV];
++
++ if (getsockname(listen_sock, (struct sockaddr *)&addr, &len) != 0)
++ return;
++
++ if (((struct sockaddr *)&addr)->sa_family != AF_INET
++ && ((struct sockaddr *)&addr)->sa_family != AF_INET6)
++ return;
++ if (num_listen_socks >= MAX_LISTEN_SOCKS)
++ fatal("Too many listen sockets. "
++ "Enlarge MAX_LISTEN_SOCKS");
++ if ((ret = getnameinfo((struct sockaddr *)&addr, len, ntop,
++ sizeof(ntop), strport, sizeof(strport),
++ NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
++ error("getnameinfo failed: %.100s",
++ ssh_gai_strerror(ret));
++ return;
++ }
++ if (set_nonblock(listen_sock) == -1) {
++ close(listen_sock);
++ return;
++ }
++ /* Socket options */
++ set_reuseaddr(listen_sock);
++
++ listen_socks[num_listen_socks] = listen_sock;
++ num_listen_socks++;
++
++ logit("Server listening on %s port %s.", ntop, strport);
++}
++#endif
++
+ /*
+ * Listen for TCP connections
+ */
+@@ -1099,22 +1147,35 @@ static void
+ server_listen(void)
+ {
+ u_int i;
++#ifdef HAVE_SYSTEMD
++ int systemd_socket_count;
++#endif
+
+ /* Initialise per-source limit tracking. */
+ srclimit_init(options.max_startups, options.per_source_max_startups,
+ options.per_source_masklen_ipv4, options.per_source_masklen_ipv6);
+
+- for (i = 0; i < options.num_listen_addrs; i++) {
+- listen_on_addrs(&options.listen_addrs[i]);
+- freeaddrinfo(options.listen_addrs[i].addrs);
+- free(options.listen_addrs[i].rdomain);
+- memset(&options.listen_addrs[i], 0,
+- sizeof(options.listen_addrs[i]));
++#ifdef HAVE_SYSTEMD
++ systemd_socket_count = sd_listen_fds(0);
++ if (systemd_socket_count > 0)
++ {
++ int i;
++ for (i = 0; i < systemd_socket_count; i++)
++ setup_systemd_socket(SD_LISTEN_FDS_START + i);
++ } else
++#endif
++ {
++ for (i = 0; i < options.num_listen_addrs; i++) {
++ listen_on_addrs(&options.listen_addrs[i]);
++ freeaddrinfo(options.listen_addrs[i].addrs);
++ free(options.listen_addrs[i].rdomain);
++ memset(&options.listen_addrs[i], 0,
++ sizeof(options.listen_addrs[i]));
++ }
++ free(options.listen_addrs);
++ options.listen_addrs = NULL;
++ options.num_listen_addrs = 0;
+ }
+- free(options.listen_addrs);
+- options.listen_addrs = NULL;
+- options.num_listen_addrs = 0;
+-
+ if (!num_listen_socks)
+ fatal("Cannot bind any address.");
+ }