• [^] # Re: Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.

    Posté par (site web personnel, Mastodon) . En réponse au lien After a Recent SSH Vulnerability, Systemd Reduces Dependencies. Évalué à 9.

    Après une récente vulnérabilité de SSH, Systemd réduit ses dépendances.

    Si j'ai bien compris ce commentaire sur Github, systemd ne réduit pas ses dépendances, mais les charge dynamiquement avec dlopen au moment où elles sont nécessaires.

    Donc, en pratique, les dépendances sont toujours là.

    Cette bibliothèque, essentielle pour intégrer les services avec systemd

    Comme soulevé par Renault dans ce commentaire, libsystemd n'est pas un pré-requis pour intégrer les services avec systemd. Dans le lien donné par Renault, Lennart Potting résume en une phrase ce qui est nécessaire:

    It literally is just sending a text string "READY=1" in an AF_UNIX datagram to a socket whose path is provided to you in the $NOTIFY_SOCKET env var. Anyone with a moderate understanding of UNIX APIs should be able to hack that up in a a few lines of code. It's a protocol I can summarize and explain in one frickin' sentence.

    Ce qui s'est traduit concrètement par ce patch pour OpenSSH par exemple (joins ci-dessous).

    Le patch est long, car OpenSSH a décidé de faire une option de build pour ne pas l'intégrer à la construction. Si on enlève ce détail, la fonction C static void ssh_systemd_notify(const char *fmt, ...) n'est effectivement pas si horrible.

    --- a/configure.ac 
    +++ a/configure.ac 
    @@ -915,6 +915,7 @@ int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
     AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts])
     AC_DEFINE([USE_BTMP])
     AC_DEFINE([LINUX_OOM_ADJUST], [1], [Adjust Linux out-of-memory killer])
    + AC_DEFINE([SYSTEMD_NOTIFY], [1], [Have sshd notify systemd on start/reload])
     inet6_default_4in6=yes
     case `uname -r` in
     1.*|2.0.*)
    --- a/openbsd-compat/port-linux.c 
    +++ a/openbsd-compat/port-linux.c 
    @@ -21,16 +21,23 @@ 
     #include "includes.h"
    -#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST)
    +#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) || \
    + defined(SYSTEMD_NOTIFY)
    +#include <sys/socket.h>
    +#include <sys/un.h>
    +
     #include <errno.h>
    +#include <inttypes.h>
     #include <stdarg.h>
     #include <string.h>
     #include <stdio.h>
     #include <stdlib.h>
    +#include <time.h>
     #include "log.h"
     #include "xmalloc.h"
     #include "port-linux.h"
    +#include "misc.h"
     #ifdef WITH_SELINUX
     #include <selinux/selinux.h>
    @@ -310,4 +317,90 @@ oom_adjust_restore(void)
     return;
     }
     #endif /* LINUX_OOM_ADJUST */
    -#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */
    +
    +#ifdef SYSTEMD_NOTIFY
    +
    +static void ssh_systemd_notify(const char *, ...)
    + __attribute__((__format__ (printf, 1, 2))) __attribute__((__nonnull__ (1)));
    +
    +static void
    +ssh_systemd_notify(const char *fmt, ...)
    +{
    + char *s = NULL;
    + const char *path;
    + struct stat sb;
    + struct sockaddr_un addr;
    + int fd = -1;
    + va_list ap;
    +
    + if ((path = getenv("NOTIFY_SOCKET")) == NULL || strlen(path) == 0)
    + return;
    +
    + va_start(ap, fmt);
    + xvasprintf(&s, fmt, ap);
    + va_end(ap);
    +
    + /* Only AF_UNIX is supported, with path or abstract sockets */
    + if (path[0] != '/' && path[0] != '@') {
    + error_f("socket \"%s\" is not compatible with AF_UNIX", path);
    + goto out;
    + }
    +
    + if (path[0] == '/' && stat(path, &sb) != 0) {
    + error_f("socket \"%s\" stat: %s", path, strerror(errno));
    + goto out;
    + }
    +
    + memset(&addr, 0, sizeof(addr));
    + addr.sun_family = AF_UNIX;
    + if (strlcpy(addr.sun_path, path,
    + sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
    + error_f("socket path \"%s\" too long", path);
    + goto out;
    + }
    + /* Support for abstract socket */
    + if (addr.sun_path[0] == '@')
    + addr.sun_path[0] = 0;
    + if ((fd = socket(PF_UNIX, SOCK_DGRAM, 0)) == -1) {
    + error_f("socket \"%s\": %s", path, strerror(errno));
    + goto out;
    + }
    + if (connect(fd, &addr, sizeof(addr)) != 0) {
    + error_f("socket \"%s\" connect: %s", path, strerror(errno));
    + goto out;
    + }
    + if (write(fd, s, strlen(s)) != (ssize_t)strlen(s)) {
    + error_f("socket \"%s\" write: %s", path, strerror(errno));
    + goto out;
    + }
    + debug_f("socket \"%s\" notified %s", path, s);
    + out:
    + if (fd != -1)
    + close(fd);
    + free(s);
    +}
    +
    +void
    +ssh_systemd_notify_ready(void)
    +{
    + ssh_systemd_notify("READY=1");
    +}
    +
    +void
    +ssh_systemd_notify_reload(void)
    +{
    + struct timespec now;
    +
    + monotime_ts(&now);
    + if (now.tv_sec < 0 || now.tv_nsec < 0) {
    + error_f("monotime returned negative value");
    + ssh_systemd_notify("RELOADING=1");
    + } else {
    + ssh_systemd_notify("RELOADING=1\nMONOTONIC_USEC=%llu",
    + ((uint64_t)now.tv_sec * 1000000ULL) +
    + ((uint64_t)now.tv_nsec / 1000ULL));
    + }
    +}
    +#endif /* SYSTEMD_NOTIFY */
    +
    +#endif /* WITH_SELINUX || LINUX_OOM_ADJUST || SYSTEMD_NOTIFY */
    --- a/openbsd-compat/port-linux.h 
    +++ a/openbsd-compat/port-linux.h 
    @@ -30,4 +30,9 @@ void oom_adjust_restore(void);
     void oom_adjust_setup(void);
     #endif
    +#ifdef SYSTEMD_NOTIFY
    +void ssh_systemd_notify_ready(void);
    +void ssh_systemd_notify_reload(void);
    +#endif
    +
     #endif /* ! _PORT_LINUX_H */
    --- a/platform.c 
    +++ a/platform.c 
    @@ -44,6 +44,14 @@ platform_pre_listen(void)
     #endif
     }
    +void
    +platform_post_listen(void)
    +{
    +#ifdef SYSTEMD_NOTIFY
    + ssh_systemd_notify_ready();
    +#endif
    +}
    +
     void
     platform_pre_fork(void)
     {
    @@ -55,6 +63,9 @@ platform_pre_fork(void)
     void
     platform_pre_restart(void)
     {
    +#ifdef SYSTEMD_NOTIFY
    + ssh_systemd_notify_reload();
    +#endif
     #ifdef LINUX_OOM_ADJUST
     oom_adjust_restore();
     #endif
    --- a/platform.h 
    +++ a/platform.h 
    @@ -21,6 +21,7 @@ 
     void platform_pre_listen(void);
     void platform_pre_fork(void);
     void platform_pre_restart(void);
    +void platform_post_listen(void);
     void platform_post_fork_parent(pid_t child_pid);
     void platform_post_fork_child(void);
     int platform_privileged_uidswap(void);
    --- a/sshd.c 
    +++ a/sshd.c 
    @@ -2077,6 +2077,8 @@ main(int ac, char **av)
     ssh_signal(SIGTERM, sigterm_handler);
     ssh_signal(SIGQUIT, sigterm_handler);
    + platform_post_listen();
    +
     /*
     * Write out the pid file after the sigterm handler
     * is setup and the listen sockets are bound