mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Handle new representation of abstract UDS paths.
When abstract unix domain socket paths are displayed in /proc/net/unix, Linux historically emitted null bytes as padding at the end of the path. Newer versions of Linux (v4.9, e7947ea770d0de434d38a0f823e660d3fd4bebb5) display these as '@' characters. Update proc_net_unix test to handle both version of the padding. PiperOrigin-RevId: 266230200
This commit is contained in:
committed by
gVisor bot
parent
863e11ac4d
commit
f74affe203
@@ -56,19 +56,44 @@ struct UnixEntry {
|
||||
std::string path;
|
||||
};
|
||||
|
||||
// Abstract socket paths can have either trailing null bytes or '@'s as padding
|
||||
// at the end, depending on the linux version. This function strips any such
|
||||
// padding.
|
||||
void StripAbstractPathPadding(std::string* s) {
|
||||
const char pad_char = s->back();
|
||||
if (pad_char != '\0' && pad_char != '@') {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto last_pos = s->find_last_not_of(pad_char);
|
||||
if (last_pos != std::string::npos) {
|
||||
s->resize(last_pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Precondition: addr must be a unix socket address (i.e. sockaddr_un) and
|
||||
// addr->sun_path must be null-terminated. This is always the case if addr comes
|
||||
// from Linux:
|
||||
//
|
||||
// Per man unix(7):
|
||||
//
|
||||
// "When the address of a pathname socket is returned (by [getsockname(2)]), its
|
||||
// length is
|
||||
//
|
||||
// offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1
|
||||
//
|
||||
// and sun_path contains the null-terminated pathname."
|
||||
std::string ExtractPath(const struct sockaddr* addr) {
|
||||
const char* path =
|
||||
reinterpret_cast<const struct sockaddr_un*>(addr)->sun_path;
|
||||
// Note: sockaddr_un.sun_path is an embedded character array of length
|
||||
// UNIX_PATH_MAX, so we can always safely dereference the first 2 bytes below.
|
||||
//
|
||||
// The kernel also enforces that the path is always null terminated.
|
||||
// We also rely on the path being null-terminated.
|
||||
if (path[0] == 0) {
|
||||
// Abstract socket paths are null padded to the end of the struct
|
||||
// sockaddr. However, these null bytes may or may not show up in
|
||||
// /proc/net/unix depending on the kernel version. Truncate after the first
|
||||
// null byte (by treating path as a c-string).
|
||||
return StrCat("@", &path[1]);
|
||||
std::string abstract_path = StrCat("@", &path[1]);
|
||||
StripAbstractPathPadding(&abstract_path);
|
||||
return abstract_path;
|
||||
}
|
||||
return std::string(path);
|
||||
}
|
||||
@@ -96,14 +121,6 @@ PosixErrorOr<std::vector<UnixEntry>> ProcNetUnixEntries() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Abstract socket paths can have trailing null bytes in them depending on
|
||||
// the linux version. Strip off everything after a null byte, including the
|
||||
// null byte.
|
||||
std::size_t null_pos = line.find('\0');
|
||||
if (null_pos != std::string::npos) {
|
||||
line.erase(null_pos);
|
||||
}
|
||||
|
||||
// Parse a single entry from /proc/net/unix.
|
||||
//
|
||||
// Sample file:
|
||||
@@ -151,6 +168,7 @@ PosixErrorOr<std::vector<UnixEntry>> ProcNetUnixEntries() {
|
||||
entry.path = "";
|
||||
if (fields.size() > 1) {
|
||||
entry.path = fields[1];
|
||||
StripAbstractPathPadding(&entry.path);
|
||||
}
|
||||
|
||||
entries.push_back(entry);
|
||||
@@ -200,8 +218,8 @@ TEST(ProcNetUnix, FilesystemBindAcceptConnect) {
|
||||
|
||||
std::string path1 = ExtractPath(sockets->first_addr());
|
||||
std::string path2 = ExtractPath(sockets->second_addr());
|
||||
std::cout << StreamFormat("Server socket address: %s\n", path1);
|
||||
std::cout << StreamFormat("Client socket address: %s\n", path2);
|
||||
std::cerr << StreamFormat("Server socket address (path1): %s\n", path1);
|
||||
std::cerr << StreamFormat("Client socket address (path2): %s\n", path2);
|
||||
|
||||
std::vector<UnixEntry> entries =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(ProcNetUnixEntries());
|
||||
@@ -224,8 +242,8 @@ TEST(ProcNetUnix, AbstractBindAcceptConnect) {
|
||||
|
||||
std::string path1 = ExtractPath(sockets->first_addr());
|
||||
std::string path2 = ExtractPath(sockets->second_addr());
|
||||
std::cout << StreamFormat("Server socket address: '%s'\n", path1);
|
||||
std::cout << StreamFormat("Client socket address: '%s'\n", path2);
|
||||
std::cerr << StreamFormat("Server socket address (path1): '%s'\n", path1);
|
||||
std::cerr << StreamFormat("Client socket address (path2): '%s'\n", path2);
|
||||
|
||||
std::vector<UnixEntry> entries =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(ProcNetUnixEntries());
|
||||
|
||||
Reference in New Issue
Block a user