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(
|
cc_library(
|
||||||
name = "syscall",
|
name = "syscall",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
|
|
@ -35,13 +35,14 @@ add_library(sandbox2_regs ${SAPI_LIB_TYPE}
|
||||||
regs.h
|
regs.h
|
||||||
)
|
)
|
||||||
add_library(sandbox2::regs ALIAS sandbox2_regs)
|
add_library(sandbox2::regs ALIAS sandbox2_regs)
|
||||||
target_link_libraries(sandbox2_regs PRIVATE
|
target_link_libraries(sandbox2_regs
|
||||||
absl::core_headers
|
PUBLIC absl::status
|
||||||
absl::strings
|
|
||||||
sapi::config
|
sapi::config
|
||||||
sapi::strerror
|
|
||||||
sandbox2::syscall
|
sandbox2::syscall
|
||||||
sandbox2::violation_proto
|
sandbox2::violation_proto
|
||||||
|
PRIVATE absl::core_headers
|
||||||
|
absl::strings
|
||||||
|
sapi::strerror
|
||||||
sapi::base
|
sapi::base
|
||||||
sapi::status
|
sapi::status
|
||||||
)
|
)
|
||||||
|
@ -609,6 +610,25 @@ target_link_libraries(sandbox2_violation_proto PRIVATE
|
||||||
if(SAPI_ENABLE_TESTS)
|
if(SAPI_ENABLE_TESTS)
|
||||||
add_subdirectory(testcases)
|
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
|
# sandboxed_api/sandbox2:syscall_test
|
||||||
add_executable(sandbox2_syscall_test
|
add_executable(sandbox2_syscall_test
|
||||||
syscall_test.cc
|
syscall_test.cc
|
||||||
|
|
|
@ -118,8 +118,8 @@ absl::Status Regs::SkipSyscallReturnValue(uintptr_t value) {
|
||||||
user_regs_.gpr[0] = -1;
|
user_regs_.gpr[0] = -1;
|
||||||
user_regs_.gpr[3] = value;
|
user_regs_.gpr[3] = value;
|
||||||
#elif defined(SAPI_ARM64)
|
#elif defined(SAPI_ARM64)
|
||||||
user_regs_.regs[0] = -1;
|
syscall_number_ = -1;
|
||||||
syscall_number_ = value;
|
user_regs_.regs[0] = value;
|
||||||
#elif defined(SAPI_ARM)
|
#elif defined(SAPI_ARM)
|
||||||
user_regs_.orig_x0 = -1;
|
user_regs_.orig_x0 = -1;
|
||||||
user_regs_.regs[7] = value;
|
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