namespace_test: use lstat instead of stat, don't descent into procfs & sysfs

PiperOrigin-RevId: 565303140
Change-Id: I7600b60613f52260410098e617b00a2e4272b2fb
This commit is contained in:
Wiktor Garbacz 2023-09-14 02:08:31 -07:00 committed by Copybara-Service
parent b47a5ead07
commit 1475458939
3 changed files with 47 additions and 3 deletions

View File

@ -724,7 +724,9 @@ cc_test(
name = "namespace_test",
srcs = ["namespace_test.cc"],
copts = sapi_platform_copts(),
data = ["//sandboxed_api/sandbox2/testcases:namespace"],
data = [
"//sandboxed_api/sandbox2/testcases:namespace",
],
tags = [
"requires-net:external",
],

View File

@ -17,6 +17,7 @@
#include <unistd.h>
#include <cstdint>
#include <cstdlib>
#include <initializer_list>
#include <memory>
#include <string>
@ -29,7 +30,6 @@
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "sandboxed_api/config.h"
#include "sandboxed_api/sandbox2/allow_all_syscalls.h"
#include "sandboxed_api/sandbox2/executor.h"
#include "sandboxed_api/sandbox2/policy.h"
@ -49,12 +49,15 @@ using ::sapi::CreateDefaultPermissiveTestPolicy;
using ::sapi::CreateNamedTempFile;
using ::sapi::GetTestSourcePath;
using ::sapi::GetTestTempPath;
using ::testing::AllOf;
using ::testing::AnyOfArray;
using ::testing::Contains;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::Gt;
using ::testing::HasSubstr;
using ::testing::IsEmpty;
using ::testing::Matcher;
using ::testing::Ne;
using ::testing::SizeIs;
using ::testing::StartsWith;
@ -251,5 +254,39 @@ TEST(NamespaceTest, TestInterfacesWithNetwork) {
EXPECT_THAT(result, SizeIs(Gt(1)));
}
TEST(NamespaceTest, TestFiles) {
SKIP_ANDROID;
const std::string path = GetTestcaseBinPath("namespace");
std::vector<std::string> result =
RunSandboxeeWithArgsAndPolicy(path, {path, "6", "/"});
std::vector<Matcher<std::string>> lib_paths = {
StartsWith("/lib/"), // Often a symlink -> /usr/lib
StartsWith("/usr/lib/"),
StartsWith("/lib64/"), // Often a symlink -> /usr/lib64
StartsWith("/usr/lib64/")};
auto correct_lib_path_matcher =
AllOf(HasSubstr(".so"), AnyOfArray(lib_paths));
std::vector<Matcher<std::string>> matchers = {
correct_lib_path_matcher,
// Conditionally mapped if Tomoyo is active
StrEq(absl::StrCat("/dev/fd/", Comms::kSandbox2TargetExecFD)),
// System ldconfig cache
StrEq("/etc/ld.so.cache"),
// GRTE ldconfig cache
StrEq("/usr/grte/v4/etc/ld.so.cache"),
StrEq("/usr/grte/v5/etc/ld.so.cache"),
// procfs and sysfs
StartsWith("/proc"), StartsWith("/sys")};
// Coverage DIR
char* coverage_dir = getenv("COVERAGE_DIR");
if (coverage_dir != nullptr) {
matchers.push_back(StartsWith(coverage_dir));
}
for (const auto& file : result) {
EXPECT_THAT(file, AnyOfArray(matchers));
}
}
} // namespace
} // namespace sandbox2

View File

@ -51,7 +51,7 @@ using sapi::file_util::fileops::ListDirectoryEntries;
bool IsDirectory(const std::string& path) {
struct stat statbuf;
PCHECK(stat(path.c_str(), &statbuf) == 0);
PCHECK(lstat(path.c_str(), &statbuf) == 0) << "Failed to stat " << path;
return statbuf.st_mode & S_IFDIR;
}
@ -62,6 +62,11 @@ void ListDirectoriesRecursively(const std::string& path,
CHECK(ListDirectoryEntries(path, &entries, &error)) << error;
for (const std::string& entry : entries) {
std::string new_path = JoinPath(path, entry);
// Don't descent into /sys or /proc, just mark their existence
if (new_path == "/sys" || new_path == "/proc") {
files.push_back(new_path);
continue;
}
if (IsDirectory(new_path)) {
ListDirectoriesRecursively(new_path, files);
} else {