diff --git a/Source/Common/FEXServerClient.cpp b/Source/Common/FEXServerClient.cpp index 424ecf0a09..0f37eee579 100644 --- a/Source/Common/FEXServerClient.cpp +++ b/Source/Common/FEXServerClient.cpp @@ -143,6 +143,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; } @@ -172,11 +190,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(&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) { diff --git a/Source/Common/FEXServerClient.h b/Source/Common/FEXServerClient.h index 14599c102e..6bad43fc07 100644 --- a/Source/Common/FEXServerClient.h +++ b/Source/Common/FEXServerClient.h @@ -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); diff --git a/Source/Tools/FEXServer/Main.cpp b/Source/Tools/FEXServer/Main.cpp index 40ae2116b7..36fc87279a 100644 --- a/Source/Tools/FEXServer/Main.cpp +++ b/Source/Tools/FEXServer/Main.cpp @@ -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; diff --git a/Source/Tools/FEXServer/ProcessPipe.cpp b/Source/Tools/FEXServer/ProcessPipe.cpp index e379dfe34b..ad88364798 100644 --- a/Source/Tools/FEXServer/ProcessPipe.cpp +++ b/Source/Tools/FEXServer/ProcessPipe.cpp @@ -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 ShouldShutdown {false}; time_t RequestTimeout {10}; bool Foreground {false}; @@ -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(&addr), SizeOfAddr); + int Result = bind(fd, reinterpret_cast(&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 +436,7 @@ void CloseConnections() { // Close the server socket so no more connections can be started close(ServerSocketFD); + close(ServerFSSocketFD); } void WaitForRequests() { @@ -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(&Addr), &AddrSize); + int NewFD = accept(Event.fd, reinterpret_cast(&Addr), &AddrSize); // Add the new client to the temporary array NewPollFDs.emplace_back(pollfd { diff --git a/Source/Tools/FEXServer/ProcessPipe.h b/Source/Tools/FEXServer/ProcessPipe.h index 5c3f4c9b51..e4379bd351 100644 --- a/Source/Tools/FEXServer/ProcessPipe.h +++ b/Source/Tools/FEXServer/ProcessPipe.h @@ -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();