aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2018-09-25 12:36:11 +0200
committerEelco Dolstra <edolstra@gmail.com>2019-10-29 13:30:51 +0100
commit63b99af85a1e280876da3d807e4bc96a5c5dde39 (patch)
treee369a7b60b86dba503893c1a74a0c30fad85c5b4
parent2d37e88319441958b7eed876042a106e79c7c85d (diff)
Move Unix domain socket creation to libutil
Also drop multithread-unfriendly hacks like doing a temporary chmod/umask.
-rw-r--r--src/libutil/util.cc31
-rw-r--r--src/libutil/util.hh4
-rw-r--r--src/nix-daemon/nix-daemon.cc44
3 files changed, 38 insertions, 41 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 2e416edef..2a1272885 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -21,7 +21,9 @@
#include <pwd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/wait.h>
+#include <sys/un.h>
#include <unistd.h>
#ifdef __APPLE__
@@ -1562,4 +1564,33 @@ std::unique_ptr<InterruptCallback> createInterruptCallback(std::function<void()>
return std::unique_ptr<InterruptCallback>(res.release());
}
+
+AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
+{
+ AutoCloseFD fdSocket = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (!fdSocket)
+ throw SysError("cannot create Unix domain socket");
+
+ closeOnExec(fdSocket.get());
+
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ if (path.size() >= sizeof(addr.sun_path))
+ throw Error("socket path '%1%' is too long", path);
+ strcpy(addr.sun_path, path.c_str());
+
+ unlink(path.c_str());
+
+ if (bind(fdSocket.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
+ throw SysError("cannot bind to socket '%1%'", path);
+
+ if (chmod(path.c_str(), mode) == -1)
+ throw SysError("changing permissions on '%1%'", path);
+
+ if (listen(fdSocket.get(), 5) == -1)
+ throw SysError("cannot listen on socket '%1%'", path);
+
+ return fdSocket;
+}
+
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 3493e80b5..0bb171268 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -553,4 +553,8 @@ typedef std::function<bool(const Path & path)> PathFilter;
extern PathFilter defaultPathFilter;
+/* Create a Unix domain socket in listen mode. */
+AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
+
+
}
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index 799d2bacf..67bf4dfeb 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -156,53 +156,15 @@ static void daemonLoop(char * * argv)
if (getEnv("LISTEN_PID") != std::to_string(getpid()) || getEnv("LISTEN_FDS") != "1")
throw Error("unexpected systemd environment variables");
fdSocket = SD_LISTEN_FDS_START;
+ closeOnExec(fdSocket.get());
}
/* Otherwise, create and bind to a Unix domain socket. */
else {
-
- /* Create and bind to a Unix domain socket. */
- fdSocket = socket(PF_UNIX, SOCK_STREAM, 0);
- if (!fdSocket)
- throw SysError("cannot create Unix domain socket");
-
- string socketPath = settings.nixDaemonSocketFile;
-
- createDirs(dirOf(socketPath));
-
- /* Urgh, sockaddr_un allows path names of only 108 characters.
- So chdir to the socket directory so that we can pass a
- relative path name. */
- if (chdir(dirOf(socketPath).c_str()) == -1)
- throw SysError("cannot change current directory");
- Path socketPathRel = "./" + baseNameOf(socketPath);
-
- struct sockaddr_un addr;
- addr.sun_family = AF_UNIX;
- if (socketPathRel.size() >= sizeof(addr.sun_path))
- throw Error(format("socket path '%1%' is too long") % socketPathRel);
- strcpy(addr.sun_path, socketPathRel.c_str());
-
- unlink(socketPath.c_str());
-
- /* Make sure that the socket is created with 0666 permission
- (everybody can connect --- provided they have access to the
- directory containing the socket). */
- mode_t oldMode = umask(0111);
- int res = bind(fdSocket.get(), (struct sockaddr *) &addr, sizeof(addr));
- umask(oldMode);
- if (res == -1)
- throw SysError(format("cannot bind to socket '%1%'") % socketPath);
-
- if (chdir("/") == -1) /* back to the root */
- throw SysError("cannot change current directory");
-
- if (listen(fdSocket.get(), 5) == -1)
- throw SysError(format("cannot listen on socket '%1%'") % socketPath);
+ createDirs(dirOf(settings.nixDaemonSocketFile));
+ fdSocket = createUnixDomainSocket(settings.nixDaemonSocketFile, 0666);
}
- closeOnExec(fdSocket.get());
-
/* Loop accepting connections. */
while (1) {