mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Test stack unwinding more thoroughly
Check unwinding recursive calls. Verify we can unwind in absence of unwind tables. PiperOrigin-RevId: 513506498 Change-Id: Ib87240b7481dae3a4513c944e17a7924a54926e9
This commit is contained in:
parent
0033c4563f
commit
a613dda7f2
|
@ -54,9 +54,11 @@ using ::testing::IsEmpty;
|
|||
using ::testing::StartsWith;
|
||||
|
||||
struct TestCase {
|
||||
std::string arg = "1";
|
||||
std::string testname = "CrashMe";
|
||||
int testno = 1;
|
||||
int testmode = 1;
|
||||
int final_status = Result::SIGNALED;
|
||||
std::string function_name = "CrashMe";
|
||||
std::string function_name = testname;
|
||||
std::string full_function_description = "CrashMe(char)";
|
||||
std::function<void(PolicyBuilder*)> modify_policy;
|
||||
absl::Duration wall_time_limit = absl::ZeroDuration();
|
||||
|
@ -67,7 +69,8 @@ class StackTraceTest : public ::testing::TestWithParam<TestCase> {};
|
|||
// Test that symbolization of stack traces works.
|
||||
void SymbolizationWorksCommon(TestCase param) {
|
||||
const std::string path = GetTestSourcePath("sandbox2/testcases/symbolize");
|
||||
std::vector<std::string> args = {path, param.arg};
|
||||
std::vector<std::string> args = {path, absl::StrCat(param.testno),
|
||||
absl::StrCat(param.testmode)};
|
||||
|
||||
auto policybuilder = PolicyBuilder()
|
||||
// Don't restrict the syscalls at all.
|
||||
|
@ -87,6 +90,20 @@ void SymbolizationWorksCommon(TestCase param) {
|
|||
// Check that demangling works as well.
|
||||
EXPECT_THAT(result.stack_trace(),
|
||||
Contains(StartsWith(param.full_function_description)));
|
||||
EXPECT_THAT(result.stack_trace(), Contains(StartsWith("RunTest")));
|
||||
EXPECT_THAT(result.stack_trace(), Contains(StartsWith("main")));
|
||||
if (param.testmode == 2) {
|
||||
EXPECT_THAT(result.stack_trace(),
|
||||
Contains(StartsWith("RecurseA")).Times(5));
|
||||
EXPECT_THAT(result.stack_trace(),
|
||||
Contains(StartsWith("RecurseB")).Times(5));
|
||||
} else if (param.testmode == 3) {
|
||||
EXPECT_THAT(result.stack_trace(), Contains(StartsWith("LibRecurse")));
|
||||
EXPECT_THAT(result.stack_trace(),
|
||||
Contains(StartsWith("LibRecurseA")).Times(5));
|
||||
EXPECT_THAT(result.stack_trace(),
|
||||
Contains(StartsWith("LibRecurseB")).Times(5));
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolizationWorksWithModifiedPolicy(
|
||||
|
@ -206,21 +223,21 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
Instantiation, StackTraceTest,
|
||||
::testing::Values(
|
||||
TestCase{
|
||||
.arg = "1",
|
||||
.testname = "CrashMe",
|
||||
.testno = 1,
|
||||
.final_status = Result::SIGNALED,
|
||||
.function_name = "CrashMe",
|
||||
.full_function_description = "CrashMe(char)",
|
||||
},
|
||||
TestCase{
|
||||
.arg = "2",
|
||||
.testname = "ViolatePolicy",
|
||||
.testno = 2,
|
||||
.final_status = Result::VIOLATION,
|
||||
.function_name = "ViolatePolicy",
|
||||
.full_function_description = "ViolatePolicy(int)",
|
||||
},
|
||||
TestCase{
|
||||
.arg = "3",
|
||||
.testname = "ExitNormally",
|
||||
.testno = 3,
|
||||
.final_status = Result::OK,
|
||||
.function_name = "ExitNormally",
|
||||
.full_function_description = "ExitNormally(int)",
|
||||
.modify_policy =
|
||||
[](PolicyBuilder* builder) {
|
||||
|
@ -228,14 +245,30 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
},
|
||||
},
|
||||
TestCase{
|
||||
.arg = "4",
|
||||
.testname = "SleepForXSeconds",
|
||||
.testno = 4,
|
||||
.final_status = Result::TIMEOUT,
|
||||
.function_name = "SleepForXSeconds",
|
||||
.full_function_description = "SleepForXSeconds(int)",
|
||||
.wall_time_limit = absl::Seconds(1),
|
||||
},
|
||||
TestCase{
|
||||
.testname = "ViolatePolicyRecursive",
|
||||
.testno = 2,
|
||||
.testmode = 2,
|
||||
.final_status = Result::VIOLATION,
|
||||
.function_name = "ViolatePolicy",
|
||||
.full_function_description = "ViolatePolicy(int)",
|
||||
},
|
||||
TestCase{
|
||||
.testname = "ViolatePolicyRecursiveLib",
|
||||
.testno = 2,
|
||||
.testmode = 3,
|
||||
.final_status = Result::VIOLATION,
|
||||
.function_name = "ViolatePolicy",
|
||||
.full_function_description = "ViolatePolicy(int)",
|
||||
}),
|
||||
[](const ::testing::TestParamInfo<TestCase>& info) {
|
||||
return info.param.function_name;
|
||||
return info.param.testname;
|
||||
});
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -163,6 +163,22 @@ cc_binary(
|
|||
features = ["fully_static_link"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "symbolize_lib",
|
||||
testonly = True,
|
||||
srcs = ["symbolize_lib.cc"],
|
||||
hdrs = ["symbolize_lib.h"],
|
||||
copts = sapi_platform_copts([
|
||||
"-fno-omit-frame-pointer",
|
||||
"-fno-unwind-tables",
|
||||
"-fno-asynchronous-unwind-tables",
|
||||
]),
|
||||
features = ["fully_static_link"],
|
||||
deps = [
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "symbolize",
|
||||
testonly = True,
|
||||
|
@ -170,6 +186,7 @@ cc_binary(
|
|||
copts = sapi_platform_copts(),
|
||||
features = ["fully_static_link"],
|
||||
deps = [
|
||||
":symbolize_lib",
|
||||
"//sandboxed_api/util:raw_logging",
|
||||
"@com_google_absl//absl/base:core_headers",
|
||||
"@com_google_absl//absl/strings",
|
||||
|
|
|
@ -213,6 +213,24 @@ target_link_libraries(sandbox2_testcase_symbolize PRIVATE
|
|||
absl::strings
|
||||
sapi::base
|
||||
sapi::raw_logging
|
||||
sandbox2::testcase_symbolize_lib
|
||||
)
|
||||
|
||||
# sandboxed_api/sandbox2/testcases:symbolize_lib
|
||||
add_library(sandbox2_testcase_symbolize_lib
|
||||
symbolize_lib.cc
|
||||
symbolize_lib.h
|
||||
)
|
||||
add_library(sandbox2::testcase_symbolize_lib ALIAS sandbox2_testcase_symbolize_lib)
|
||||
target_link_libraries(sandbox2_testcase_symbolize_lib PRIVATE
|
||||
-static
|
||||
absl::core_headers
|
||||
sapi::base
|
||||
)
|
||||
target_compile_options(sandbox2_testcase_symbolize_lib PRIVATE
|
||||
-fno-omit-frame-pointer
|
||||
-fno-unwind-tables
|
||||
-fno-asynchronous-unwind-tables
|
||||
)
|
||||
|
||||
# sandboxed_api/sandbox2/testcases:starve
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/strings/numbers.h"
|
||||
#include "sandboxed_api/sandbox2/testcases/symbolize_lib.h"
|
||||
#include "sandboxed_api/util/raw_logging.h"
|
||||
|
||||
// Sometimes we don't have debug info to properly unwind through libc (a frame
|
||||
|
@ -63,10 +64,9 @@ void SleepForXSeconds(int x = 0) {
|
|||
IndirectLibcCall([x]() { sleep(x); });
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
SAPI_RAW_CHECK(argc >= 2, "Not enough arguments");
|
||||
int testno;
|
||||
SAPI_RAW_CHECK(absl::SimpleAtoi(argv[1], &testno), "testno not a number");
|
||||
ABSL_ATTRIBUTE_NOINLINE
|
||||
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
void RunTest(int testno) {
|
||||
switch (testno) {
|
||||
case 1:
|
||||
CrashMe();
|
||||
|
@ -83,5 +83,46 @@ int main(int argc, char* argv[]) {
|
|||
default:
|
||||
SAPI_RAW_LOG(FATAL, "Unknown test case: %d", testno);
|
||||
}
|
||||
}
|
||||
|
||||
ABSL_ATTRIBUTE_NOINLINE
|
||||
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
void RecurseA(int testno, int n);
|
||||
|
||||
ABSL_ATTRIBUTE_NOINLINE
|
||||
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
void RecurseB(int testno, int n) {
|
||||
if (n > 1) {
|
||||
return RecurseA(testno, n - 1);
|
||||
}
|
||||
return RunTest(testno);
|
||||
}
|
||||
|
||||
void RecurseA(int testno, int n) {
|
||||
if (n > 1) {
|
||||
return RecurseB(testno, n - 1);
|
||||
}
|
||||
return RunTest(testno);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
SAPI_RAW_CHECK(argc >= 3, "Not enough arguments");
|
||||
int testno;
|
||||
int testmode;
|
||||
SAPI_RAW_CHECK(absl::SimpleAtoi(argv[1], &testno), "testno not a number");
|
||||
SAPI_RAW_CHECK(absl::SimpleAtoi(argv[2], &testmode), "testmode not a number");
|
||||
switch (testmode) {
|
||||
case 1:
|
||||
RunTest(testno);
|
||||
break;
|
||||
case 2:
|
||||
RecurseA(testno, 10);
|
||||
break;
|
||||
case 3:
|
||||
LibRecurse(&RunTest, testno, 10);
|
||||
break;
|
||||
default:
|
||||
SAPI_RAW_LOG(FATAL, "Unknown test mode: %d", testmode);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
25
sandboxed_api/sandbox2/testcases/symbolize_lib.cc
Normal file
25
sandboxed_api/sandbox2/testcases/symbolize_lib.cc
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "sandboxed_api/sandbox2/testcases/symbolize_lib.h"
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
|
||||
ABSL_ATTRIBUTE_NOINLINE
|
||||
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
void LibRecurseA(void (*cb)(int), int data, int n);
|
||||
|
||||
ABSL_ATTRIBUTE_NOINLINE
|
||||
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
void LibRecurseB(void (*cb)(int), int data, int n) {
|
||||
if (n > 1) {
|
||||
return LibRecurseA(cb, data, n - 1);
|
||||
}
|
||||
return cb(data);
|
||||
}
|
||||
|
||||
void LibRecurseA(void (*cb)(int), int data, int n) {
|
||||
if (n > 1) {
|
||||
return LibRecurseB(cb, data, n - 1);
|
||||
}
|
||||
return cb(data);
|
||||
}
|
||||
|
||||
void LibRecurse(void (*cb)(int), int data, int n) { LibRecurseA(cb, data, n); }
|
10
sandboxed_api/sandbox2/testcases/symbolize_lib.h
Normal file
10
sandboxed_api/sandbox2/testcases/symbolize_lib.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef SANDBOXED_API_SANDBOX2_TESTCASES_SYMBOLIZE_LIB_H_
|
||||
#define SANDBOXED_API_SANDBOX2_TESTCASES_SYMBOLIZE_LIB_H_
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
|
||||
ABSL_ATTRIBUTE_NOINLINE
|
||||
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
void LibRecurse(void (*cb)(int), int data, int n);
|
||||
|
||||
#endif // SANDBOXED_API_SANDBOX2_TESTCASES_SYMBOLIZE_LIB_H_
|
Loading…
Reference in New Issue
Block a user