]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
ctl: tighten umask around bind() for the control socket
authorVincent Bernat <vincent@bernat.ch>
Sat, 9 May 2026 12:58:32 +0000 (14:58 +0200)
committerVincent Bernat <vincent@bernat.ch>
Sat, 9 May 2026 13:26:12 +0000 (15:26 +0200)
Between bind() and the chown()/chmod() done by the caller, the unix
socket inode existed with whatever 0777 & ~current_umask produced,
typically 0755 — non-root users could connect during that window.
Set umask(S_IRWXO) for the duration of bind() so 'other' bits are
masked. Only apply when ENABLE_PRIVSEP is set since the chown/chmod
follow-up is itself privsep-only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
src/ctl.c

index f9473a26a18a3f627d303da5f57e25e1a128d608..475d90bc94adff4e789d67c6b66d1d1720046275 100644 (file)
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -20,6 +20,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <string.h>
@@ -41,6 +42,9 @@ ctl_create(const char *name)
        int s;
        struct sockaddr_un su;
        int rc;
+#ifdef ENABLE_PRIVSEP
+       mode_t old_umask;
+#endif
 
        log_debug("control", "create control socket %s", name);
 
@@ -51,7 +55,16 @@ ctl_create(const char *name)
        }
        su.sun_family = AF_UNIX;
        strlcpy(su.sun_path, name, sizeof(su.sun_path));
-       if (bind(s, (struct sockaddr *)&su, sizeof(struct sockaddr_un)) == -1) {
+#ifdef ENABLE_PRIVSEP
+       /* Tighten the umask so the socket is not world-accessible between
+        * bind() and the subsequent chown()/chmod(). */
+       old_umask = umask(S_IRWXO);
+#endif
+       rc = bind(s, (struct sockaddr *)&su, sizeof(struct sockaddr_un));
+#ifdef ENABLE_PRIVSEP
+       umask(old_umask);
+#endif
+       if (rc == -1) {
                rc = errno;
                close(s);
                errno = rc;