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>
#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>
int s;
struct sockaddr_un su;
int rc;
+#ifdef ENABLE_PRIVSEP
+ mode_t old_umask;
+#endif
log_debug("control", "create control socket %s", 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;