Skip to content

Commit

Permalink
notify systemd on listen and reload
Browse files Browse the repository at this point in the history
Standalone implementation that does not depend on libsystemd.
With assistance from Luca Boccassi, and feedback/testing from Colin
Watson. bz2641
  • Loading branch information
djmdjm committed Apr 3, 2024
1 parent 43e7c1c commit 08f5792
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 2 deletions.
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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.*)
Expand Down
97 changes: 95 additions & 2 deletions openbsd-compat/port-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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 */
5 changes: 5 additions & 0 deletions openbsd-compat/port-linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
11 changes: 11 additions & 0 deletions platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions sshd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 08f5792

Please sign in to comment.