mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Run more tests with coverage and sanitizers
Running with a permissive test policy should not interfere with sanitizers or coverage. Most tests should run with such a permissive policy. The exception are tests which actually tests policy enforcement. PiperOrigin-RevId: 513548936 Change-Id: I9a4c2cc8074997cff08cc22d15f4736219ce4d63
This commit is contained in:
parent
a613dda7f2
commit
cd945565f5
|
@ -224,6 +224,9 @@ cc_library(
|
||||||
copts = sapi_platform_copts(),
|
copts = sapi_platform_copts(),
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
":config",
|
||||||
|
"//sandboxed_api/sandbox2:policybuilder",
|
||||||
|
"//sandboxed_api/sandbox2:testonly_allow_all_syscalls",
|
||||||
"//sandboxed_api/util:file_base",
|
"//sandboxed_api/util:file_base",
|
||||||
"@com_google_absl//absl/strings",
|
"@com_google_absl//absl/strings",
|
||||||
],
|
],
|
||||||
|
|
|
@ -198,10 +198,13 @@ if(BUILD_TESTING AND SAPI_BUILD_TESTING AND NOT CMAKE_CROSSCOMPILING)
|
||||||
testing.h
|
testing.h
|
||||||
)
|
)
|
||||||
add_library(sapi::testing ALIAS sapi_testing)
|
add_library(sapi::testing ALIAS sapi_testing)
|
||||||
target_link_libraries(sapi_testing PRIVATE
|
target_link_libraries(sapi_testing
|
||||||
absl::strings
|
PRIVATE absl::strings
|
||||||
sapi::file_base
|
sapi::file_base
|
||||||
sapi::base
|
sapi::base
|
||||||
|
PUBLIC sapi::config
|
||||||
|
sandbox2::allow_all_syscalls
|
||||||
|
sandbox2::policybuilder
|
||||||
)
|
)
|
||||||
|
|
||||||
# sandboxed_api:sapi_test
|
# sandboxed_api:sapi_test
|
||||||
|
|
|
@ -911,7 +911,6 @@ cc_test(
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
":sandbox2",
|
":sandbox2",
|
||||||
":testonly_allow_all_syscalls",
|
|
||||||
"//sandboxed_api:config",
|
"//sandboxed_api:config",
|
||||||
"//sandboxed_api:testing",
|
"//sandboxed_api:testing",
|
||||||
"//sandboxed_api/util:status_matchers",
|
"//sandboxed_api/util:status_matchers",
|
||||||
|
|
|
@ -998,7 +998,6 @@ if(BUILD_TESTING AND SAPI_BUILD_TESTING)
|
||||||
)
|
)
|
||||||
target_link_libraries(sandbox2_sandbox2_test PRIVATE
|
target_link_libraries(sandbox2_sandbox2_test PRIVATE
|
||||||
absl::strings
|
absl::strings
|
||||||
sandbox2::allow_all_syscalls
|
|
||||||
sapi::config
|
sapi::config
|
||||||
sandbox2::sandbox2
|
sandbox2::sandbox2
|
||||||
sapi::testing
|
sapi::testing
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "sandboxed_api/config.h"
|
#include "sandboxed_api/config.h"
|
||||||
#include "sandboxed_api/sandbox2/allow_all_syscalls.h"
|
|
||||||
#include "sandboxed_api/sandbox2/executor.h"
|
#include "sandboxed_api/sandbox2/executor.h"
|
||||||
#include "sandboxed_api/sandbox2/policy.h"
|
#include "sandboxed_api/sandbox2/policy.h"
|
||||||
#include "sandboxed_api/sandbox2/policybuilder.h"
|
#include "sandboxed_api/sandbox2/policybuilder.h"
|
||||||
|
@ -38,19 +37,7 @@
|
||||||
namespace sandbox2 {
|
namespace sandbox2 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
PolicyBuilder CreateDefaultPolicyBuilder(absl::string_view path) {
|
using ::sapi::CreateDefaultPermissiveTestPolicy;
|
||||||
PolicyBuilder builder;
|
|
||||||
// Don't restrict the syscalls at all.
|
|
||||||
builder.DefaultAction(AllowAllSyscalls());
|
|
||||||
if constexpr (sapi::sanitizers::IsAny()) {
|
|
||||||
builder.AddLibrariesForBinary(path);
|
|
||||||
}
|
|
||||||
if constexpr (sapi::sanitizers::IsAny()) {
|
|
||||||
builder.AddDirectory("/proc");
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
using ::sapi::GetTestSourcePath;
|
using ::sapi::GetTestSourcePath;
|
||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
using ::testing::IsEmpty;
|
using ::testing::IsEmpty;
|
||||||
|
@ -60,14 +47,13 @@ using ::testing::Lt;
|
||||||
// Test that aborting inside a sandbox with all userspace core dumping
|
// Test that aborting inside a sandbox with all userspace core dumping
|
||||||
// disabled reports the signal.
|
// disabled reports the signal.
|
||||||
TEST(SandboxCoreDumpTest, AbortWithoutCoreDumpReturnsSignaled) {
|
TEST(SandboxCoreDumpTest, AbortWithoutCoreDumpReturnsSignaled) {
|
||||||
SKIP_SANITIZERS_AND_COVERAGE;
|
|
||||||
const std::string path = GetTestSourcePath("sandbox2/testcases/abort");
|
const std::string path = GetTestSourcePath("sandbox2/testcases/abort");
|
||||||
std::vector<std::string> args = {
|
std::vector<std::string> args = {
|
||||||
path,
|
path,
|
||||||
};
|
};
|
||||||
auto executor = std::make_unique<Executor>(path, args);
|
auto executor = std::make_unique<Executor>(path, args);
|
||||||
|
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(auto policy, CreateDefaultPolicyBuilder(path)
|
SAPI_ASSERT_OK_AND_ASSIGN(auto policy, CreateDefaultPermissiveTestPolicy(path)
|
||||||
.TryBuild());
|
.TryBuild());
|
||||||
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
||||||
auto result = sandbox.Run();
|
auto result = sandbox.Run();
|
||||||
|
@ -79,7 +65,6 @@ TEST(SandboxCoreDumpTest, AbortWithoutCoreDumpReturnsSignaled) {
|
||||||
// Test that with TSYNC we are able to sandbox when multithreaded and with no
|
// Test that with TSYNC we are able to sandbox when multithreaded and with no
|
||||||
// memory checks. If TSYNC is not supported, then no.
|
// memory checks. If TSYNC is not supported, then no.
|
||||||
TEST(TsyncTest, TsyncNoMemoryChecks) {
|
TEST(TsyncTest, TsyncNoMemoryChecks) {
|
||||||
SKIP_SANITIZERS_AND_COVERAGE;
|
|
||||||
const std::string path = GetTestSourcePath("sandbox2/testcases/tsync");
|
const std::string path = GetTestSourcePath("sandbox2/testcases/tsync");
|
||||||
|
|
||||||
auto executor =
|
auto executor =
|
||||||
|
@ -87,7 +72,7 @@ TEST(TsyncTest, TsyncNoMemoryChecks) {
|
||||||
executor->set_enable_sandbox_before_exec(false);
|
executor->set_enable_sandbox_before_exec(false);
|
||||||
|
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
||||||
CreateDefaultPolicyBuilder(path).TryBuild());
|
CreateDefaultPermissiveTestPolicy(path).TryBuild());
|
||||||
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
||||||
auto result = sandbox.Run();
|
auto result = sandbox.Run();
|
||||||
|
|
||||||
|
@ -99,8 +84,6 @@ TEST(TsyncTest, TsyncNoMemoryChecks) {
|
||||||
// Tests whether Executor(fd, std::vector<std::string>{path}, envp) constructor
|
// Tests whether Executor(fd, std::vector<std::string>{path}, envp) constructor
|
||||||
// works as expected.
|
// works as expected.
|
||||||
TEST(ExecutorTest, ExecutorFdConstructor) {
|
TEST(ExecutorTest, ExecutorFdConstructor) {
|
||||||
SKIP_SANITIZERS_AND_COVERAGE;
|
|
||||||
|
|
||||||
const std::string path = GetTestSourcePath("sandbox2/testcases/minimal");
|
const std::string path = GetTestSourcePath("sandbox2/testcases/minimal");
|
||||||
int fd = open(path.c_str(), O_RDONLY);
|
int fd = open(path.c_str(), O_RDONLY);
|
||||||
ASSERT_NE(fd, -1);
|
ASSERT_NE(fd, -1);
|
||||||
|
@ -110,7 +93,7 @@ TEST(ExecutorTest, ExecutorFdConstructor) {
|
||||||
auto executor = std::make_unique<Executor>(fd, args, envs);
|
auto executor = std::make_unique<Executor>(fd, args, envs);
|
||||||
|
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
||||||
CreateDefaultPolicyBuilder(path).TryBuild());
|
CreateDefaultPermissiveTestPolicy(path).TryBuild());
|
||||||
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
||||||
auto result = sandbox.Run();
|
auto result = sandbox.Run();
|
||||||
|
|
||||||
|
@ -127,7 +110,7 @@ TEST(RunAsyncTest, SandboxeeExternalKill) {
|
||||||
auto executor = std::make_unique<Executor>(path, args, envs);
|
auto executor = std::make_unique<Executor>(path, args, envs);
|
||||||
|
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
||||||
CreateDefaultPolicyBuilder(path).TryBuild());
|
CreateDefaultPermissiveTestPolicy(path).TryBuild());
|
||||||
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
||||||
ASSERT_TRUE(sandbox.RunAsync());
|
ASSERT_TRUE(sandbox.RunAsync());
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
@ -145,7 +128,7 @@ TEST(RunAsyncTest, SandboxeeTimeoutDisabledStacktraces) {
|
||||||
std::vector<std::string> envs;
|
std::vector<std::string> envs;
|
||||||
auto executor = std::make_unique<Executor>(path, args, envs);
|
auto executor = std::make_unique<Executor>(path, args, envs);
|
||||||
|
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(auto policy, CreateDefaultPolicyBuilder(path)
|
SAPI_ASSERT_OK_AND_ASSIGN(auto policy, CreateDefaultPermissiveTestPolicy(path)
|
||||||
.CollectStacktracesOnTimeout(false)
|
.CollectStacktracesOnTimeout(false)
|
||||||
.TryBuild());
|
.TryBuild());
|
||||||
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
||||||
|
@ -181,8 +164,8 @@ TEST(RunAsyncTest, SandboxeeNotKilledWhenStartingThreadFinishes) {
|
||||||
std::vector<std::string> args = {path};
|
std::vector<std::string> args = {path};
|
||||||
auto executor = std::make_unique<Executor>(path, args);
|
auto executor = std::make_unique<Executor>(path, args);
|
||||||
|
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(auto policy, CreateDefaultPolicyBuilder(path)
|
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
||||||
.TryBuild());
|
CreateDefaultPermissiveTestPolicy(path).TryBuild());
|
||||||
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
||||||
std::thread sandbox_start_thread([&sandbox]() { sandbox.RunAsync(); });
|
std::thread sandbox_start_thread([&sandbox]() { sandbox.RunAsync(); });
|
||||||
sandbox_start_thread.join();
|
sandbox_start_thread.join();
|
||||||
|
@ -199,7 +182,7 @@ TEST(StarvationTest, MonitorIsNotStarvedByTheSandboxee) {
|
||||||
executor->limits()->set_walltime_limit(absl::Seconds(5));
|
executor->limits()->set_walltime_limit(absl::Seconds(5));
|
||||||
|
|
||||||
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
SAPI_ASSERT_OK_AND_ASSIGN(auto policy,
|
||||||
CreateDefaultPolicyBuilder(path).TryBuild());
|
CreateDefaultPermissiveTestPolicy(path).TryBuild());
|
||||||
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
Sandbox2 sandbox(std::move(executor), std::move(policy));
|
||||||
|
|
||||||
auto start = absl::Now();
|
auto start = absl::Now();
|
||||||
|
|
|
@ -14,11 +14,39 @@
|
||||||
|
|
||||||
#include "sandboxed_api/testing.h"
|
#include "sandboxed_api/testing.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
|
#include "sandboxed_api/config.h"
|
||||||
|
#include "sandboxed_api/sandbox2/allow_all_syscalls.h"
|
||||||
#include "sandboxed_api/util/path.h"
|
#include "sandboxed_api/util/path.h"
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
|
|
||||||
|
bool IsCoverageRun() {
|
||||||
|
return getenv("COVERAGE") != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
sandbox2::PolicyBuilder CreateDefaultPermissiveTestPolicy(
|
||||||
|
absl::string_view bin_path) {
|
||||||
|
sandbox2::PolicyBuilder builder;
|
||||||
|
// Don't restrict the syscalls at all.
|
||||||
|
builder.DefaultAction(sandbox2::AllowAllSyscalls());
|
||||||
|
if (sapi::host_os::IsAndroid()) {
|
||||||
|
builder.DisableNamespaces();
|
||||||
|
}
|
||||||
|
if (IsCoverageRun()) {
|
||||||
|
builder.AddDirectory(getenv("COVERAGE_DIR"), /*is_ro=*/false);
|
||||||
|
}
|
||||||
|
if constexpr (sapi::sanitizers::IsAny()) {
|
||||||
|
builder.AddLibrariesForBinary(bin_path);
|
||||||
|
}
|
||||||
|
if constexpr (sapi::sanitizers::IsAny()) {
|
||||||
|
builder.AddDirectory("/proc");
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetTestTempPath(absl::string_view name) {
|
std::string GetTestTempPath(absl::string_view name) {
|
||||||
// When using Bazel, the environment variable TEST_TMPDIR is guaranteed to be
|
// When using Bazel, the environment variable TEST_TMPDIR is guaranteed to be
|
||||||
// set.
|
// set.
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
#ifndef SANDBOXED_API_TESTING_H_
|
#ifndef SANDBOXED_API_TESTING_H_
|
||||||
#define SANDBOXED_API_TESTING_H_
|
#define SANDBOXED_API_TESTING_H_
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
|
#include "sandboxed_api/config.h"
|
||||||
|
#include "sandboxed_api/sandbox2/policybuilder.h"
|
||||||
|
|
||||||
// The macro SKIP_ANDROID can be used in tests to skip running a
|
// The macro SKIP_ANDROID can be used in tests to skip running a
|
||||||
// given test (by emitting 'retrun') when running on Android. Example:
|
// given test (by emitting 'retrun') when running on Android. Example:
|
||||||
|
@ -30,11 +31,12 @@
|
||||||
//
|
//
|
||||||
// The reason for this is because certain unit tests require the use of user
|
// The reason for this is because certain unit tests require the use of user
|
||||||
// namespaces which are not present on Android.
|
// namespaces which are not present on Android.
|
||||||
#if defined(__ANDROID__)
|
#define SKIP_ANDROID \
|
||||||
#define SKIP_ANDROID return
|
do { \
|
||||||
#else
|
if constexpr (sapi::host_os::IsAndroid()) { \
|
||||||
#define SKIP_ANDROID
|
return; \
|
||||||
#endif
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
// The macro SKIP_SANITIZERS_AND_COVERAGE can be used in tests to skip running
|
// The macro SKIP_SANITIZERS_AND_COVERAGE can be used in tests to skip running
|
||||||
// a given test (by emitting 'return') when running under one of the sanitizers
|
// a given test (by emitting 'return') when running under one of the sanitizers
|
||||||
|
@ -57,21 +59,21 @@
|
||||||
// The downside of this approach is that no coverage will be collected.
|
// The downside of this approach is that no coverage will be collected.
|
||||||
// To still have coverage, pre-compile sandboxees and add them as test data,
|
// To still have coverage, pre-compile sandboxees and add them as test data,
|
||||||
// then there will be no need to skip tests.
|
// then there will be no need to skip tests.
|
||||||
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
|
|
||||||
defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
|
|
||||||
#define SKIP_SANITIZERS_AND_COVERAGE return
|
|
||||||
#else
|
|
||||||
#define SAPI_BUILDDATA_COVERAGE_ENABLED false
|
|
||||||
#define SKIP_SANITIZERS_AND_COVERAGE \
|
#define SKIP_SANITIZERS_AND_COVERAGE \
|
||||||
do { \
|
do { \
|
||||||
if (SAPI_BUILDDATA_COVERAGE_ENABLED || getenv("COVERAGE") != nullptr) { \
|
if (sapi::sanitizers::IsAny() || sapi::IsCoverageRun()) { \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace sapi {
|
namespace sapi {
|
||||||
|
|
||||||
|
// Returns whether the executable running under code coverage.
|
||||||
|
bool IsCoverageRun();
|
||||||
|
|
||||||
|
sandbox2::PolicyBuilder CreateDefaultPermissiveTestPolicy(
|
||||||
|
absl::string_view bin_path);
|
||||||
|
|
||||||
// Returns a writable path usable in tests. If the name argument is specified,
|
// Returns a writable path usable in tests. If the name argument is specified,
|
||||||
// returns a name under that path. This can then be used for creating temporary
|
// returns a name under that path. This can then be used for creating temporary
|
||||||
// test files and/or directories.
|
// test files and/or directories.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user