mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Introduce util::CharPtrArray with proper ownership semantics
Replace existing calls to VecStringToCharPtrArr PiperOrigin-RevId: 417383812 Change-Id: Ibf9d878df5ada2cb3a0872f7ca7cab96c304a5c1
This commit is contained in:
parent
a44e57e243
commit
3f5184770d
|
@ -560,6 +560,7 @@ cc_library(
|
||||||
"//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:status",
|
||||||
|
"@com_google_absl//absl/algorithm:container",
|
||||||
"@com_google_absl//absl/base:core_headers",
|
"@com_google_absl//absl/base:core_headers",
|
||||||
"@com_google_absl//absl/status",
|
"@com_google_absl//absl/status",
|
||||||
"@com_google_absl//absl/status:statusor",
|
"@com_google_absl//absl/status:statusor",
|
||||||
|
|
|
@ -499,7 +499,8 @@ add_library(sandbox2_util ${SAPI_LIB_TYPE}
|
||||||
)
|
)
|
||||||
add_library(sandbox2::util ALIAS sandbox2_util)
|
add_library(sandbox2::util ALIAS sandbox2_util)
|
||||||
target_link_libraries(sandbox2_util
|
target_link_libraries(sandbox2_util
|
||||||
PRIVATE absl::core_headers
|
PRIVATE absl::algorithm_container
|
||||||
|
absl::core_headers
|
||||||
absl::str_format
|
absl::str_format
|
||||||
absl::strings
|
absl::strings
|
||||||
sapi::config
|
sapi::config
|
||||||
|
|
|
@ -38,9 +38,7 @@ namespace sandbox2 {
|
||||||
namespace file_util = ::sapi::file_util;
|
namespace file_util = ::sapi::file_util;
|
||||||
|
|
||||||
std::vector<std::string> Executor::CopyEnviron() {
|
std::vector<std::string> Executor::CopyEnviron() {
|
||||||
std::vector<std::string> environ_copy;
|
return util::CharPtrArray(environ).ToStringVector();
|
||||||
util::CharPtrArrToVecString(environ, &environ_copy);
|
|
||||||
return environ_copy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t Executor::StartSubProcess(int32_t clone_flags, const Namespace* ns,
|
pid_t Executor::StartSubProcess(int32_t clone_flags, const Namespace* ns,
|
||||||
|
|
|
@ -255,8 +255,6 @@ void ForkServer::LaunchChild(const ForkRequest& request, int execve_fd,
|
||||||
// sandoxing can cause syscall violations (e.g. related to memory management).
|
// sandoxing can cause syscall violations (e.g. related to memory management).
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
std::vector<std::string> envs;
|
std::vector<std::string> envs;
|
||||||
const char** argv = nullptr;
|
|
||||||
const char** envp = nullptr;
|
|
||||||
if (will_execve) {
|
if (will_execve) {
|
||||||
PrepareExecveArgs(request, &args, &envs);
|
PrepareExecveArgs(request, &args, &envs);
|
||||||
}
|
}
|
||||||
|
@ -328,25 +326,24 @@ void ForkServer::LaunchChild(const ForkRequest& request, int execve_fd,
|
||||||
c.PrepareEnvironment();
|
c.PrepareEnvironment();
|
||||||
|
|
||||||
envs.push_back(c.GetFdMapEnvVar());
|
envs.push_back(c.GetFdMapEnvVar());
|
||||||
// Convert argv and envs to const char **. No need to free it, as the
|
// Convert args and envs before enabling sandbox (it'll allocate which might
|
||||||
// code will either execve() or exit().
|
// be blocked).
|
||||||
argv = util::VecStringToCharPtrArr(args);
|
util::CharPtrArray argv = util::CharPtrArray::FromStringVector(args);
|
||||||
envp = util::VecStringToCharPtrArr(envs);
|
util::CharPtrArray envp = util::CharPtrArray::FromStringVector(envs);
|
||||||
|
|
||||||
c.EnableSandbox();
|
c.EnableSandbox();
|
||||||
if (request.mode() == FORKSERVER_FORK_JOIN_SANDBOX_UNWIND) {
|
if (request.mode() == FORKSERVER_FORK_JOIN_SANDBOX_UNWIND) {
|
||||||
exit(RunLibUnwindAndSymbolizer(&client_comms) ? EXIT_SUCCESS
|
exit(RunLibUnwindAndSymbolizer(&client_comms) ? EXIT_SUCCESS
|
||||||
: EXIT_FAILURE);
|
: EXIT_FAILURE);
|
||||||
} else {
|
} else {
|
||||||
ExecuteProcess(execve_fd, argv, envp);
|
ExecuteProcess(execve_fd, argv.data(), envp.data());
|
||||||
}
|
}
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (will_execve) {
|
if (will_execve) {
|
||||||
argv = util::VecStringToCharPtrArr(args);
|
ExecuteProcess(execve_fd, util::CharPtrArray::FromStringVector(args).data(),
|
||||||
envp = util::VecStringToCharPtrArr(envs);
|
util::CharPtrArray::FromStringVector(envs).data());
|
||||||
ExecuteProcess(execve_fd, argv, envp);
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,8 +562,8 @@ void ForkServer::SanitizeEnvironment() {
|
||||||
absl::StrCat("while sanitizing process: ", status.message()).c_str());
|
absl::StrCat("while sanitizing process: ", status.message()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForkServer::ExecuteProcess(int execve_fd, const char** argv,
|
void ForkServer::ExecuteProcess(int execve_fd, const char* const* argv,
|
||||||
const char** envp) {
|
const char* const* envp) {
|
||||||
// Do not add any code before execve(), as it's subject to seccomp policies.
|
// Do not add any code before execve(), as it's subject to seccomp policies.
|
||||||
// Indicate that it's a special execve(), by setting 4th, 5th and 6th syscall
|
// Indicate that it's a special execve(), by setting 4th, 5th and 6th syscall
|
||||||
// argument to magic values.
|
// argument to magic values.
|
||||||
|
|
|
@ -72,8 +72,8 @@ class ForkServer {
|
||||||
static void SanitizeEnvironment();
|
static void SanitizeEnvironment();
|
||||||
|
|
||||||
// Executes the sandboxee, or exit with Executor::kFailedExecve.
|
// Executes the sandboxee, or exit with Executor::kFailedExecve.
|
||||||
static void ExecuteProcess(int execve_fd, const char** argv,
|
static void ExecuteProcess(int execve_fd, const char* const* argv,
|
||||||
const char** envp);
|
const char* const* envp);
|
||||||
|
|
||||||
// Runs namespace initializers for a sandboxee.
|
// Runs namespace initializers for a sandboxee.
|
||||||
static void InitializeNamespaces(const ForkRequest& request, uid_t uid,
|
static void InitializeNamespaces(const ForkRequest& request, uid_t uid,
|
||||||
|
|
|
@ -51,18 +51,17 @@ namespace {
|
||||||
|
|
||||||
// Runs a new process and returns 0 if the process terminated with 0.
|
// Runs a new process and returns 0 if the process terminated with 0.
|
||||||
int RunTestcase(const std::string& path, const std::vector<std::string>& args) {
|
int RunTestcase(const std::string& path, const std::vector<std::string>& args) {
|
||||||
|
util::CharPtrArray array = util::CharPtrArray::FromStringVector(args);
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
PLOG(ERROR) << "fork()";
|
PLOG(ERROR) << "fork()";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
const char** argv = util::VecStringToCharPtrArr(args);
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
execv(path.c_str(), const_cast<char**>(argv));
|
execv(path.c_str(), const_cast<char**>(array.data()));
|
||||||
PLOG(ERROR) << "execv('" << path << "')";
|
PLOG(ERROR) << "execv('" << path << "')";
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
delete[] argv;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int status;
|
int status;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "absl/algorithm/container.h"
|
||||||
#include "absl/base/attributes.h"
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
#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_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "absl/strings/str_join.h"
|
||||||
#include "absl/strings/str_replace.h"
|
#include "absl/strings/str_replace.h"
|
||||||
#include "absl/strings/str_split.h"
|
#include "absl/strings/str_split.h"
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
|
@ -57,10 +59,21 @@ namespace sandbox2::util {
|
||||||
namespace file = ::sapi::file;
|
namespace file = ::sapi::file;
|
||||||
namespace file_util = ::sapi::file_util;
|
namespace file_util = ::sapi::file_util;
|
||||||
|
|
||||||
void CharPtrArrToVecString(char* const* arr, std::vector<std::string>* vec) {
|
namespace {
|
||||||
for (int i = 0; arr[i]; ++i) {
|
|
||||||
vec->push_back(arr[i]);
|
std::string ConcatenateAll(char* const* arr) {
|
||||||
|
std::string result;
|
||||||
|
for (; *arr != nullptr; ++arr) {
|
||||||
|
size_t len = strlen(*arr);
|
||||||
|
result.append(*arr, len + 1);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void CharPtrArrToVecString(char* const* arr, std::vector<std::string>* vec) {
|
||||||
|
*vec = CharPtrArray(arr).ToStringVector();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char** VecStringToCharPtrArr(const std::vector<std::string>& vec) {
|
const char** VecStringToCharPtrArr(const std::vector<std::string>& vec) {
|
||||||
|
@ -73,6 +86,39 @@ const char** VecStringToCharPtrArr(const std::vector<std::string>& vec) {
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CharPtrArray::CharPtrArray(char* const* arr) : content_(ConcatenateAll(arr)) {
|
||||||
|
for (auto it = content_.begin(); it != content_.end();
|
||||||
|
it += strlen(&*it) + 1) {
|
||||||
|
array_.push_back(&*it);
|
||||||
|
}
|
||||||
|
array_.push_back(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
CharPtrArray::CharPtrArray(const std::vector<std::string>& vec)
|
||||||
|
: content_(absl::StrJoin(vec, absl::string_view("\0", 1))) {
|
||||||
|
size_t len = 0;
|
||||||
|
array_.reserve(vec.size() + 1);
|
||||||
|
for (const std::string& str : vec) {
|
||||||
|
array_.push_back(&content_[len]);
|
||||||
|
len += str.size() + 1;
|
||||||
|
}
|
||||||
|
array_.push_back(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
CharPtrArray CharPtrArray::FromStringVector(
|
||||||
|
const std::vector<std::string>& vec) {
|
||||||
|
return CharPtrArray(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> CharPtrArray::ToStringVector() const {
|
||||||
|
std::vector<std::string> result;
|
||||||
|
result.reserve(array_.size() - 1);
|
||||||
|
for (size_t i = 0; i < array_.size() - 1; ++i) {
|
||||||
|
result.push_back(array_[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetProgName(pid_t pid) {
|
std::string GetProgName(pid_t pid) {
|
||||||
std::string fname = file::JoinPath("/proc", absl::StrCat(pid), "exe");
|
std::string fname = file::JoinPath("/proc", absl::StrCat(pid), "exe");
|
||||||
// Use ReadLink instead of RealPath, as for fd-based executables (e.g. created
|
// Use ReadLink instead of RealPath, as for fd-based executables (e.g. created
|
||||||
|
@ -248,19 +294,13 @@ absl::StatusOr<int> Communicate(const std::vector<std::string>& argv,
|
||||||
posix_spawn_file_actions_adddup2(&action, cout_pipe[1], 2);
|
posix_spawn_file_actions_adddup2(&action, cout_pipe[1], 2);
|
||||||
posix_spawn_file_actions_addclose(&action, cout_pipe[1]);
|
posix_spawn_file_actions_addclose(&action, cout_pipe[1]);
|
||||||
|
|
||||||
char** args = const_cast<char**>(util::VecStringToCharPtrArr(argv));
|
CharPtrArray args = CharPtrArray::FromStringVector(argv);
|
||||||
char** envp = const_cast<char**>(util::VecStringToCharPtrArr(envv));
|
CharPtrArray envp = CharPtrArray::FromStringVector(envv);
|
||||||
struct ArgumentCleanup {
|
|
||||||
~ArgumentCleanup() {
|
|
||||||
delete[] args_;
|
|
||||||
delete[] envp_;
|
|
||||||
}
|
|
||||||
char** args_;
|
|
||||||
char** envp_;
|
|
||||||
} args_cleanup{args, envp};
|
|
||||||
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
if (posix_spawnp(&pid, args[0], &action, nullptr, args, envp) != 0) {
|
if (posix_spawnp(&pid, args.array()[0], &action, nullptr,
|
||||||
|
const_cast<char**>(args.data()),
|
||||||
|
const_cast<char**>(envp.data())) != 0) {
|
||||||
return absl::UnknownError(sapi::OsErrorMessage(errno, "posix_spawnp()"));
|
return absl::UnknownError(sapi::OsErrorMessage(errno, "posix_spawnp()"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/base/macros.h"
|
#include "absl/base/macros.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
|
|
||||||
|
@ -31,13 +32,35 @@ namespace sandbox2::util {
|
||||||
|
|
||||||
// Converts an array of char* (terminated by a nullptr, like argv, or environ
|
// Converts an array of char* (terminated by a nullptr, like argv, or environ
|
||||||
// arrays), to an std::vector<std::string>.
|
// arrays), to an std::vector<std::string>.
|
||||||
|
ABSL_DEPRECATED("Use CharPtrArray(arr).ToStringVector() instead")
|
||||||
void CharPtrArrToVecString(char* const* arr, std::vector<std::string>* vec);
|
void CharPtrArrToVecString(char* const* arr, std::vector<std::string>* vec);
|
||||||
|
|
||||||
// Converts a vector of strings to a newly allocated array. The array is limited
|
// Converts a vector of strings to a newly allocated array. The array is limited
|
||||||
// by the terminating nullptr entry (like environ or argv). It must be freed by
|
// by the terminating nullptr entry (like environ or argv). It must be freed by
|
||||||
// the caller.
|
// the caller.
|
||||||
|
ABSL_DEPRECATED("Use CharPtrArray class instead")
|
||||||
const char** VecStringToCharPtrArr(const std::vector<std::string>& vec);
|
const char** VecStringToCharPtrArr(const std::vector<std::string>& vec);
|
||||||
|
|
||||||
|
// An char ptr array limited by the terminating nullptr entry (like environ
|
||||||
|
// or argv).
|
||||||
|
class CharPtrArray {
|
||||||
|
public:
|
||||||
|
CharPtrArray(char* const* array);
|
||||||
|
static CharPtrArray FromStringVector(const std::vector<std::string>& vec);
|
||||||
|
|
||||||
|
const std::vector<const char*>& array() const { return array_; }
|
||||||
|
|
||||||
|
const char* const* data() const { return array_.data(); }
|
||||||
|
|
||||||
|
std::vector<std::string> ToStringVector() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CharPtrArray(const std::vector<std::string>& vec);
|
||||||
|
|
||||||
|
const std::string content_;
|
||||||
|
std::vector<const char*> array_;
|
||||||
|
};
|
||||||
|
|
||||||
// Returns the program name (via /proc/self/comm) for a given PID.
|
// Returns the program name (via /proc/self/comm) for a given PID.
|
||||||
std::string GetProgName(pid_t pid);
|
std::string GetProgName(pid_t pid);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user