Commit 22aa66d1 authored by mdempsky's avatar mdempsky Committed by Commit bot

Convert sandbox_bpf_unittest.cc to use bpf_dsl

This unfortunately means converting what are currently sandbox_bpf unit
tests into effectively integration tests for bpf_dsl, as they now test
both bpf_dsl + sandbox_bpf.  However, this is a necessary step towards
eliminating dependencies on the current sandbox_bpf API so that we can
more freely evolve it to fit bpf_dsl's needs.

For ease of review, this only converts tests that were already using
SandboxBPFPolicy (i.e., BPF_TEST()s are left alone), and some of the
conversions are slightly non-idiomatic in the interest of mimicking the
existing test structure.  Both of these will be addressed further in
followup CLs so that this CL can be reviewed as a mere translation of
policies from the sandbox_bpf API to bpf_dsl.

Review URL: https://codereview.chromium.org/559653004

Cr-Commit-Position: refs/heads/master@{#294723}
parent 37e3ddb2
......@@ -98,6 +98,7 @@ test("sandbox_linux_unittests") {
}
if (use_seccomp_bpf) {
sources += [
"bpf_dsl/bpf_dsl_more_unittest.cc",
"bpf_dsl/bpf_dsl_unittest.cc",
"bpf_dsl/cons_unittest.cc",
"seccomp-bpf-helpers/baseline_policy_unittest.cc",
......@@ -105,7 +106,6 @@ test("sandbox_linux_unittests") {
"seccomp-bpf/bpf_tests_unittest.cc",
"seccomp-bpf/codegen_unittest.cc",
"seccomp-bpf/errorcode_unittest.cc",
"seccomp-bpf/sandbox_bpf_unittest.cc",
"seccomp-bpf/syscall_iterator_unittest.cc",
"seccomp-bpf/syscall_unittest.cc",
]
......
include_rules = [
"+sandbox/linux/seccomp-bpf",
"+sandbox/linux/services", # for bpf_dsl_more_unittest.cc
]
......@@ -49,9 +49,42 @@ class ErrorResultExprImpl : public internal::ResultExprImpl {
DISALLOW_COPY_AND_ASSIGN(ErrorResultExprImpl);
};
class KillResultExprImpl : public internal::ResultExprImpl {
public:
explicit KillResultExprImpl(const char* msg) : msg_(msg) { DCHECK(msg_); }
virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
return sb->Kill(msg_);
}
private:
virtual ~KillResultExprImpl() {}
const char* msg_;
DISALLOW_COPY_AND_ASSIGN(KillResultExprImpl);
};
class TraceResultExprImpl : public internal::ResultExprImpl {
public:
TraceResultExprImpl(uint16_t aux) : aux_(aux) {}
virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
return ErrorCode(ErrorCode::ERR_TRACE + aux_);
}
private:
virtual ~TraceResultExprImpl() {}
uint16_t aux_;
DISALLOW_COPY_AND_ASSIGN(TraceResultExprImpl);
};
class TrapResultExprImpl : public internal::ResultExprImpl {
public:
TrapResultExprImpl(Trap::TrapFnc func, void* arg) : func_(func), arg_(arg) {
TrapResultExprImpl(Trap::TrapFnc func, const void* arg)
: func_(func), arg_(arg) {
DCHECK(func_);
}
......@@ -63,11 +96,31 @@ class TrapResultExprImpl : public internal::ResultExprImpl {
virtual ~TrapResultExprImpl() {}
Trap::TrapFnc func_;
void* arg_;
const void* arg_;
DISALLOW_COPY_AND_ASSIGN(TrapResultExprImpl);
};
class UnsafeTrapResultExprImpl : public internal::ResultExprImpl {
public:
UnsafeTrapResultExprImpl(Trap::TrapFnc func, const void* arg)
: func_(func), arg_(arg) {
DCHECK(func_);
}
virtual ErrorCode Compile(SandboxBPF* sb) const OVERRIDE {
return sb->UnsafeTrap(func_, arg_);
}
private:
virtual ~UnsafeTrapResultExprImpl() {}
Trap::TrapFnc func_;
const void* arg_;
DISALLOW_COPY_AND_ASSIGN(UnsafeTrapResultExprImpl);
};
class IfThenResultExprImpl : public internal::ResultExprImpl {
public:
IfThenResultExprImpl(const BoolExpr& cond,
......@@ -228,10 +281,22 @@ ResultExpr Error(int err) {
return ResultExpr(new const ErrorResultExprImpl(err));
}
ResultExpr Trap(Trap::TrapFnc trap_func, void* aux) {
ResultExpr Kill(const char* msg) {
return ResultExpr(new const KillResultExprImpl(msg));
}
ResultExpr Trace(uint16_t aux) {
return ResultExpr(new const TraceResultExprImpl(aux));
}
ResultExpr Trap(Trap::TrapFnc trap_func, const void* aux) {
return ResultExpr(new const TrapResultExprImpl(trap_func, aux));
}
ResultExpr UnsafeTrap(Trap::TrapFnc trap_func, const void* aux) {
return ResultExpr(new const UnsafeTrapResultExprImpl(trap_func, aux));
}
BoolExpr BoolConst(bool value) {
return BoolExpr(new const ConstBoolExprImpl(value));
}
......@@ -311,7 +376,7 @@ ErrorCode SandboxBPFDSLPolicy::InvalidSyscall(SandboxBPF* sb) const {
return InvalidSyscall()->Compile(sb);
}
ResultExpr SandboxBPFDSLPolicy::Trap(Trap::TrapFnc trap_func, void* aux) {
ResultExpr SandboxBPFDSLPolicy::Trap(Trap::TrapFnc trap_func, const void* aux) {
return bpf_dsl::Trap(trap_func, aux);
}
......
......@@ -60,11 +60,12 @@ class SandboxBPF;
//
// More generally, the DSL currently supports the following grammar:
//
// result = Allow() | Error(errno) | Trap(trap_func, aux)
// result = Allow() | Error(errno) | Kill(msg) | Trace(aux)
// | Trap(trap_func, aux) | UnsafeTrap(trap_func, aux)
// | If(bool, result)[.ElseIf(bool, result)].Else(result)
// | Switch(arg)[.Case(val, result)].Default(result)
// bool = BoolConst(boolean) | !bool | bool && bool | bool || bool
// | arg == val
// | arg == val | arg != val
// arg = Arg<T>(num) | arg & mask
//
// The semantics of each function and operator are intended to be
......@@ -113,7 +114,7 @@ class SANDBOX_EXPORT SandboxBPFDSLPolicy : public SandboxBPFPolicy {
virtual ErrorCode InvalidSyscall(SandboxBPF* sb) const OVERRIDE FINAL;
// Helper method so policies can just write Trap(func, aux).
static ResultExpr Trap(Trap::TrapFnc trap_func, void* aux);
static ResultExpr Trap(Trap::TrapFnc trap_func, const void* aux);
private:
DISALLOW_COPY_AND_ASSIGN(SandboxBPFDSLPolicy);
......@@ -129,10 +130,37 @@ SANDBOX_EXPORT ResultExpr Allow();
// side effects.
SANDBOX_EXPORT ResultExpr Error(int err);
// Kill specifies a result to kill the program and print an error message.
SANDBOX_EXPORT ResultExpr Kill(const char* msg);
// Trace specifies a result to notify a tracing process via the
// PTRACE_EVENT_SECCOMP event and allow it to change or skip the system call.
// The value of |aux| will be available to the tracer via PTRACE_GETEVENTMSG.
SANDBOX_EXPORT ResultExpr Trace(uint16_t aux);
// Trap specifies a result that the system call should be handled by
// trapping back into userspace and invoking |trap_func|, passing
// |aux| as the second parameter.
SANDBOX_EXPORT ResultExpr Trap(Trap::TrapFnc trap_func, void* aux);
SANDBOX_EXPORT ResultExpr Trap(Trap::TrapFnc trap_func, const void* aux);
// UnsafeTrap is like Trap, except the policy is marked as "unsafe"
// and allowed to use SandboxSyscall to invoke any system call.
//
// NOTE: This feature, by definition, disables all security features of
// the sandbox. It should never be used in production, but it can be
// very useful to diagnose code that is incompatible with the sandbox.
// If even a single system call returns "UnsafeTrap", the security of
// entire sandbox should be considered compromised.
SANDBOX_EXPORT ResultExpr UnsafeTrap(Trap::TrapFnc trap_func, const void* aux);
// BoolConst converts a bool value into a BoolExpr.
SANDBOX_EXPORT BoolExpr BoolConst(bool value);
// Various ways to combine boolean expressions into more complex expressions.
// They follow standard boolean algebra laws.
SANDBOX_EXPORT BoolExpr operator!(const BoolExpr& cond);
SANDBOX_EXPORT BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs);
SANDBOX_EXPORT BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs);
template <typename T>
class SANDBOX_EXPORT Arg {
......@@ -149,10 +177,14 @@ class SANDBOX_EXPORT Arg {
return Arg(lhs.num_, lhs.mask_ & rhs);
}
// Returns a boolean expression comparing whether the system call
// argument (after applying any bitmasks, if appropriate) equals |rhs|.
// Returns a boolean expression comparing whether the system call argument
// (after applying any bitmasks, if appropriate) equals |rhs|.
friend BoolExpr operator==(const Arg& lhs, T rhs) { return lhs.EqualTo(rhs); }
// Returns a boolean expression comparing whether the system call argument
// (after applying any bitmasks, if appropriate) does not equal |rhs|.
friend BoolExpr operator!=(const Arg& lhs, T rhs) { return !(lhs == rhs); }
private:
Arg(int num, uint64_t mask) : num_(num), mask_(mask) {}
......@@ -164,15 +196,6 @@ class SANDBOX_EXPORT Arg {
DISALLOW_ASSIGN(Arg);
};
// Convert a bool value into a BoolExpr.
SANDBOX_EXPORT BoolExpr BoolConst(bool value);
// Various ways to combine boolean expressions into more complex expressions.
// They follow standard boolean algebra laws.
SANDBOX_EXPORT BoolExpr operator!(const BoolExpr& cond);
SANDBOX_EXPORT BoolExpr operator&&(const BoolExpr& lhs, const BoolExpr& rhs);
SANDBOX_EXPORT BoolExpr operator||(const BoolExpr& lhs, const BoolExpr& rhs);
// If begins a conditional result expression predicated on the
// specified boolean expression.
SANDBOX_EXPORT Elser If(const BoolExpr& cond, const ResultExpr& then_result);
......
......@@ -67,6 +67,10 @@ class BasicPolicy : public SandboxBPFDSLPolicy {
const Arg<pid_t> pid(0);
return If(pid == 0, Error(EPERM)).Else(Error(EINVAL));
}
if (sysno == __NR_setuid) {
const Arg<uid_t> uid(0);
return If(uid != 42, Error(ESRCH)).Else(Error(ENOMEM));
}
return Allow();
}
......@@ -77,6 +81,9 @@ class BasicPolicy : public SandboxBPFDSLPolicy {
BPF_TEST_C(BPFDSL, Basic, BasicPolicy) {
ASSERT_SYSCALL_RESULT(-EPERM, getpgid, 0);
ASSERT_SYSCALL_RESULT(-EINVAL, getpgid, 1);
ASSERT_SYSCALL_RESULT(-ENOMEM, setuid, 42);
ASSERT_SYSCALL_RESULT(-ESRCH, setuid, 43);
}
/* On IA-32, socketpair() is implemented via socketcall(). :-( */
......
......@@ -34,6 +34,7 @@
}],
[ 'use_seccomp_bpf==1', {
'sources': [
'bpf_dsl/bpf_dsl_more_unittest.cc',
'bpf_dsl/bpf_dsl_unittest.cc',
'bpf_dsl/cons_unittest.cc',
'seccomp-bpf-helpers/baseline_policy_unittest.cc',
......@@ -41,7 +42,6 @@
'seccomp-bpf/bpf_tests_unittest.cc',
'seccomp-bpf/codegen_unittest.cc',
'seccomp-bpf/errorcode_unittest.cc',
'seccomp-bpf/sandbox_bpf_unittest.cc',
'seccomp-bpf/syscall_iterator_unittest.cc',
'seccomp-bpf/syscall_unittest.cc',
],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment