mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-14 02:06:16 +02:00
Connect/bind Unix domain sockets in a child process
In the child process, we can do a chdir() and avoid the problem of the path not fitting into sockaddr_un.
This commit is contained in:
parent
08cc572f89
commit
43d4d75e22
3 changed files with 69 additions and 21 deletions
|
@ -65,16 +65,7 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
|
||||||
throw SysError("cannot create Unix domain socket");
|
throw SysError("cannot create Unix domain socket");
|
||||||
closeOnExec(conn->fd.get());
|
closeOnExec(conn->fd.get());
|
||||||
|
|
||||||
string socketPath = path ? *path : settings.nixDaemonSocketFile;
|
nix::connect(conn->fd.get(), path ? *path : settings.nixDaemonSocketFile);
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
if (socketPath.size() + 1 >= sizeof(addr.sun_path))
|
|
||||||
throw Error("socket path '%1%' is too long", socketPath);
|
|
||||||
strcpy(addr.sun_path, socketPath.c_str());
|
|
||||||
|
|
||||||
if (::connect(conn->fd.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
|
||||||
throw SysError("cannot connect to daemon at '%1%'", socketPath);
|
|
||||||
|
|
||||||
conn->from.fd = conn->fd.get();
|
conn->from.fd = conn->fd.get();
|
||||||
conn->to.fd = conn->fd.get();
|
conn->to.fd = conn->fd.get();
|
||||||
|
|
|
@ -1686,16 +1686,7 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
|
||||||
|
|
||||||
closeOnExec(fdSocket.get());
|
closeOnExec(fdSocket.get());
|
||||||
|
|
||||||
struct sockaddr_un addr;
|
bind(fdSocket.get(), path);
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
if (path.size() + 1 >= 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)
|
if (chmod(path.c_str(), mode) == -1)
|
||||||
throw SysError("changing permissions on '%1%'", path);
|
throw SysError("changing permissions on '%1%'", path);
|
||||||
|
@ -1707,6 +1698,66 @@ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bind(int fd, const std::string & path)
|
||||||
|
{
|
||||||
|
unlink(path.c_str());
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
|
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||||
|
Pid pid = startProcess([&]() {
|
||||||
|
auto dir = dirOf(path);
|
||||||
|
if (chdir(dir.c_str()) == -1)
|
||||||
|
throw SysError("chdir to '%s' failed", dir);
|
||||||
|
std::string base(baseNameOf(path));
|
||||||
|
if (base.size() + 1 >= sizeof(addr.sun_path))
|
||||||
|
throw Error("socket path '%s' is too long", base);
|
||||||
|
strcpy(addr.sun_path, base.c_str());
|
||||||
|
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||||
|
throw SysError("cannot bind to socket '%s'", path);
|
||||||
|
_exit(0);
|
||||||
|
});
|
||||||
|
int status = pid.wait();
|
||||||
|
if (status != 0)
|
||||||
|
throw Error("cannot bind to socket '%s'", path);
|
||||||
|
} else {
|
||||||
|
strcpy(addr.sun_path, path.c_str());
|
||||||
|
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||||
|
throw SysError("cannot bind to socket '%s'", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void connect(int fd, const std::string & path)
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
|
||||||
|
if (path.size() + 1 >= sizeof(addr.sun_path)) {
|
||||||
|
Pid pid = startProcess([&]() {
|
||||||
|
auto dir = dirOf(path);
|
||||||
|
if (chdir(dir.c_str()) == -1)
|
||||||
|
throw SysError("chdir to '%s' failed", dir);
|
||||||
|
std::string base(baseNameOf(path));
|
||||||
|
if (base.size() + 1 >= sizeof(addr.sun_path))
|
||||||
|
throw Error("socket path '%s' is too long", base);
|
||||||
|
strcpy(addr.sun_path, base.c_str());
|
||||||
|
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||||
|
throw SysError("cannot connect to socket at '%s'", path);
|
||||||
|
_exit(0);
|
||||||
|
});
|
||||||
|
int status = pid.wait();
|
||||||
|
if (status != 0)
|
||||||
|
throw Error("cannot connect to socket ar '%s'", path);
|
||||||
|
} else {
|
||||||
|
strcpy(addr.sun_path, path.c_str());
|
||||||
|
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||||
|
throw SysError("cannot connect to socket at '%s'", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
string showBytes(uint64_t bytes)
|
string showBytes(uint64_t bytes)
|
||||||
{
|
{
|
||||||
return fmt("%.2f MiB", bytes / (1024.0 * 1024.0));
|
return fmt("%.2f MiB", bytes / (1024.0 * 1024.0));
|
||||||
|
|
|
@ -259,7 +259,7 @@ void killUser(uid_t uid);
|
||||||
pid to the caller. */
|
pid to the caller. */
|
||||||
struct ProcessOptions
|
struct ProcessOptions
|
||||||
{
|
{
|
||||||
string errorPrefix = "error: ";
|
string errorPrefix = "";
|
||||||
bool dieWithParent = true;
|
bool dieWithParent = true;
|
||||||
bool runExitHandlers = false;
|
bool runExitHandlers = false;
|
||||||
bool allowVfork = true;
|
bool allowVfork = true;
|
||||||
|
@ -574,6 +574,12 @@ void commonChildInit(Pipe & logPipe);
|
||||||
/* Create a Unix domain socket in listen mode. */
|
/* Create a Unix domain socket in listen mode. */
|
||||||
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
|
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
|
||||||
|
|
||||||
|
/* Bind a Unix domain socket to a path. */
|
||||||
|
void bind(int fd, const std::string & path);
|
||||||
|
|
||||||
|
/* Connect to a Unix domain socket. */
|
||||||
|
void connect(int fd, const std::string & path);
|
||||||
|
|
||||||
|
|
||||||
// A Rust/Python-like enumerate() iterator adapter.
|
// A Rust/Python-like enumerate() iterator adapter.
|
||||||
// Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17.
|
// Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17.
|
||||||
|
|
Loading…
Reference in a new issue