mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Fix Regs::SkipSyscallReturnValue for Aarch64
Add a test. PiperOrigin-RevId: 420271649 Change-Id: Ifc857ec5351a0fc70547c98f57c22cf792d5d9f9
This commit is contained in:
parent
d54338db3e
commit
b0bc17e456
|
@ -53,6 +53,22 @@ cc_library(
|
|||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "regs_test",
|
||||
srcs = ["regs_test.cc"],
|
||||
copts = sapi_platform_copts(),
|
||||
tags = ["no_qemu_user_mode"],
|
||||
deps = [
|
||||
":regs",
|
||||
":sanitizer",
|
||||
":util",
|
||||
"//sandboxed_api/sandbox2/util:bpf_helper",
|
||||
"//sandboxed_api/util:status_matchers",
|
||||
"@com_google_glog//:glog",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "syscall",
|
||||
srcs = [
|
||||
|
|
|
@ -35,15 +35,16 @@ add_library(sandbox2_regs ${SAPI_LIB_TYPE}
|
|||
regs.h
|
||||
)
|
||||
add_library(sandbox2::regs ALIAS sandbox2_regs)
|
||||
target_link_libraries(sandbox2_regs PRIVATE
|
||||
absl::core_headers
|
||||
absl::strings
|
||||
sapi::config
|
||||
sapi::strerror
|
||||
sandbox2::syscall
|
||||
sandbox2::violation_proto
|
||||
sapi::base
|
||||
sapi::status
|
||||
target_link_libraries(sandbox2_regs
|
||||
PUBLIC absl::status
|
||||
sapi::config
|
||||
sandbox2::syscall
|
||||
sandbox2::violation_proto
|
||||
PRIVATE absl::core_headers
|
||||
absl::strings
|
||||
sapi::strerror
|
||||
sapi::base
|
||||
sapi::status
|
||||
)
|
||||
|
||||
# sandboxed_api/sandbox2:syscall
|
||||
|
@ -609,6 +610,25 @@ target_link_libraries(sandbox2_violation_proto PRIVATE
|
|||
if(SAPI_ENABLE_TESTS)
|
||||
add_subdirectory(testcases)
|
||||
|
||||
# sandboxed_api/sandbox2:regs_test
|
||||
add_executable(sandbox2_regs_test
|
||||
regs_test.cc
|
||||
)
|
||||
set_target_properties(sandbox2_regs_test PROPERTIES
|
||||
OUTPUT_NAME regs_test
|
||||
)
|
||||
target_link_libraries(sandbox2_regs_test PRIVATE
|
||||
glog::glog
|
||||
sapi::config
|
||||
sapi::status_matchers
|
||||
sandbox2::bpf_helper
|
||||
sandbox2::regs
|
||||
sandbox2::sanitizer
|
||||
sandbox2::util
|
||||
sapi::test_main
|
||||
)
|
||||
gtest_discover_tests_xcompile(sandbox2_regs_test)
|
||||
|
||||
# sandboxed_api/sandbox2:syscall_test
|
||||
add_executable(sandbox2_syscall_test
|
||||
syscall_test.cc
|
||||
|
|
|
@ -118,8 +118,8 @@ absl::Status Regs::SkipSyscallReturnValue(uintptr_t value) {
|
|||
user_regs_.gpr[0] = -1;
|
||||
user_regs_.gpr[3] = value;
|
||||
#elif defined(SAPI_ARM64)
|
||||
user_regs_.regs[0] = -1;
|
||||
syscall_number_ = value;
|
||||
syscall_number_ = -1;
|
||||
user_regs_.regs[0] = value;
|
||||
#elif defined(SAPI_ARM)
|
||||
user_regs_.orig_x0 = -1;
|
||||
user_regs_.regs[7] = value;
|
||||
|
|
98
sandboxed_api/sandbox2/regs_test.cc
Normal file
98
sandboxed_api/sandbox2/regs_test.cc
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "sandboxed_api/sandbox2/regs.h"
|
||||
|
||||
#include <linux/audit.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "sandboxed_api/sandbox2/sanitizer.h"
|
||||
#include "sandboxed_api/sandbox2/util.h"
|
||||
#include "sandboxed_api/sandbox2/util/bpf_helper.h"
|
||||
#include "sandboxed_api/util/status_matchers.h"
|
||||
|
||||
namespace sandbox2 {
|
||||
namespace {
|
||||
|
||||
using ::sapi::IsOk;
|
||||
|
||||
#define __WPTRACEEVENT(x) ((x & 0xff0000) >> 16)
|
||||
|
||||
TEST(RegsTest, SkipSyscallWorks) {
|
||||
std::vector<sock_filter> policy = {
|
||||
LOAD_SYSCALL_NR,
|
||||
JEQ32(__NR_getpid, TRACE(0)),
|
||||
ALLOW,
|
||||
};
|
||||
sock_fprog prog = {
|
||||
.len = policy.size(),
|
||||
.filter = policy.data(),
|
||||
};
|
||||
// Create socketpair for synchronization
|
||||
int sv[2];
|
||||
ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
|
||||
// Fork a child process to run the syscalls in.
|
||||
pid_t ppid = util::Syscall(__NR_gettid);
|
||||
pid_t pid = fork();
|
||||
ASSERT_NE(pid, -1);
|
||||
char c = 'C';
|
||||
if (pid == 0) {
|
||||
// Get ready for being ptraced.
|
||||
sanitizer::WaitForSanitizer();
|
||||
CHECK_EQ(prctl(PR_SET_DUMPABLE, 1), 0);
|
||||
prctl(PR_SET_PTRACER, ppid);
|
||||
CHECK_EQ(prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0), 0);
|
||||
CHECK_EQ(prctl(PR_SET_KEEPCAPS, 0), 0);
|
||||
// Notify parent that we're ready for ptrace.
|
||||
CHECK_EQ(write(sv[0], &c, 1), 1);
|
||||
// Apply seccomp policy
|
||||
CHECK_EQ(util::Syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, 0,
|
||||
reinterpret_cast<uintptr_t>(&prog)),
|
||||
0);
|
||||
// Wait for tracer to be attached.
|
||||
CHECK_EQ(read(sv[0], &c, 1), 1);
|
||||
// Run the test syscall
|
||||
errno = 0;
|
||||
util::Syscall(__NR_getpid, 123, reinterpret_cast<uintptr_t>(&c), 1);
|
||||
_Exit(errno == ENOENT ? 0 : 1);
|
||||
}
|
||||
// Wait for child to be ready for ptrace
|
||||
ASSERT_EQ(read(sv[1], &c, 1), 1);
|
||||
ASSERT_EQ(ptrace(PTRACE_SEIZE, pid, 0, PTRACE_O_TRACESECCOMP), 0);
|
||||
// Notify child it has been ptraced.
|
||||
ASSERT_EQ(write(sv[1], &c, 1), 1);
|
||||
// Wait for seccomp TRACE stop
|
||||
int status;
|
||||
ASSERT_EQ(waitpid(pid, &status, __WNOTHREAD | __WALL | WUNTRACED), pid);
|
||||
ASSERT_TRUE(WIFSTOPPED(status));
|
||||
ASSERT_EQ(__WPTRACEEVENT(status), PTRACE_EVENT_SECCOMP);
|
||||
// Fetch the registers
|
||||
Regs regs(pid);
|
||||
ASSERT_THAT(regs.Fetch(), IsOk());
|
||||
// Check syscall arguments
|
||||
Syscall syscall = regs.ToSyscall(sapi::host_cpu::Architecture());
|
||||
EXPECT_EQ(syscall.nr(), __NR_getpid);
|
||||
EXPECT_EQ(syscall.args()[0], 123);
|
||||
EXPECT_EQ(syscall.args()[1], reinterpret_cast<uintptr_t>(&c));
|
||||
EXPECT_EQ(syscall.args()[2], 1);
|
||||
// Skip syscall
|
||||
ASSERT_THAT(regs.SkipSyscallReturnValue(-ENOENT), IsOk());
|
||||
// Continue&detach the child process
|
||||
ASSERT_EQ(ptrace(PTRACE_DETACH, pid, 0, 0), 0);
|
||||
// Wait for the child to exit
|
||||
ASSERT_EQ(waitpid(pid, &status, __WNOTHREAD | __WALL | WUNTRACED), pid);
|
||||
ASSERT_TRUE(WIFEXITED(status));
|
||||
EXPECT_EQ(WEXITSTATUS(status), 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace sandbox2
|
Loading…
Reference in New Issue
Block a user