Dump coverage prior to execveat

PiperOrigin-RevId: 520002416
Change-Id: Ic792b0b71b8e7b2f00b669db9b6831acd8341c5c
This commit is contained in:
Wiktor Garbacz 2023-03-28 05:50:06 -07:00 committed by Copybara-Service
parent 1755ba08e1
commit a4d602298b
6 changed files with 61 additions and 13 deletions

View File

@ -244,6 +244,7 @@ cc_binary(
":comms",
":forkserver",
":sanitizer",
":util",
"//sandboxed_api/util:raw_logging",
"//sandboxed_api/util:strerror",
"@com_google_absl//absl/log:globals",
@ -266,6 +267,7 @@ cc_library(
":fork_client",
":forkserver_bin_embed",
":forkserver_cc_proto",
":util",
"//sandboxed_api:config",
"//sandboxed_api:embed_file",
"//sandboxed_api/util:fileops",

View File

@ -210,6 +210,7 @@ target_link_libraries(sandbox2_forkserver_bin PRIVATE
sandbox2::comms
sandbox2::forkserver
sandbox2::sanitizer
sandbox2::util
sapi::base
sapi::raw_logging
)
@ -236,6 +237,7 @@ target_link_libraries(sandbox2_global_forkserver
absl::log
sandbox2::client
sandbox2::forkserver_bin_embed
sandbox2::util
sapi::strerror
sapi::base
sapi::config

View File

@ -61,6 +61,10 @@
#include "sandboxed_api/util/raw_logging.h"
#include "sandboxed_api/util/strerror.h"
namespace sandbox2 {
namespace file_util = ::sapi::file_util;
namespace {
using ::sapi::StrError;
@ -244,10 +248,6 @@ bool IsLikelyChrooted() {
} // namespace
namespace sandbox2 {
namespace file_util = ::sapi::file_util;
void ForkServer::PrepareExecveArgs(const ForkRequest& request,
std::vector<std::string>* args,
std::vector<std::string>* envp) {
@ -616,11 +616,8 @@ void ForkServer::ExecuteProcess(int execve_fd, const char* const* argv,
// 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
// argument to magic values.
util::Syscall(
__NR_execveat, static_cast<uintptr_t>(execve_fd),
reinterpret_cast<uintptr_t>(""), reinterpret_cast<uintptr_t>(argv),
reinterpret_cast<uintptr_t>(envp), static_cast<uintptr_t>(AT_EMPTY_PATH),
reinterpret_cast<uintptr_t>(internal::kExecveMagic));
util::Execveat(execve_fd, "", argv, envp, AT_EMPTY_PATH,
internal::kExecveMagic);
int saved_errno = errno;
SAPI_RAW_PLOG(ERROR, "sandbox2::ForkServer: execveat failed");

View File

@ -49,6 +49,7 @@
#include "sandboxed_api/sandbox2/comms.h"
#include "sandboxed_api/sandbox2/fork_client.h"
#include "sandboxed_api/sandbox2/forkserver_bin_embed.h"
#include "sandboxed_api/sandbox2/util.h"
#include "sandboxed_api/util/fileops.h"
#include "sandboxed_api/util/raw_logging.h"
@ -142,11 +143,8 @@ int LaunchForkserver(void* vargs) {
char proc_name[] = "S2-FORK-SERV";
char* const argv[] = {proc_name, nullptr};
char* const envp[] = {nullptr};
syscall(__NR_execveat, args->exec_fd, "", argv, envp, AT_EMPTY_PATH);
util::Execveat(args->exec_fd, "", argv, environ, AT_EMPTY_PATH);
SAPI_RAW_PLOG(FATAL, "Could not launch forkserver binary");
abort();
}
absl::StatusOr<std::unique_ptr<GlobalForkClient>> StartGlobalForkServer() {

View File

@ -31,6 +31,7 @@
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
#include "absl/algorithm/container.h"
#include "absl/base/attributes.h"
@ -68,6 +69,32 @@ std::string ConcatenateAll(char* const* arr) {
return result;
}
#ifdef __ELF__
extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
extern "C" void __gcov_reset() ABSL_ATTRIBUTE_WEAK;
#endif
void DumpCoverageData() {
#ifdef __ELF__
if (&__gcov_dump != nullptr) {
SAPI_RAW_LOG(WARNING, "Flushing coverage data (dump)");
__gcov_dump();
} else if (&__gcov_flush != nullptr) {
SAPI_RAW_LOG(WARNING, "Flushing coverage data (flush)");
__gcov_flush();
}
#endif
}
void ResetCoverageData() {
#ifdef __ELF__
if (&__gcov_reset != nullptr) {
__gcov_reset();
}
#endif
}
} // namespace
void CharPtrArrToVecString(char* const* arr, std::vector<std::string>* vec) {
@ -400,4 +427,22 @@ absl::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr) {
return path;
}
int Execveat(int dirfd, const char* pathname, const char* const argv[],
const char* const envp[], int flags, uintptr_t extra_arg) {
// Flush coverage data prior to exec.
if (extra_arg == 0) {
DumpCoverageData();
}
int res = syscall(__NR_execveat, static_cast<uintptr_t>(dirfd),
reinterpret_cast<uintptr_t>(pathname),
reinterpret_cast<uintptr_t>(argv),
reinterpret_cast<uintptr_t>(envp),
static_cast<uintptr_t>(flags), extra_arg);
// Reset coverage data if exec fails as the counters have been already dumped.
if (extra_arg == 0) {
ResetCoverageData();
}
return res;
}
} // namespace sandbox2::util

View File

@ -106,6 +106,10 @@ std::string GetPtraceEventName(int event);
// process memory
absl::StatusOr<std::string> ReadCPathFromPid(pid_t pid, uintptr_t ptr);
// Wrapper for execveat(2).
int Execveat(int dirfd, const char* pathname, const char* const argv[],
const char* const envp[], int flags, uintptr_t extra_arg = 0);
} // namespace sandbox2::util
#endif // SANDBOXED_API_SANDBOX2_UTIL_H_