Abstract sockets support in systemd notify

Damien Miller djm at mindrot.org
Wed Jan 28 11:01:15 AEDT 2026


Hi,

According to this PR our systemd notification support is broken for
abstract sockets:

https://github.com/openssh/openssh-portable/pull/615

Per https://man7.org/linux/man-pages/man7/unix.7.html

> an abstract socket address is distinguished (from a
> pathname socket) by the fact that sun_path[0] is a null
> byte ('\0').  The socket's address in this namespace is
> given by the additional bytes in sun_path that are covered
> by the specified length of the address structure.  (Null
> bytes in the name have no special significance.)

That last sentence actually means "a nul byte can be part of the
abstract socket name". So for these we need to signal the path
length via addrlen.

I don't know how to get systemd to offer sshd a notification
channel on an abstract socket, so I'd appreciate if anyone could
either educate me or test this themselves.

(This is a much more minimal fix than the above PR, which contains
unrelated refactoring)

-d

diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
index c1d54f38d..22998bdc9 100644
--- a/openbsd-compat/port-linux.c
+++ b/openbsd-compat/port-linux.c
@@ -344,10 +344,13 @@ ssh_systemd_notify(const char *fmt, ...)
 	const char *path;
 	struct stat sb;
 	struct sockaddr_un addr;
+	socklen_t alen;
+	size_t pathlen;
 	int fd = -1;
 	va_list ap;
 
-	if ((path = getenv("NOTIFY_SOCKET")) == NULL || strlen(path) == 0)
+	if ((path = getenv("NOTIFY_SOCKET")) == NULL ||
+	    (pathlen = strlen(path)) == 0)
 		return;
 
 	va_start(ap, fmt);
@@ -372,14 +375,21 @@ ssh_systemd_notify(const char *fmt, ...)
 		error_f("socket path \"%s\" too long", path);
 		goto out;
 	}
-	/* Support for abstract socket */
-	if (addr.sun_path[0] == '@')
+	alen = sizeof(addr);
+	/* Support for abstract sockets */
+	if (addr.sun_path[0] == '@') {
 		addr.sun_path[0] = 0;
+		/*
+		 * nul bytes in abstract socket names are interpreted as part
+		 * of the name. Path length is signaled via addrlen.
+		 */
+		alen = ((uintptr_t)&addr.sun_path - (uintptr_t)&addr) + pathlen;
+	}
 	if ((fd = socket(PF_UNIX, SOCK_DGRAM, 0)) == -1) {
 		error_f("socket \"%s\": %s", path, strerror(errno));
 		goto out;
 	}
-	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
+	if (connect(fd, (struct sockaddr *)&addr, alen) != 0) {
 		error_f("socket \"%s\" connect: %s", path, strerror(errno));
 		goto out;
 	}


More information about the openssh-unix-dev mailing list