Add more convenience functions to PolicyBuilder

- Allow to specify multiple syscalls with `BlockSyscallsWithErrno()`
- Add functions to allow `unlink()` and `rename()` in all their spellings

PiperOrigin-RevId: 414987303
Change-Id: Ic0e680b785e8e3a3498f20e6a7403737e63fe876
This commit is contained in:
Christian Blichmann 2021-12-08 06:40:48 -08:00 committed by Copybara-Service
parent 46c09e0024
commit 354cbe89f9
7 changed files with 134 additions and 54 deletions

View File

@ -70,33 +70,37 @@ std::unique_ptr<Policy> BufferTestcasePolicy() {
.AllowExit() .AllowExit()
.AllowSafeFcntl() .AllowSafeFcntl()
.AllowTime() .AllowTime()
.AllowSyscall(__NR_dup)
.AllowSyscall(__NR_futex)
.AllowSyscall(__NR_getpid)
.AllowSyscall(__NR_gettid)
.AllowSystemMalloc() .AllowSystemMalloc()
.AllowRead() .AllowRead()
.AllowWrite() .AllowWrite()
.AllowSyscall(__NR_nanosleep)
.AllowSyscall(__NR_rt_sigprocmask)
.AllowSyscall(__NR_recvmsg)
.AllowMmap() .AllowMmap()
.AllowStat() .AllowStat()
.AllowSyscall(__NR_lseek) .AllowSyscalls({
.AllowSyscall(__NR_close) __NR_dup,
.BlockSyscallWithErrno(__NR_prlimit64, EPERM) __NR_futex,
__NR_getpid,
__NR_gettid,
__NR_nanosleep,
__NR_rt_sigprocmask,
__NR_recvmsg,
__NR_lseek,
__NR_close,
})
.BlockSyscallsWithErrno(
{
#ifdef __NR_open #ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT) __NR_open,
#endif #endif
.BlockSyscallWithErrno(__NR_openat, ENOENT) __NR_openat,
#ifdef __NR_access #ifdef __NR_access
// On Debian, even static binaries check existence of // On Debian, even static binaries check existence of
// /etc/ld.so.nohwcap. // /etc/ld.so.nohwcap.
.BlockSyscallWithErrno(__NR_access, ENOENT) __NR_access,
#endif
#ifdef __NR_faccessat
.BlockSyscallWithErrno(__NR_faccessat, ENOENT)
#endif #endif
__NR_faccessat,
},
ENOENT)
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.BuildOrDie(); .BuildOrDie();
return s2p; return s2p;

View File

@ -53,11 +53,6 @@ std::unique_ptr<sandbox2::Policy> GetPolicy() {
// Allow the getpid() syscall. // Allow the getpid() syscall.
.AllowSyscall(__NR_getpid) .AllowSyscall(__NR_getpid)
#ifdef __NR_access
// On Debian, even static binaries check existence of /etc/ld.so.nohwcap.
.BlockSyscallWithErrno(__NR_access, ENOENT)
#endif
// Examples for AddPolicyOnSyscall: // Examples for AddPolicyOnSyscall:
.AddPolicyOnSyscall(__NR_write, .AddPolicyOnSyscall(__NR_write,
{ {
@ -89,23 +84,34 @@ std::unique_ptr<sandbox2::Policy> GetPolicy() {
// override this rule. // override this rule.
.AddPolicyOnSyscall( .AddPolicyOnSyscall(
__NR_exit_group, __NR_exit_group,
{// Load first argument (exit_code). {
ARG_32(0), // Load first argument (exit_code).
// Deny every argument except 0. ARG_32(0),
JNE32(0, KILL), // Deny every argument except 0.
// Allow all exit() calls that were not previously forbidden JNE32(0, KILL),
// = exit_code == 0. // Allow all exit() calls that were not previously forbidden
ALLOW}) // = exit_code == 0.
ALLOW,
})
// = This won't have any effect as we handled every case of this syscall // = This won't have any effect as we handled every case of this syscall
// in the previous rule. // in the previous rule.
.AllowSyscall(__NR_exit_group) .AllowSyscall(__NR_exit_group)
#ifdef __NR_open .BlockSyscallsWithErrno(
.BlockSyscallWithErrno(__NR_open, ENOENT) {
#else #ifdef __NR_access
.BlockSyscallWithErrno(__NR_openat, ENOENT) // On Debian, even static binaries check existence of
// /etc/ld.so.nohwcap.
__NR_access,
#endif #endif
#ifdef __NR_open
__NR_open,
#endif
__NR_openat,
},
ENOENT)
.BuildOrDie(); .BuildOrDie();
} }

View File

@ -58,12 +58,14 @@ std::unique_ptr<sandbox2::Policy> GetPolicy() {
.AllowStaticStartup() .AllowStaticStartup()
.AllowSystemMalloc() .AllowSystemMalloc()
.AllowExit() .AllowExit()
.BlockSyscallsWithErrno(
{
#ifdef __NR_access #ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT) __NR_access,
#endif
#ifdef __NR_faccessat
.BlockSyscallWithErrno(__NR_faccessat, ENOENT)
#endif #endif
__NR_faccessat,
},
ENOENT)
.BuildOrDie(); .BuildOrDie();
} }

View File

@ -51,13 +51,17 @@ std::unique_ptr<Policy> NotifyTestcasePolicy() {
.AllowWrite() .AllowWrite()
.AllowSyscall(__NR_close) .AllowSyscall(__NR_close)
.AddPolicyOnSyscall(__NR_personality, {SANDBOX2_TRACE}) .AddPolicyOnSyscall(__NR_personality, {SANDBOX2_TRACE})
.BlockSyscallsWithErrno(
{
#ifdef __NR_open #ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT) __NR_open,
#endif #endif
__NR_openat,
#ifdef __NR_access #ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT) __NR_access,
#endif #endif
.BlockSyscallWithErrno(__NR_openat, ENOENT) },
ENOENT)
.BlockSyscallWithErrno(__NR_prlimit64, EPERM) .BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.BuildOrDie(); .BuildOrDie();
} }

View File

@ -51,16 +51,20 @@ PolicyBuilder CreatePolicyTestPolicyBuilder() {
.AllowSyscall(__NR_close) .AllowSyscall(__NR_close)
.AllowSyscall(__NR_getppid) .AllowSyscall(__NR_getppid)
.AllowTCGETS() .AllowTCGETS()
.BlockSyscallsWithErrno(
{
#ifdef __NR_open #ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT) __NR_open,
#endif #endif
.BlockSyscallWithErrno(__NR_openat, ENOENT) __NR_openat,
#ifdef __NR_access #ifdef __NR_access
.BlockSyscallWithErrno(__NR_access, ENOENT) __NR_access,
#endif #endif
#ifdef __NR_faccessat #ifdef __NR_faccessat
.BlockSyscallWithErrno(__NR_faccessat, ENOENT) __NR_faccessat,
#endif #endif
},
ENOENT)
.BlockSyscallWithErrno(__NR_prlimit64, EPERM); .BlockSyscallWithErrno(__NR_prlimit64, EPERM);
} }
@ -282,10 +286,6 @@ TEST(MultipleSyscalls, AddPolicyOnSyscallsWorks) {
auto executor = absl::make_unique<Executor>(path, args); auto executor = absl::make_unique<Executor>(path, args);
auto policy = PolicyBuilder() auto policy = PolicyBuilder()
#ifdef __NR_open
.BlockSyscallWithErrno(__NR_open, ENOENT)
#endif
.BlockSyscallWithErrno(__NR_openat, ENOENT)
.AllowStaticStartup() .AllowStaticStartup()
.AllowTcMalloc() .AllowTcMalloc()
.AllowExit() .AllowExit()
@ -323,10 +323,18 @@ TEST(MultipleSyscalls, AddPolicyOnSyscallsWorks) {
{ERRNO(42)}) {ERRNO(42)})
.AddPolicyOnSyscalls({__NR_read, __NR_write}, {ERRNO(43)}) .AddPolicyOnSyscalls({__NR_read, __NR_write}, {ERRNO(43)})
.AddPolicyOnSyscall(__NR_umask, {DENY}) .AddPolicyOnSyscall(__NR_umask, {DENY})
.BlockSyscallWithErrno(__NR_prlimit64, EPERM) .BlockSyscallsWithErrno(
#ifdef __NR_access {
.BlockSyscallWithErrno(__NR_access, ENOENT) #ifdef __NR_open
__NR_open,
#endif #endif
__NR_openat,
#ifdef __NR_access
__NR_access,
#endif
},
ENOENT)
.BlockSyscallWithErrno(__NR_prlimit64, EPERM)
.BuildOrDie(); .BuildOrDie();
Sandbox2 s2(std::move(executor), std::move(policy)); Sandbox2 s2(std::move(executor), std::move(policy));

View File

@ -93,6 +93,22 @@ PolicyBuilder& PolicyBuilder::AllowSyscalls(SyscallInitializer nums) {
return *this; return *this;
} }
PolicyBuilder& PolicyBuilder::BlockSyscallsWithErrno(
const std::vector<uint32_t> nums, int error) {
for (auto num : nums) {
AllowSyscall(num);
}
return *this;
}
PolicyBuilder& PolicyBuilder::BlockSyscallsWithErrno(SyscallInitializer nums,
int error) {
for (auto num : nums) {
AllowSyscall(num);
}
return *this;
}
PolicyBuilder& PolicyBuilder::BlockSyscallWithErrno(unsigned int num, PolicyBuilder& PolicyBuilder::BlockSyscallWithErrno(unsigned int num,
int error) { int error) {
if (handled_syscalls_.insert(num).second) { if (handled_syscalls_.insert(num).second) {
@ -574,6 +590,29 @@ PolicyBuilder& PolicyBuilder::AllowLogForwarding() {
}); });
} }
PolicyBuilder& PolicyBuilder::AllowUnlink() {
AllowSyscalls({
#ifdef __NR_unlink
__NR_unlink,
#endif
__NR_unlinkat,
});
return *this;
}
PolicyBuilder& PolicyBuilder::AllowRename() {
AllowSyscalls({
#ifdef __NR_rename
__NR_rename,
#endif
__NR_renameat,
#ifdef __NR_renameat2
__NR_renameat2,
#endif
});
return *this;
}
PolicyBuilder& PolicyBuilder::AllowFutexOp(int op) { PolicyBuilder& PolicyBuilder::AllowFutexOp(int op) {
return AddPolicyOnSyscall( return AddPolicyOnSyscall(
__NR_futex, { __NR_futex, {

View File

@ -114,8 +114,12 @@ class PolicyBuilder final {
PolicyBuilder& AllowSyscalls(const std::vector<uint32_t>& nums); PolicyBuilder& AllowSyscalls(const std::vector<uint32_t>& nums);
PolicyBuilder& AllowSyscalls(SyscallInitializer nums); PolicyBuilder& AllowSyscalls(SyscallInitializer nums);
// Appends code to block a specific syscall while setting errno to the error // Appends code to block a syscalls while setting errno to the error given.
// given PolicyBuilder& BlockSyscallsWithErrno(const std::vector<uint32_t> nums,
int error);
PolicyBuilder& BlockSyscallsWithErrno(SyscallInitializer nums, int error);
// Appends code to block a specific syscall and setting errno.
PolicyBuilder& BlockSyscallWithErrno(unsigned int num, int error); PolicyBuilder& BlockSyscallWithErrno(unsigned int num, int error);
// Appends code to allow exiting. // Appends code to allow exiting.
@ -354,6 +358,19 @@ class PolicyBuilder final {
// - close // - close
PolicyBuilder& AllowLogForwarding(); PolicyBuilder& AllowLogForwarding();
// Appends code to allow deleting files
// Allows these syscalls:
// - unlink (if available)
// - unlinkat
PolicyBuilder& AllowUnlink();
// Appends code to allow renaming files
// Allows these syscalls:
// - rename (if available)
// - renameat
// - renameat2
PolicyBuilder& AllowRename();
// Enables the syscalls necessary to start a statically linked binary // Enables the syscalls necessary to start a statically linked binary
// //
// NOTE: This will call BlockSyscallWithErrno(__NR_readlink, ENOENT). If you // NOTE: This will call BlockSyscallWithErrno(__NR_readlink, ENOENT). If you