Skip to content

Commit

Permalink
FEXServer: Listen on both abstract & named sockets
Browse files Browse the repository at this point in the history
Abstract sockets have one limitation: they are bound to a network
namespace. Chromium/CEF sandboxes using a new netns, which breaks
connecting to the FEXServer.

To work around this, use and try *both* abstract and named sockets. As
long as either the filesystem or the network is unsandboxed, things will
work. If both are sandboxed, there isn't much we can do... but at that
point we shouldn't be reinitializing the FEXServer connection anyway
since the FS should be available on FEXInterpreter startup.
  • Loading branch information
asahilina committed Nov 18, 2024
1 parent 2c6484d commit 6bc8107
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 19 deletions.
40 changes: 37 additions & 3 deletions Source/Common/FEXServerClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,24 @@ fextl::string GetServerSocketName() {
return ServerSocketPath;
}

fextl::string GetServerSocketPath() {
FEX_CONFIG_OPT(ServerSocketPath, SERVERSOCKETPATH);

auto name = ServerSocketPath();

if (name.starts_with("/")) {
return name;
}

auto Folder = GetTempFolder();

if (name.empty()) {
return fextl::fmt::format("{}/{}.FEXServer.Socket", Folder, ::geteuid());
} else {
return fextl::fmt::format("{}/{}", Folder, name);
}
}

int GetServerFD() {
return ServerFD;
}
Expand Down Expand Up @@ -179,11 +197,27 @@ int ConnectToServer(ConnectionOption ConnectionOption) {
if (ConnectionOption == ConnectionOption::Default || errno != ECONNREFUSED) {
LogMan::Msg::EFmt("Couldn't connect to FEXServer socket {} {} {}", ServerSocketName, errno, strerror(errno));
}
close(SocketFD);
return -1;
} else {
return SocketFD;
}

return SocketFD;
// Try again with a path-based socket, since abstract sockets will fail if we have been
// placed in a new netns as part of a sandbox.
auto ServerSocketPath = GetServerSocketPath();

SizeOfSocketString = std::min(ServerSocketPath.size(), sizeof(addr.sun_path) - 1);
strncpy(addr.sun_path, ServerSocketPath.data(), SizeOfSocketString);
SizeOfAddr = sizeof(addr.sun_family) + SizeOfSocketString;
if (connect(SocketFD, reinterpret_cast<struct sockaddr*>(&addr), SizeOfAddr) == -1) {
if (ConnectionOption == ConnectionOption::Default || errno != ECONNREFUSED) {
LogMan::Msg::EFmt("Couldn't connect to FEXServer socket {} {} {}", ServerSocketPath, errno, strerror(errno));
}
} else {
return SocketFD;
}

close(SocketFD);
return -1;
}

bool SetupClient(char* InterpreterPath) {
Expand Down
1 change: 1 addition & 0 deletions Source/Common/FEXServerClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ fextl::string GetServerRootFSLockFile();
fextl::string GetTempFolder();
fextl::string GetServerMountFolder();
fextl::string GetServerSocketName();
fextl::string GetServerSocketPath();
int GetServerFD();

bool SetupClient(char* InterpreterPath);
Expand Down
8 changes: 7 additions & 1 deletion Source/Tools/FEXServer/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,13 @@ int main(int argc, char** argv, char** const envp) {
return -1;
}

if (!ProcessPipe::InitializeServerSocket()) {
if (!ProcessPipe::InitializeServerSocket(true)) {
// Couldn't create server socket for some reason
PipeScanner::ClosePipes();
return -1;
}

if (!ProcessPipe::InitializeServerSocket(false)) {
// Couldn't create server socket for some reason
PipeScanner::ClosePipes();
return -1;
Expand Down
43 changes: 29 additions & 14 deletions Source/Tools/FEXServer/ProcessPipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace ProcessPipe {
constexpr int USER_PERMS = S_IRWXU | S_IRWXG | S_IRWXO;
int ServerLockFD {-1};
int ServerSocketFD {-1};
int ServerFSSocketFD {-1};
std::atomic<bool> ShouldShutdown {false};
time_t RequestTimeout {10};
bool Foreground {false};
Expand Down Expand Up @@ -175,40 +176,53 @@ bool InitializeServerPipe() {
return true;
}

bool InitializeServerSocket() {
auto ServerSocketName = FEXServerClient::GetServerSocketName();
bool InitializeServerSocket(bool abstract) {

// Create the initial unix socket
ServerSocketFD = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (ServerSocketFD == -1) {
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (fd == -1) {
LogMan::Msg::EFmt("Couldn't create AF_UNIX socket: {} {}\n", errno, strerror(errno));
return false;
}

struct sockaddr_un addr {};
addr.sun_family = AF_UNIX;
size_t SizeOfSocketString = std::min(ServerSocketName.size() + 1, sizeof(addr.sun_path) - 1);
addr.sun_path[0] = 0; // Abstract AF_UNIX sockets start with \0
strncpy(addr.sun_path + 1, ServerSocketName.data(), SizeOfSocketString);

size_t SizeOfSocketString;
if (abstract) {
auto ServerSocketName = FEXServerClient::GetServerSocketName();
SizeOfSocketString = std::min(ServerSocketName.size() + 1, sizeof(addr.sun_path) - 1);
addr.sun_path[0] = 0; // Abstract AF_UNIX sockets start with \0
strncpy(addr.sun_path + 1, ServerSocketName.data(), SizeOfSocketString);
} else {
auto ServerSocketPath = FEXServerClient::GetServerSocketPath();
SizeOfSocketString = std::min(ServerSocketPath.size(), sizeof(addr.sun_path) - 1);
strncpy(addr.sun_path, ServerSocketPath.data(), SizeOfSocketString);
}
// Include final null character.
size_t SizeOfAddr = sizeof(addr.sun_family) + SizeOfSocketString;

// Bind the socket to the path
int Result = bind(ServerSocketFD, reinterpret_cast<struct sockaddr*>(&addr), SizeOfAddr);
int Result = bind(fd, reinterpret_cast<struct sockaddr*>(&addr), SizeOfAddr);
if (Result == -1) {
LogMan::Msg::EFmt("Couldn't bind AF_UNIX socket '{}': {} {}\n", addr.sun_path, errno, strerror(errno));
close(ServerSocketFD);
ServerSocketFD = -1;
close(fd);
return false;
}

listen(ServerSocketFD, 16);
listen(fd, 16);
PollFDs.emplace_back(pollfd {
.fd = ServerSocketFD,
.fd = fd,
.events = POLLIN,
.revents = 0,
});

if (abstract) {
ServerSocketFD = fd;
} else {
ServerFSSocketFD = fd;
}

return true;
}

Expand Down Expand Up @@ -422,6 +436,7 @@ void CloseConnections() {

// Close the server socket so no more connections can be started
close(ServerSocketFD);
close(ServerFSSocketFD);
}

void WaitForRequests() {
Expand All @@ -441,12 +456,12 @@ void WaitForRequests() {
bool Erase {};

if (Event.revents != 0) {
if (Event.fd == ServerSocketFD) {
if (Event.fd == ServerSocketFD || Event.fd == ServerFSSocketFD) {
if (Event.revents & POLLIN) {
// If it is the listen socket then we have a new connection
struct sockaddr_storage Addr {};
socklen_t AddrSize {};
int NewFD = accept(ServerSocketFD, reinterpret_cast<struct sockaddr*>(&Addr), &AddrSize);
int NewFD = accept(Event.fd, reinterpret_cast<struct sockaddr*>(&Addr), &AddrSize);

// Add the new client to the temporary array
NewPollFDs.emplace_back(pollfd {
Expand Down
2 changes: 1 addition & 1 deletion Source/Tools/FEXServer/ProcessPipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace ProcessPipe {
bool InitializeServerPipe();
bool InitializeServerSocket();
bool InitializeServerSocket(bool abstract);
void WaitForRequests();
void SetConfiguration(bool Foreground, uint32_t PersistentTimeout);
void Shutdown();
Expand Down

0 comments on commit 6bc8107

Please sign in to comment.