Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/libcmd/include/nix/cmd/unix-socket-server.hh
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@
#include <filesystem>
#include <functional>
#include <optional>
#include <sys/types.h>

namespace nix::unix {
#ifndef _WIN32
# include <sys/types.h>
#endif

namespace nix {

#ifndef _WIN32
namespace unix {

/**
* Information about the identity of the peer on a Unix domain socket connection.
Expand All @@ -25,6 +31,9 @@ struct PeerInfo
*/
PeerInfo getPeerInfo(Descriptor remote);

} // namespace unix
#endif

/**
* Callback type for handling new connections.
*
Expand Down Expand Up @@ -76,4 +85,4 @@ struct ServeUnixSocketOptions
*/
[[noreturn]] void serveUnixSocket(const ServeUnixSocketOptions & options, UnixSocketHandler handler);

} // namespace nix::unix
} // namespace nix
11 changes: 5 additions & 6 deletions src/libcmd/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,18 @@ sources = files(
'network-proxy.cc',
'repl-interacter.cc',
'repl.cc',
'unix-socket-server.cc',
)

if host_machine.system() != 'windows'
sources += files(
'unix/unix-socket-server.cc',
)
endif

subdir('include/nix/cmd')

subdir('nix-meson-build-support/export-all-symbols')
subdir('nix-meson-build-support/windows-version')

if host_machine.system() == 'windows'
deps_other += cxx.find_library('ws2_32')
endif

this_library = library(
'nixcmd',
sources,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,68 @@
#include "nix/util/unix-domain-socket.hh"
#include "nix/util/util.hh"

#include <sys/socket.h>
#include <sys/un.h>
#include <poll.h>
#include <sys/types.h>

#ifdef _WIN32
# include <winsock2.h>
# include <afunix.h>
#else
# include <sys/socket.h>
# include <sys/un.h>
# include <poll.h>
#endif

#if defined(__APPLE__) || defined(__FreeBSD__)
# include <sys/ucred.h>
#endif

namespace nix::unix {
namespace nix {

#ifndef _WIN32
namespace unix {

PeerInfo getPeerInfo(Descriptor remote)
{
PeerInfo peer;

#if defined(SO_PEERCRED)
# if defined(SO_PEERCRED)

# if defined(__OpenBSD__)
# if defined(__OpenBSD__)
struct sockpeercred cred;
# else
# else
ucred cred;
# endif
# endif
socklen_t credLen = sizeof(cred);
if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == 0) {
peer.pid = cred.pid;
peer.uid = cred.uid;
peer.gid = cred.gid;
}

#elif defined(LOCAL_PEERCRED)
# elif defined(LOCAL_PEERCRED)

# if !defined(SOL_LOCAL)
# define SOL_LOCAL 0
# endif
# if !defined(SOL_LOCAL)
# define SOL_LOCAL 0
# endif

xucred cred;
socklen_t credLen = sizeof(cred);
if (getsockopt(remote, SOL_LOCAL, LOCAL_PEERCRED, &cred, &credLen) == 0)
peer.uid = cred.cr_uid;

#endif
# endif

return peer;
}

} // namespace unix
#endif

[[noreturn]] void serveUnixSocket(const ServeUnixSocketOptions & options, UnixSocketHandler handler)
{
std::vector<AutoCloseFD> listeningSockets;

#ifndef _WIN32
static constexpr int SD_LISTEN_FDS_START = 3;

// Handle socket-based activation by systemd.
Expand All @@ -68,42 +82,59 @@ PeerInfo getPeerInfo(Descriptor remote)
assert(count);
for (unsigned int i = 0; i < count; ++i) {
AutoCloseFD fdSocket(SD_LISTEN_FDS_START + i);
closeOnExec(fdSocket.get());
unix::closeOnExec(fdSocket.get());
listeningSockets.push_back(std::move(fdSocket));
}
}

// Otherwise, create and bind to a Unix domain socket.
else {
#else
{
#endif
createDirs(options.socketPath.parent_path());
listeningSockets.push_back(createUnixDomainSocket(options.socketPath.string(), options.socketMode));
}

#ifndef _WIN32
std::vector<struct pollfd> fds;
for (auto & i : listeningSockets)
fds.push_back({.fd = i.get(), .events = POLLIN});
#endif

// Loop accepting connections.
while (1) {
try {
checkInterrupt();

#ifndef _WIN32
auto count = poll(fds.data(), fds.size(), -1);
if (count == -1) {
if (errno == EINTR)
continue;
throw SysError("polling for incoming connections");
}

for (auto & fd : fds) {
if (!fd.revents)
for (auto & pollfd : fds) {
if (!pollfd.revents)
continue;
Socket fd = toSocket(pollfd.fd);
#else
assert(listeningSockets.size() == 1);
{
Socket fd = toSocket(listeningSockets[0].get());
#endif

// Accept a connection.
struct sockaddr_un remoteAddr;
socklen_t remoteAddrLen = sizeof(remoteAddr);
#ifndef _WIN32
socklen_t
#else
int
#endif
remoteAddrLen = sizeof(remoteAddr);

AutoCloseFD remote = accept(fd.fd, (struct sockaddr *) &remoteAddr, &remoteAddrLen);
AutoCloseFD remote = fromSocket(accept(fd, (struct sockaddr *) &remoteAddr, &remoteAddrLen));
checkInterrupt();
if (!remote) {
if (errno == EINTR)
Expand All @@ -123,4 +154,4 @@ PeerInfo getPeerInfo(Descriptor remote)
}
}

} // namespace nix::unix
} // namespace nix
2 changes: 1 addition & 1 deletion src/libutil/include/nix/util/processes.hh
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct ProcessOptions
};

#ifndef _WIN32
pid_t startProcess(std::function<void()> fun, const ProcessOptions & options = ProcessOptions());
pid_t startProcess(std::move_only_function<void()> fun, const ProcessOptions & options = ProcessOptions());
#endif

/**
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/include/nix/util/unix-domain-socket.hh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include "nix/util/file-descriptor.hh"
#include "nix/util/socket.hh"

#include <unistd.h>
#include <sys/types.h>

#include <filesystem>

Expand Down
4 changes: 2 additions & 2 deletions src/libutil/unix/processes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ void killUser(uid_t uid)

//////////////////////////////////////////////////////////////////////

using ChildWrapperFunction = std::function<void()>;
using ChildWrapperFunction = std::move_only_function<void()>;

/* Wrapper around vfork to prevent the child process from clobbering
the caller's stack frame in the parent. */
Expand Down Expand Up @@ -208,7 +208,7 @@ static int childEntry(void * arg)
}
#endif

pid_t startProcess(std::function<void()> fun, const ProcessOptions & options)
pid_t startProcess(std::move_only_function<void()> fun, const ProcessOptions & options)
{
auto newLogger = makeSimpleLogger();
ChildWrapperFunction wrapper = [&] {
Expand Down
Loading
Loading