mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 14:00:16 +02:00
FEXServer: Listen on both abstract & named sockets
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.
This commit is contained in:
1 parent
a1aa2547ce
commit
d761fc44f4
5 files changed
+80
-19
No files matched your search
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
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 && errno != ENOENT)) {
|
||||
LogMan::Msg::EFmt("Couldn't connect to FEXServer socket {} {}", ServerSocketPath, errno);
|
||||
}
|
||||
} else {
|
||||
return SocketFD;
|
||||
}
|
||||
|
||||
close(SocketFD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool SetupClient(char* InterpreterPath) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
@@ -175,40 +176,58 @@ 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();
|
||||
// Unlink the socket file if it exists
|
||||
// We are being asked to create a daemon, not error check
|
||||
// We don't care if this failed or not
|
||||
unlink(ServerSocketPath.c_str());
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -422,6 +441,7 @@ void CloseConnections() {
|
||||
|
||||
// Close the server socket so no more connections can be started
|
||||
close(ServerSocketFD);
|
||||
close(ServerFSSocketFD);
|
||||
}
|
||||
|
||||
void WaitForRequests() {
|
||||
@@ -441,12 +461,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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user