mirror of
https://github.com/google/sandboxed-api.git
synced 2024-03-22 13:11:30 +08:00
Add option to block the ptrace system call instead of denying it.
PiperOrigin-RevId: 451347905 Change-Id: Iaed0f6f116bca3be4e6e7009dddd4dd6267823bb
This commit is contained in:
parent
65487bca39
commit
5513e560eb
|
@ -106,10 +106,16 @@ std::vector<sock_filter> Policy::GetDefaultPolicy() const {
|
||||||
SANDBOX2_TRACE,
|
SANDBOX2_TRACE,
|
||||||
LABEL(&l, past_execveat_l),
|
LABEL(&l, past_execveat_l),
|
||||||
|
|
||||||
// Forbid ptrace because it's unsafe or too risky.
|
|
||||||
LOAD_SYSCALL_NR,
|
LOAD_SYSCALL_NR,
|
||||||
JEQ32(__NR_ptrace, DENY),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Forbid ptrace because it's unsafe or too risky. The user policy can only
|
||||||
|
// block (i.e. return an error instead of killing the process) but not allow
|
||||||
|
// ptrace. This uses LOAD_SYSCALL_NR from above.
|
||||||
|
if (!user_policy_handles_ptrace_) {
|
||||||
|
policy.insert(policy.end(), {JEQ32(__NR_ptrace, DENY)});
|
||||||
|
}
|
||||||
|
|
||||||
// If user policy doesn't mention it, then forbid bpf because it's unsafe or
|
// If user policy doesn't mention it, then forbid bpf because it's unsafe or
|
||||||
// too risky. This uses LOAD_SYSCALL_NR from above.
|
// too risky. This uses LOAD_SYSCALL_NR from above.
|
||||||
if (!user_policy_handles_bpf_) {
|
if (!user_policy_handles_bpf_) {
|
||||||
|
|
|
@ -107,6 +107,7 @@ class Policy final {
|
||||||
// The policy set by the user.
|
// The policy set by the user.
|
||||||
std::vector<sock_filter> user_policy_;
|
std::vector<sock_filter> user_policy_;
|
||||||
bool user_policy_handles_bpf_ = false;
|
bool user_policy_handles_bpf_ = false;
|
||||||
|
bool user_policy_handles_ptrace_ = false;
|
||||||
|
|
||||||
// Contains a list of hosts the sandboxee is allowed to connect to.
|
// Contains a list of hosts the sandboxee is allowed to connect to.
|
||||||
absl::optional<AllowedHosts> allowed_hosts_;
|
absl::optional<AllowedHosts> allowed_hosts_;
|
||||||
|
|
|
@ -114,6 +114,21 @@ TEST(PolicyTest, PtraceDisallowed) {
|
||||||
EXPECT_THAT(result.reason_code(), Eq(__NR_ptrace));
|
EXPECT_THAT(result.reason_code(), Eq(__NR_ptrace));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PolicyTest, PtraceBlocked) {
|
||||||
|
SKIP_SANITIZERS_AND_COVERAGE;
|
||||||
|
const std::string path = GetTestSourcePath("sandbox2/testcases/policy");
|
||||||
|
std::vector<std::string> args = {path, "8"};
|
||||||
|
|
||||||
|
Sandbox2 s2(std::make_unique<Executor>(path, args),
|
||||||
|
CreatePolicyTestPolicyBuilder()
|
||||||
|
.BlockSyscallWithErrno(__NR_ptrace, EPERM)
|
||||||
|
.BuildOrDie());
|
||||||
|
auto result = s2.Run();
|
||||||
|
|
||||||
|
// The policy binary fails with an error if the system call is *not* blocked.
|
||||||
|
ASSERT_THAT(result.final_status(), Eq(Result::OK));
|
||||||
|
}
|
||||||
|
|
||||||
// Test that clone(2) with flag CLONE_UNTRACED is disallowed.
|
// Test that clone(2) with flag CLONE_UNTRACED is disallowed.
|
||||||
TEST(PolicyTest, CloneUntracedDisallowed) {
|
TEST(PolicyTest, CloneUntracedDisallowed) {
|
||||||
SKIP_SANITIZERS_AND_COVERAGE;
|
SKIP_SANITIZERS_AND_COVERAGE;
|
||||||
|
|
|
@ -113,6 +113,9 @@ PolicyBuilder& PolicyBuilder::BlockSyscallWithErrno(uint32_t num, int error) {
|
||||||
if (num == __NR_bpf) {
|
if (num == __NR_bpf) {
|
||||||
user_policy_handles_bpf_ = true;
|
user_policy_handles_bpf_ = true;
|
||||||
}
|
}
|
||||||
|
if (num == __NR_ptrace) {
|
||||||
|
user_policy_handles_ptrace_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -929,6 +932,7 @@ absl::StatusOr<std::unique_ptr<Policy>> PolicyBuilder::TryBuild() {
|
||||||
overridable_policy_.begin(),
|
overridable_policy_.begin(),
|
||||||
overridable_policy_.end());
|
overridable_policy_.end());
|
||||||
output->user_policy_handles_bpf_ = user_policy_handles_bpf_;
|
output->user_policy_handles_bpf_ = user_policy_handles_bpf_;
|
||||||
|
output->user_policy_handles_ptrace_ = user_policy_handles_ptrace_;
|
||||||
|
|
||||||
auto pb_description = absl::make_unique<PolicyBuilderDescription>();
|
auto pb_description = absl::make_unique<PolicyBuilderDescription>();
|
||||||
|
|
||||||
|
|
|
@ -639,6 +639,7 @@ class PolicyBuilder final {
|
||||||
std::vector<sock_filter> user_policy_;
|
std::vector<sock_filter> user_policy_;
|
||||||
std::vector<sock_filter> overridable_policy_;
|
std::vector<sock_filter> overridable_policy_;
|
||||||
bool user_policy_handles_bpf_ = false;
|
bool user_policy_handles_bpf_ = false;
|
||||||
|
bool user_policy_handles_ptrace_ = false;
|
||||||
absl::flat_hash_set<uint32_t> handled_syscalls_;
|
absl::flat_hash_set<uint32_t> handled_syscalls_;
|
||||||
|
|
||||||
// Error handling
|
// Error handling
|
||||||
|
|
|
@ -58,13 +58,22 @@ void TestAMD64SyscallMismatchFs() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void TestPtrace() {
|
void TestPtraceDenied() {
|
||||||
ptrace(PTRACE_SEIZE, getppid(), 0, 0);
|
ptrace(PTRACE_SEIZE, getppid(), 0, 0);
|
||||||
|
|
||||||
printf("Syscall violation should have been discovered by now\n");
|
printf("Syscall violation should have been discovered by now\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestPtraceBlocked() {
|
||||||
|
int result = ptrace(PTRACE_SEIZE, getppid(), 0, 0);
|
||||||
|
|
||||||
|
if (result != -1 || errno != EPERM) {
|
||||||
|
printf("System call should have been blocked\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TestCloneUntraced() {
|
void TestCloneUntraced() {
|
||||||
syscall(__NR_clone, static_cast<uintptr_t>(CLONE_UNTRACED), nullptr, nullptr,
|
syscall(__NR_clone, static_cast<uintptr_t>(CLONE_UNTRACED), nullptr, nullptr,
|
||||||
nullptr, static_cast<uintptr_t>(0));
|
nullptr, static_cast<uintptr_t>(0));
|
||||||
|
@ -113,7 +122,7 @@ int main(int argc, char* argv[]) {
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 3:
|
case 3:
|
||||||
TestPtrace();
|
TestPtraceDenied();
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
TestCloneUntraced();
|
TestCloneUntraced();
|
||||||
|
@ -127,6 +136,9 @@ int main(int argc, char* argv[]) {
|
||||||
case 7:
|
case 7:
|
||||||
TestBpfError();
|
TestBpfError();
|
||||||
break;
|
break;
|
||||||
|
case 8:
|
||||||
|
TestPtraceBlocked();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Unknown test: %d\n", testno);
|
printf("Unknown test: %d\n", testno);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user