Rework GetListOfFDs API

PiperOrigin-RevId: 395043959
Change-Id: I77ce13f0c786d3644971ed239f3106319667e979
This commit is contained in:
Kevin Hamacher 2021-09-06 01:00:42 -07:00 committed by Copybara-Service
parent 289adcff06
commit eb2c5a66f4
5 changed files with 54 additions and 34 deletions

View File

@ -384,8 +384,11 @@ cc_library(
"//sandboxed_api/util:file_helpers", "//sandboxed_api/util:file_helpers",
"//sandboxed_api/util:fileops", "//sandboxed_api/util:fileops",
"//sandboxed_api/util:raw_logging", "//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:status",
"//sandboxed_api/util:strerror", "//sandboxed_api/util:strerror",
"@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings", "@com_google_absl//absl/strings",
"@com_google_glog//:glog", "@com_google_glog//:glog",
], ],
@ -415,6 +418,7 @@ cc_library(
"//sandboxed_api/util:status", "//sandboxed_api/util:status",
"//sandboxed_api/util:strerror", "//sandboxed_api/util:strerror",
"@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/memory", "@com_google_absl//absl/memory",
"@com_google_absl//absl/status", "@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor", "@com_google_absl//absl/status:statusor",

View File

@ -368,6 +368,7 @@ add_library(sandbox2_sanitizer ${SAPI_LIB_TYPE}
add_library(sandbox2::sanitizer ALIAS sandbox2_sanitizer) add_library(sandbox2::sanitizer ALIAS sandbox2_sanitizer)
target_link_libraries(sandbox2_sanitizer target_link_libraries(sandbox2_sanitizer
PRIVATE absl::core_headers PRIVATE absl::core_headers
absl::flat_hash_set
absl::strings absl::strings
sapi::file_helpers sapi::file_helpers
sapi::fileops sapi::fileops
@ -384,6 +385,7 @@ add_library(sandbox2_forkserver ${SAPI_LIB_TYPE}
add_library(sandbox2::forkserver ALIAS sandbox2_forkserver) add_library(sandbox2::forkserver ALIAS sandbox2_forkserver)
target_link_libraries(sandbox2_forkserver PRIVATE target_link_libraries(sandbox2_forkserver PRIVATE
absl::flat_hash_map absl::flat_hash_map
absl::flat_hash_set
absl::memory absl::memory
absl::status absl::status
absl::statusor absl::statusor

View File

@ -35,6 +35,7 @@
#include <cstring> #include <cstring>
#include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
@ -107,7 +108,7 @@ void MoveFDs(std::initializer_list<std::pair<int*, int>> move_fds,
} }
} }
void RunInitProcess(std::set<int> open_fds) { void RunInitProcess(const absl::flat_hash_set<int>& open_fds) {
if (prctl(PR_SET_NAME, "S2-INIT-PROC", 0, 0, 0) != 0) { if (prctl(PR_SET_NAME, "S2-INIT-PROC", 0, 0, 0) != 0) {
SAPI_RAW_PLOG(WARNING, "prctl(PR_SET_NAME, 'S2-INIT-PROC')"); SAPI_RAW_PLOG(WARNING, "prctl(PR_SET_NAME, 'S2-INIT-PROC')");
} }
@ -266,9 +267,11 @@ void ForkServer::LaunchChild(const ForkRequest& request, int execve_fd,
SanitizeEnvironment(); SanitizeEnvironment();
std::set<int> open_fds; absl::StatusOr<absl::flat_hash_set<int>> open_fds = sanitizer::GetListOfFDs();
if (!sanitizer::GetListOfFDs(&open_fds)) { if (!open_fds.ok()) {
SAPI_RAW_LOG(WARNING, "Could not get list of current open FDs"); SAPI_RAW_LOG(WARNING, "Could not get list of current open FDs: %s",
std::string(open_fds.status().message()).c_str());
open_fds = absl::flat_hash_set<int>();
} }
InitializeNamespaces(request, uid, gid, avoid_pivot_root); InitializeNamespaces(request, uid, gid, avoid_pivot_root);
@ -297,7 +300,7 @@ void ForkServer::LaunchChild(const ForkRequest& request, int execve_fd,
SAPI_RAW_PLOG(FATAL, "Could not spawn init process"); SAPI_RAW_PLOG(FATAL, "Could not spawn init process");
} }
if (child != 0) { if (child != 0) {
RunInitProcess(open_fds); RunInitProcess(*open_fds);
} }
// Send sandboxee pid // Send sandboxee pid
auto status = SendPid(signaling_fd); auto status = SendPid(signaling_fd);

View File

@ -35,6 +35,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "absl/container/flat_hash_set.h"
#include "absl/strings/numbers.h" #include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h" #include "absl/strings/str_split.h"
@ -42,6 +43,7 @@
#include "sandboxed_api/util/file_helpers.h" #include "sandboxed_api/util/file_helpers.h"
#include "sandboxed_api/util/fileops.h" #include "sandboxed_api/util/fileops.h"
#include "sandboxed_api/util/raw_logging.h" #include "sandboxed_api/util/raw_logging.h"
#include "sandboxed_api/util/status_macros.h"
#include "sandboxed_api/util/strerror.h" #include "sandboxed_api/util/strerror.h"
namespace sandbox2::sanitizer { namespace sandbox2::sanitizer {
@ -52,55 +54,62 @@ namespace file_util = ::sapi::file_util;
constexpr char kProcSelfFd[] = "/proc/self/fd"; constexpr char kProcSelfFd[] = "/proc/self/fd";
// Reads filenames inside the directory and converts them to numerical values. // Reads filenames inside the directory and converts them to numerical values.
bool ListNumericalDirectoryEntries(const std::string& directory, absl::StatusOr<absl::flat_hash_set<int>> ListNumericalDirectoryEntries(
std::set<int>* nums) { const std::string& directory) {
absl::flat_hash_set<int> result;
std::vector<std::string> entries; std::vector<std::string> entries;
std::string error; std::string error;
if (!file_util::fileops::ListDirectoryEntries(directory, &entries, &error)) { if (!file_util::fileops::ListDirectoryEntries(directory, &entries, &error)) {
SAPI_RAW_LOG(WARNING, "List directory entries for '%s' failed: %s", return absl::InternalError(absl::StrCat("List directory entries for '",
kProcSelfFd, error.c_str()); directory, "' failed: ", error));
return false;
} }
result.reserve(entries.size());
for (const auto& entry : entries) { for (const auto& entry : entries) {
int num; int num;
if (!absl::SimpleAtoi(entry, &num)) { if (!absl::SimpleAtoi(entry, &num)) {
SAPI_RAW_LOG(WARNING, "Cannot convert %s to a number", entry.c_str()); return absl::InternalError(
return false; absl::StrCat("Cannot convert ", entry, " to a number"));
} }
nums->insert(num); result.insert(num);
} }
return true; return result;
} }
} // namespace } // namespace
bool GetListOfFDs(std::set<int>* fds) { absl::StatusOr<absl::flat_hash_set<int>> GetListOfFDs() {
if (!ListNumericalDirectoryEntries(kProcSelfFd, fds)) { SAPI_ASSIGN_OR_RETURN(absl::flat_hash_set<int> fds,
return false; ListNumericalDirectoryEntries(kProcSelfFd));
}
// Exclude the dirfd which was opened in ListDirectoryEntries. // Exclude the dirfd which was opened in ListDirectoryEntries.
// Most probably will be the highest fd, hence the reverse order. for (auto it = fds.begin(), end = fds.end(); it != end; ++it) {
for (auto it = fds->rbegin(), end = fds->rend(); it != end; ++it) {
if (access(absl::StrCat(kProcSelfFd, "/", *it).c_str(), F_OK) != 0) { if (access(absl::StrCat(kProcSelfFd, "/", *it).c_str(), F_OK) != 0) {
fds->erase(*it); fds.erase(it);
break; break;
} }
} }
return true; return fds;
} }
bool GetListOfTasks(int pid, std::set<int>* tasks) { bool GetListOfTasks(int pid, std::set<int>* tasks) {
const std::string task_dir = absl::StrCat("/proc/", pid, "/task"); const std::string task_dir = absl::StrCat("/proc/", pid, "/task");
return ListNumericalDirectoryEntries(task_dir, tasks); auto task_entries = ListNumericalDirectoryEntries(task_dir);
} if (!task_entries.ok()) {
bool CloseAllFDsExcept(const std::set<int>& fd_exceptions) {
std::set<int> fds;
if (!GetListOfFDs(&fds)) {
return false; return false;
} }
for (auto fd : fds) { tasks->clear();
tasks->insert(task_entries->begin(), task_entries->end());
return true;
}
bool CloseAllFDsExcept(const std::set<int>& fd_exceptions) {
absl::StatusOr<absl::flat_hash_set<int>> fds = GetListOfFDs();
if (!fds.ok()) {
return false;
}
for (auto fd : *fds) {
if (fd_exceptions.find(fd) != fd_exceptions.end()) { if (fd_exceptions.find(fd) != fd_exceptions.end()) {
continue; continue;
} }
@ -111,12 +120,12 @@ bool CloseAllFDsExcept(const std::set<int>& fd_exceptions) {
} }
bool MarkAllFDsAsCOEExcept(const std::set<int>& fd_exceptions) { bool MarkAllFDsAsCOEExcept(const std::set<int>& fd_exceptions) {
std::set<int> fds; auto fds = GetListOfFDs();
if (!GetListOfFDs(&fds)) { if (!fds.ok()) {
return false; return false;
} }
for (auto fd : fds) { for (auto fd : *fds) {
if (fd_exceptions.find(fd) != fd_exceptions.end()) { if (fd_exceptions.find(fd) != fd_exceptions.end()) {
continue; continue;
} }

View File

@ -21,12 +21,14 @@
#include <set> #include <set>
#include "absl/base/macros.h" #include "absl/base/macros.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/statusor.h"
namespace sandbox2 { namespace sandbox2 {
namespace sanitizer { namespace sanitizer {
// Reads a list of open file descriptors in the current process. // Reads a list of open file descriptors in the current process.
bool GetListOfFDs(std::set<int>* fds); absl::StatusOr<absl::flat_hash_set<int>> GetListOfFDs();
// Closes all file descriptors in the current process except the ones in // Closes all file descriptors in the current process except the ones in
// fd_exceptions. // fd_exceptions.