From aa3632962f2032063e76c0fe99085e83a947fedb Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Wed, 3 Apr 2024 15:13:00 +0200 Subject: [PATCH] MEDIUM: mworker: get rid of libsystemd Given the xz drama which allowed liblzma to be linked to openssh, lets remove libsystemd to get rid of useless dependencies. The sd_notify API seems to be stable and is now documented. This patch replaces the sd_notify() and sd_notifyf() function by a reimplementation inspired by the systemd documentation. This should not change anything functionnally. The function will be built when haproxy is built using USE_SYSTEMD=1. References: https://github.com/systemd/systemd/issues/32028 https://www.freedesktop.org/software/systemd/man/devel/sd_notify.html#Notes Before: wla@kikyo:~% ldd /usr/sbin/haproxy linux-vdso.so.1 (0x00007ffcfaf65000) libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x000074637fef4000) libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x000074637fe4f000) libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x000074637f400000) liblua5.4.so.0 => /lib/x86_64-linux-gnu/liblua5.4.so.0 (0x000074637fe0d000) libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x000074637f92a000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x000074637f365000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000074637f000000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000074637f27a000) libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x000074637fdff000) libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x000074637eeb8000) liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x000074637fdcd000) libzstd.so.1 => /lib/x86_64-linux-gnu/libzstd.so.1 (0x000074637ee01000) liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x000074637fda8000) /lib64/ld-linux-x86-64.so.2 (0x000074637ff5d000) libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x000074637f904000) After: wla@kikyo:~% ldd /usr/sbin/haproxy linux-vdso.so.1 (0x00007ffd51901000) libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f758d6c0000) libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x00007f758d61b000) libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007f758ca00000) liblua5.4.so.0 => /lib/x86_64-linux-gnu/liblua5.4.so.0 (0x00007f758d5d9000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f758d365000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f758d5ba000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f758c600000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f758c915000) /lib64/ld-linux-x86-64.so.2 (0x00007f758d729000) A backport to all stable versions could be considered at some point. --- Makefile | 2 +- include/haproxy/systemd.h | 7 ++ src/mworker.c | 7 +- src/systemd.c | 134 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 include/haproxy/systemd.h create mode 100644 src/systemd.c diff --git a/Makefile b/Makefile index c904094dc4..df50d1700d 100644 --- a/Makefile +++ b/Makefile @@ -734,7 +734,7 @@ ifneq ($(USE_WURFL),) endif ifneq ($(USE_SYSTEMD),) - SYSTEMD_LDFLAGS = -lsystemd + OPTIONS_OBJS += src/systemd.o endif ifneq ($(USE_PCRE)$(USE_STATIC_PCRE)$(USE_PCRE_JIT),) diff --git a/include/haproxy/systemd.h b/include/haproxy/systemd.h new file mode 100644 index 0000000000..65b0ab6166 --- /dev/null +++ b/include/haproxy/systemd.h @@ -0,0 +1,7 @@ +#ifndef _HAPROXY_SYSTEMD_H +#define _HAPROXY_SYSTEMD_H + +int sd_notify(int unset_environment, const char *message); +int sd_notifyf(int unset_environment, const char *format, ...); + +#endif diff --git a/src/mworker.c b/src/mworker.c index be98246bf4..c4461cc10e 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -20,10 +20,6 @@ #include #include -#if defined(USE_SYSTEMD) -#include -#endif - #include #include #include @@ -45,6 +41,9 @@ #include #include +#if defined(USE_SYSTEMD) +#include +#endif static int exitcode = -1; static int max_reloads = -1; /* number max of reloads a worker can have until they are killed */ diff --git a/src/systemd.c b/src/systemd.c new file mode 100644 index 0000000000..fb36dd993f --- /dev/null +++ b/src/systemd.c @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: MIT-0 */ + +/* Implement the systemd notify protocol without external dependencies. + * Supports both readiness notification on startup and on reloading, + * according to the protocol defined at: + * https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html + * This protocol is guaranteed to be stable as per: + * https://systemd.io/PORTABILITY_AND_STABILITY/ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * standalone reimplementation of sd_notify from the libsystemd + * Return: + * -errno in case of error + * 0 when ignored + * >0 when succeeded + * + * Will send over the NOTIFY_SOCKET. + * When unset_environement is set, unsetenv NOTIFY_SOCKET. + */ +int sd_notify(int unset_environment, const char *message) +{ + union sockaddr_union { + struct sockaddr sa; + struct sockaddr_un sun; + } socket_addr = { + .sun.sun_family = AF_UNIX, + }; + int ret = 1; + int fd = -1; + size_t path_length, message_length; + const char *socket_path; + ssize_t written; + + socket_path = getenv("NOTIFY_SOCKET"); + if (!socket_path) { + ret = 0; /* Not running under systemd? Nothing to do */ + goto end; + } + + if (unset_environment) + unsetenv("NOTIFY_SOCKET"); + + if (!message) { + ret = -EINVAL; + goto end; + } + + message_length = strlen(message); + if (message_length == 0) { + ret = -EINVAL; + goto end; + } + + /* Only AF_UNIX is supported, with path or abstract sockets */ + if (socket_path[0] != '/' && socket_path[0] != '@') { + ret = -EAFNOSUPPORT; + goto end; + } + + path_length = strlen(socket_path); + /* Ensure there is room for NUL byte */ + if (path_length >= sizeof(socket_addr.sun.sun_path)) { + ret = -E2BIG; + goto end; + } + + memcpy(socket_addr.sun.sun_path, socket_path, path_length); + + /* Support for abstract socket */ + if (socket_addr.sun.sun_path[0] == '@') + socket_addr.sun.sun_path[0] = 0; + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) { + ret = -errno; + goto end; + } + + if (connect(fd, &socket_addr.sa, offsetof(struct sockaddr_un, sun_path) + path_length) != 0) { + ret = -errno; + goto end; + } + + written = write(fd, message, message_length); + if (written != (ssize_t) message_length) { + ret = written < 0 ? -errno : -EPROTO; + goto end; + } + +end: + if (fd > -1) + close(fd); + return ret; /* Notified! */ +} + +/* va_args variant of sd_notify */ +int sd_notifyf(int unset_environment, const char *format, ...) +{ + int r; + va_list args; + char *strp = NULL; + + va_start(args, format); + strp = memvprintf(&strp, format, args); + va_end(args); + + if (strp == NULL) { + r = -ENOMEM; + goto end; + } + + r = sd_notify(unset_environment, strp); + free(strp); +end: + return r; +} + -- 2.39.5