diff --git a/src/base/socket.cc b/src/base/socket.cc index a30c6af446..76dc73f5fd 100644 --- a/src/base/socket.cc +++ b/src/base/socket.cc @@ -61,75 +61,12 @@ namespace gem5 { -namespace -{ - -bool -isSocketNameAbstract(const std::string &path) -{ - if (path.empty()) { - return false; - } - // No null byte should be present in the path - return path.front() == '@'; -} - -std::string -resolve(const std::string &path) -{ - if (path.empty()) { - return path; - } - if (isSocketNameAbstract(path)) { - return '\0' + path.substr(1); - } - return simout.resolve(path); -} - -} // namespace bool ListenSocket::listeningDisabled = false; bool ListenSocket::anyListening = false; bool ListenSocket::bindToLoopback = false; -UnixSocketAddr -UnixSocketAddr::build(const std::string &path) -{ - sockaddr_un addr = {.sun_family = AF_UNIX, .sun_path = {}}; - - const bool is_abstract = isSocketNameAbstract(path); - size_t max_len = sizeof(addr.sun_path); - if (!is_abstract) { - // File based socket names need to be null terminated - max_len -= 1; - } - - std::string resolved_path = resolve(path); - std::string fmt_path = replace(resolved_path, '\0', '@'); - if (resolved_path.size() > max_len) { - resolved_path = resolved_path.substr(0, max_len); - const std::string untruncated_path = std::move(fmt_path); - fmt_path = replace(resolved_path, '\0', '@'); - warn("SocketPath: unix socket path truncated from '%s' to '%s'", - untruncated_path, fmt_path); - } - - // We can't use strncpy here, since abstract sockets start with \0 which - // will make strncpy think that the string is empty. - memcpy(addr.sun_path, resolved_path.c_str(), resolved_path.size()); - // We can't use sizeof(sockaddr_un) for abstract sockets, since all - // sizeof(sun_path) bytes are used in representing the path. - const size_t path_size = - is_abstract ? resolved_path.size() : sizeof(addr.sun_path); - const size_t addr_size = offsetof(sockaddr_un, sun_path) + path_size; - - return UnixSocketAddr{.addr = std::move(addr), - .addrSize = addr_size, - .isAbstract = is_abstract, - .formattedPath = std::move(fmt_path)}; -} - void ListenSocket::cleanup() { diff --git a/src/base/socket.hh b/src/base/socket.hh index 5ae02aa103..b8828e7f43 100644 --- a/src/base/socket.hh +++ b/src/base/socket.hh @@ -43,37 +43,6 @@ namespace gem5 { -/** - * @brief Wrapper around sockaddr_un, so that it can be used for both file - * based unix sockets as well as abstract unix sockets. - */ -struct UnixSocketAddr -{ - /** - * @brief Builds UnixSocketAddr from the given path. - * @pre: `path` either represents a file based unix socket, or an abstract - * unix socket. If `path` represents an abstract socket, it should - * start with the character '@', and it should not have any null - * bytes in the name. - * @param path: Pathname, where the socket should be instantiated. - * @return UnixSocketAddr - */ - static UnixSocketAddr build(const std::string &path); - - sockaddr_un addr; - // Size of `sockaddr_un addr`. This is equal to sizeof(sockaddr_un) if - // `addr` represents a normal file based unix socket. For abstract sockets - // however, the size could be different. Because all sizeof(sun_path) is - // used to represent the name of an abstract socket, addrSize for abstract - // sockets only count the number of characters actually used by sun_path, - // excluding any trailing null bytes. - size_t addrSize; - bool isAbstract; - // Formatted string for file based sockets look the same as addr.sun_path. - // For abstract sockets however, all null bytes are replaced with @ - std::string formattedPath; -}; - class ListenSocket : public Named { protected: diff --git a/src/base/socket.test.cc b/src/base/socket.test.cc index 7bf9e180c7..5fd0f3f129 100644 --- a/src/base/socket.test.cc +++ b/src/base/socket.test.cc @@ -45,79 +45,6 @@ using namespace gem5; * socket.cc have not been fully tested due to interaction with system-calls. */ -namespace { - -std::string -repeat(const std::string& str, size_t n) -{ - std::stringstream ss; - for (int i = 0; i < n; ++i) { - ss << str; - } - return ss.str(); -} - -} // namespace - -TEST(UnixSocketAddrTest, AbstractSocket) -{ - UnixSocketAddr sock_addr = UnixSocketAddr::build("@abstract"); - EXPECT_EQ(AF_UNIX, sock_addr.addr.sun_family); - // null byte will not show, so compare from the first byte - EXPECT_STREQ("abstract", sock_addr.addr.sun_path + 1); - EXPECT_TRUE(sock_addr.isAbstract); - EXPECT_STREQ("@abstract", sock_addr.formattedPath.c_str()); -} - -TEST(UnixSocketAddrTest, TruncatedAbstractSocket) -{ - // Test that address is truncated if longer than sizeof(sun_path) - constexpr size_t MaxSize = sizeof(std::declval().sun_path); - - // >sizeof(sun_path) bytes - std::string addr = "@" + repeat("123456789", 100); - ASSERT_GT(addr.size(), MaxSize); - std::string truncated_addr = addr.substr(0, MaxSize); - - UnixSocketAddr sock_addr = UnixSocketAddr::build(addr); - EXPECT_EQ(AF_UNIX, sock_addr.addr.sun_family); - // Use memcmp so that we can compare null bytes as well - std::string null_formatted = '\0' + truncated_addr.substr(1); - EXPECT_EQ(0, std::memcmp(null_formatted.c_str(), sock_addr.addr.sun_path, - MaxSize)); - EXPECT_TRUE(sock_addr.isAbstract); - EXPECT_EQ(truncated_addr, sock_addr.formattedPath); -} - -TEST(UnixSocketAddrTest, FileBasedSocket) -{ - std::string addr = "/home/parent/dir/x"; - UnixSocketAddr sock_addr = UnixSocketAddr::build(addr); - EXPECT_EQ(AF_UNIX, sock_addr.addr.sun_family); - EXPECT_STREQ(addr.c_str(), sock_addr.addr.sun_path); - EXPECT_FALSE(sock_addr.isAbstract); - EXPECT_EQ(addr, sock_addr.formattedPath); -} - -TEST(UnixSocketAddrTest, TruncatedFileBasedSocket) -{ - // sun_path should null terminate, so test that address is truncated if - // longer than sizeof(sun_path) - 1 bytes. - constexpr size_t MaxSize = - sizeof(std::declval().sun_path) - 1; - - // >sizeof(sun_path) - 1 bytes - std::string addr = "/" + repeat("123456789", 100); - ASSERT_GT(addr.size(), MaxSize); - std::string truncated_addr = addr.substr(0, MaxSize); - - UnixSocketAddr sock_addr = UnixSocketAddr::build(addr); - EXPECT_EQ(AF_UNIX, sock_addr.addr.sun_family); - EXPECT_STREQ(truncated_addr.c_str(), sock_addr.addr.sun_path); - EXPECT_FALSE(sock_addr.isAbstract); - EXPECT_EQ(truncated_addr, sock_addr.formattedPath); -} - class MockListenSocket : public ListenSocketInet { public: