2020-01-17 21:05:03 +08:00
|
|
|
// Copyright 2019 Google LLC
|
2019-03-19 00:21:48 +08:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
2022-01-28 17:38:27 +08:00
|
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
2019-03-19 00:21:48 +08:00
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2023-03-02 17:25:02 +08:00
|
|
|
// A binary that exits via different modes: crashes, causes violation, exits
|
|
|
|
// normally or times out, to test the stack tracing symbolizer.
|
2019-03-19 00:21:48 +08:00
|
|
|
|
2023-08-24 21:23:03 +08:00
|
|
|
#include <syscall.h>
|
2019-03-19 00:21:48 +08:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2023-03-02 17:25:02 +08:00
|
|
|
#include <cstdlib>
|
2019-03-19 00:21:48 +08:00
|
|
|
|
|
|
|
#include "absl/base/attributes.h"
|
|
|
|
#include "absl/strings/numbers.h"
|
2023-03-02 21:09:05 +08:00
|
|
|
#include "sandboxed_api/sandbox2/testcases/symbolize_lib.h"
|
2019-03-19 00:21:48 +08:00
|
|
|
#include "sandboxed_api/util/raw_logging.h"
|
2023-03-02 17:25:02 +08:00
|
|
|
|
|
|
|
// Sometimes we don't have debug info to properly unwind through libc (a frame
|
|
|
|
// is skipped).
|
|
|
|
// Workaround by putting another frame on the call stack.
|
|
|
|
template <typename F>
|
|
|
|
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL void IndirectLibcCall(
|
|
|
|
F func) {
|
|
|
|
func();
|
|
|
|
}
|
2019-03-19 00:21:48 +08:00
|
|
|
|
|
|
|
ABSL_ATTRIBUTE_NOINLINE
|
2023-03-02 17:25:02 +08:00
|
|
|
void CrashMe(char x = 0) {
|
2021-08-12 23:03:25 +08:00
|
|
|
volatile char* null = nullptr;
|
2023-03-02 17:25:02 +08:00
|
|
|
*null = x;
|
2019-03-19 00:21:48 +08:00
|
|
|
}
|
|
|
|
|
2023-03-02 17:25:02 +08:00
|
|
|
ABSL_ATTRIBUTE_NOINLINE
|
|
|
|
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
|
|
|
void ViolatePolicy(int x = 0) {
|
|
|
|
IndirectLibcCall([x]() { syscall(__NR_ptrace, x); });
|
|
|
|
}
|
2019-03-19 00:21:48 +08:00
|
|
|
|
2023-03-02 17:25:02 +08:00
|
|
|
ABSL_ATTRIBUTE_NOINLINE
|
|
|
|
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
|
|
|
void ExitNormally(int x = 0) {
|
|
|
|
IndirectLibcCall([x]() {
|
|
|
|
// _exit is marked noreturn, which makes stack traces a bit trickier -
|
|
|
|
// work around by using a volatile read
|
|
|
|
if (volatile int y = 1) {
|
|
|
|
_exit(x);
|
2019-03-19 00:21:48 +08:00
|
|
|
}
|
2023-03-02 17:25:02 +08:00
|
|
|
});
|
|
|
|
}
|
2019-03-19 00:21:48 +08:00
|
|
|
|
2023-03-02 17:25:02 +08:00
|
|
|
ABSL_ATTRIBUTE_NOINLINE
|
|
|
|
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
|
|
|
void SleepForXSeconds(int x = 0) {
|
|
|
|
IndirectLibcCall([x]() { sleep(x); });
|
2019-03-19 00:21:48 +08:00
|
|
|
}
|
|
|
|
|
2023-03-02 21:09:05 +08:00
|
|
|
ABSL_ATTRIBUTE_NOINLINE
|
|
|
|
ABSL_ATTRIBUTE_NO_TAIL_CALL
|
|
|
|
void RunTest(int testno) {
|
2019-03-19 00:21:48 +08:00
|
|
|
switch (testno) {
|
|
|
|
case 1:
|
|
|
|
CrashMe();
|
|
|
|
break;
|
|
|
|
case 2:
|
2023-03-02 17:25:02 +08:00
|
|
|
ViolatePolicy();
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
ExitNormally();
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
SleepForXSeconds(10);
|
2019-03-19 00:21:48 +08:00
|
|
|
break;
|
|
|
|
default:
|
2023-03-02 17:25:02 +08:00
|
|
|
SAPI_RAW_LOG(FATAL, "Unknown test case: %d", testno);
|
2019-03-19 00:21:48 +08:00
|
|
|
}
|
2023-03-02 21:09:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2019-03-19 00:21:48 +08:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|