Index: sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
index 83b98a663f9235fc63c409fe13d1577ba8d938d0..d0f6620d8ec3af4c6e2c0f30279574bf94cbb160 100644 |
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc |
@@ -199,9 +199,7 @@ class RedirectToUserSpacePolicyWrapper : public SandboxBPFPolicy { |
int system_call_number) const OVERRIDE { |
ErrorCode err = |
wrapped_policy_->EvaluateSyscall(sandbox_compiler, system_call_number); |
- if ((err.err() & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { |
- return ReturnErrnoViaTrap(sandbox_compiler, err.err() & SECCOMP_RET_DATA); |
- } |
+ ChangeErrnoToTraps(&err, sandbox_compiler); |
return err; |
} |
@@ -215,6 +213,29 @@ class RedirectToUserSpacePolicyWrapper : public SandboxBPFPolicy { |
return sandbox_compiler->Trap(ReturnErrno, reinterpret_cast<void*>(err)); |
} |
+ // ChangeErrnoToTraps recursivly iterates through the ErrorCode |
+ // converting any ERRNO to a userspace trap |
+ void ChangeErrnoToTraps(ErrorCode* err, SandboxBPF* sandbox_compiler) const { |
+ if (err->error_type() == ErrorCode::ET_SIMPLE && |
+ (err->err() & SECCOMP_RET_ACTION) == SECCOMP_RET_ERRNO) { |
+ // Have an errno, need to change this to a trap |
+ *err = |
+ ReturnErrnoViaTrap(sandbox_compiler, err->err() & SECCOMP_RET_DATA); |
+ return; |
+ } else if (err->error_type() == ErrorCode::ET_COND) { |
+ // Need to explore both paths |
+ ChangeErrnoToTraps((ErrorCode*)err->passed(), sandbox_compiler); |
+ ChangeErrnoToTraps((ErrorCode*)err->failed(), sandbox_compiler); |
+ return; |
+ } else if (err->error_type() == ErrorCode::ET_TRAP) { |
+ return; |
+ } else if (err->error_type() == ErrorCode::ET_SIMPLE && |
+ (err->err() & SECCOMP_RET_ACTION) == SECCOMP_RET_ALLOW) { |
+ return; |
+ } |
+ NOTREACHED(); |
+ } |
+ |
const SandboxBPFPolicy* wrapped_policy_; |
DISALLOW_COPY_AND_ASSIGN(RedirectToUserSpacePolicyWrapper); |
}; |
@@ -1035,6 +1056,19 @@ ErrorCode SandboxBPF::UnsafeTrap(Trap::TrapFnc fnc, const void* aux) { |
return Trap::MakeTrap(fnc, aux, false /* Unsafe Trap */); |
} |
+bool SandboxBPF::IsRequiredForUnsafeTrap(int sysno) { |
+ return (sysno == __NR_rt_sigprocmask || sysno == __NR_rt_sigreturn |
+#if defined(__NR_sigprocmask) |
+ || |
+ sysno == __NR_sigprocmask |
+#endif |
+#if defined(__NR_sigreturn) |
+ || |
+ sysno == __NR_sigreturn |
+#endif |
+ ); |
+} |
+ |
intptr_t SandboxBPF::ForwardSyscall(const struct arch_seccomp_data& args) { |
return Syscall::Call(args.nr, |
static_cast<intptr_t>(args.args[0]), |