Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Unified Diff: components/nacl/loader/nacl_sandbox_linux.cc

Issue 196793023: Add seccomp sandbox for non-SFI NaCl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/nacl/loader/nacl_sandbox_linux.cc
diff --git a/components/nacl/loader/nacl_sandbox_linux.cc b/components/nacl/loader/nacl_sandbox_linux.cc
index f1e4a49a4f71b1ab1efaaade862ea8a9d9f399b2..f49695cb1f4e4a6730e4713191f649de1d23cf4b 100644
--- a/components/nacl/loader/nacl_sandbox_linux.cc
+++ b/components/nacl/loader/nacl_sandbox_linux.cc
@@ -5,8 +5,10 @@
#include "components/nacl/loader/nacl_sandbox_linux.h"
#include <errno.h>
+#include <linux/net.h>
#include <signal.h>
#include <sys/ptrace.h>
+#include <sys/syscall.h>
#include "base/basictypes.h"
#include "base/callback.h"
@@ -16,8 +18,11 @@
#if defined(USE_SECCOMP_BPF)
#include "content/public/common/sandbox_init.h"
+#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+#include "sandbox/linux/seccomp-bpf/trap.h"
#include "sandbox/linux/services/linux_syscalls.h"
using sandbox::ErrorCode;
@@ -122,6 +127,7 @@ ErrorCode NaClBPFSandboxPolicy::EvaluateSyscall(
case __NR_uname:
return ErrorCode(ErrorCode::ERR_ALLOWED);
case __NR_ptrace:
+ // For RunSandboxSanityChecks().
return ErrorCode(EPERM);
default:
// TODO(jln): look into getting rid of System V shared memory:
@@ -142,6 +148,175 @@ ErrorCode NaClBPFSandboxPolicy::EvaluateSyscall(
return ErrorCode(EPERM);
}
+// The seccomp sandbox policy for NaCl non-SFI mode. Note that this
+// policy must be as strong as possible, as non-SFI mode heavily
+// depends on seccomp sandbox.
+class NonSfiNaClBPFSandboxPolicy : public SandboxBPFPolicy {
+ public:
+ explicit NonSfiNaClBPFSandboxPolicy()
+ : baseline_policy_(content::GetBPFSandboxBaselinePolicy()) {
+ }
+ virtual ~NonSfiNaClBPFSandboxPolicy() {}
+
+ virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
+ int system_call_number) const OVERRIDE;
+
+ private:
+ scoped_ptr<SandboxBPFPolicy> baseline_policy_;
+ DISALLOW_COPY_AND_ASSIGN(NonSfiNaClBPFSandboxPolicy);
+};
+
+ErrorCode NonSfiNaClBPFSandboxPolicy::EvaluateSyscall(
+ sandbox::SandboxBPF* sb, int sysno) const {
+ DCHECK(baseline_policy_);
+ ErrorCode ret = baseline_policy_->EvaluateSyscall(sb, sysno);
Mark Seaborn 2014/03/18 23:53:58 You're falling through to the baseline policy. I
jln (very slow on Chromium) 2014/03/20 00:54:53 I absolutely agree with Mark here. We need a short
hamaji 2014/03/24 15:56:37 Done. I also stopped using sandbox::Restrict* as t
+ switch (sysno) {
+ // __NR_times needed as clock() is called by CommandBufferHelper, which is
+ // used by NaCl applications that use Pepper's 3D interfaces.
+ // See crbug.com/264856 for details.
+ case __NR_times:
+ ret = ErrorCode(ErrorCode::ERR_ALLOWED);
+ break;
+
+ // Conditionally allowed syscalls:
+ case __NR_clone: {
+ // We allow clone only for new thread creation.
+ ret = sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS |
+ CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID,
+ ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Trap(sandbox::SIGSYSCloneFailure, NULL));
+ break;
+ }
+ case __NR_prctl:
+ // We only allow PR_SET_NAME, PR_SET_DUMPABLE, and PR_GET_DUMPABLE.
Mark Seaborn 2014/03/18 23:53:58 I don't think these are operations that should be
hamaji 2014/03/24 15:56:37 I stopped using RestrictPrctl. Now it returns EPER
+ ret = sandbox::RestrictPrctl(sb);
+ break;
+#if defined(__i686__)
Mark Seaborn 2014/03/18 23:53:58 __i386__ would be preferred.
hamaji 2014/03/24 15:56:37 Done.
+ case __NR_socketcall: {
+ // We only allow socketpair, sendmsg, and recvmsg.
+ ret = sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ SYS_SOCKETPAIR, ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ SYS_SENDMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
+ sb->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL,
+ SYS_RECVMSG, ErrorCode(ErrorCode::ERR_ALLOWED),
+ ErrorCode(EPERM))));
+ break;
+ }
+#endif
+
+ // It is allowed to call the following syscalls, but they just
+ // return EPERM.
+ case __NR_ptrace:
+ // For RunSandboxSanityChecks().
+ ret = ErrorCode(EPERM);
+ break;
+ case __NR_set_robust_list:
+ // glibc uses this for its pthread implementation. If we return
+ // EPERM for this, glibc will stop using this.
+ // TODO(hamaji): newlib does not use this. Make this SIGTRAP once
+ // we have switched to newlib.
+ ret = ErrorCode(EPERM);
+ break;
+#if !defined(__x86_64__)
+ case __NR_getegid32:
+ case __NR_geteuid32:
+ case __NR_getgid32:
+ case __NR_getuid32:
+#endif
+ // third_party/libevent uses them, but we can just return -1 from
+ // them as it is just checking getuid() != geteuid() and
+ // getgid() != getegid()
+ ret = ErrorCode(EPERM);
+ break;
+#if !defined(__arm__)
Mark Seaborn 2014/03/18 23:53:58 Should be "defined(__i386__) || defined(__x86_64__
hamaji 2014/03/24 15:56:37 Done.
+ case __NR_time:
+ // This is obsolete in ARM EABI, but x86 glibc indirectly calls
+ // this in sysconf.
+ case __NR_modify_ldt:
+ // nacl_helper calls this from service_runtime/linux/x86/nacl_ldt.c
Mark Seaborn 2014/03/18 23:53:58 But this doesn't apply to Non-SFI Mode.
hamaji 2014/03/24 15:56:37 It seems current nacl_helper always calls NaClTlsI
+ ret = ErrorCode(EPERM);
+ break;
+#endif
+
+ // Followings are restricted syscalls.
+
+ // glibc internally calls brk in its memory allocation.
Mark Seaborn 2014/03/18 23:53:58 glibc does call brk(), but it doesn't require it t
jln (very slow on Chromium) 2014/03/20 00:54:53 Yes, in other words, just EPERM it.
hamaji 2014/03/24 15:56:37 Oops, my comment was wrong. brk was called by tcma
Mark Seaborn 2014/03/28 16:41:39 Does tcmalloc currently require brk(), or does it
+ // TODO(hamaji): Uncomment this once newlib switch has been done.
+ // case __NR_brk:
+ case __NR_capget:
Mark Seaborn 2014/03/18 23:53:58 This is a blacklist of disallowed syscalls, but I
hamaji 2014/03/24 15:56:37 Done.
+ case __NR_dup3:
+ case __NR_epoll_create1:
+ case __NR_fcntl:
+ case __NR_fork:
+ case __NR_get_robust_list:
+ case __NR_getgroups:
+ case __NR_getpid:
+ case __NR_getppid:
+ case __NR_getresgid:
+ case __NR_getresuid:
+ case __NR_getsid:
+ case __NR_kill:
+ case __NR_mlock:
+ case __NR_munlock:
+ case __NR_pause:
+ case __NR_pipe2:
+ case __NR_poll:
+ case __NR_ppoll:
+ case __NR_pselect6:
+ case __NR_readv:
+ case __NR_recvmmsg:
+ case __NR_rt_sigaction:
+ case __NR_sendmmsg:
+ case __NR_tgkill:
+ case __NR_tkill:
+ case __NR_wait4:
+ case __NR_waitid:
+ case __NR_writev:
+ // We do not need 32bit versions of them.
+ case __NR_fstat:
+ case __NR_lseek:
+#if !defined(__arm__)
+ // They do not exist on ARM EABI.
+ case __NR_select:
+#endif
+#if defined(__i686__)
+ // This is i686 only.
+ case __NR_waitpid:
+#endif
+#if !defined(__i686__)
+ // i686 uses socketcall instead of them.
+ case __NR_sendto:
+ case __NR_shutdown:
+ case __NR_recvfrom:
+#if defined(__arm__)
+ case __NR_send:
+ case __NR_recv:
+#endif
+#endif
+#if !defined(__x86_64__)
+ // They do not exist on x86-64.
+ case __NR__newselect:
+ case __NR_getegid:
+ case __NR_geteuid:
+ case __NR_getgid:
+ case __NR_getgroups32:
+ case __NR_getresgid32:
+ case __NR_getresuid32:
+ case __NR_getuid:
+ case __NR_rt_sigprocmask:
+ case __NR_rt_sigreturn:
+ case __NR_sigprocmask:
+ case __NR_sigreturn:
+#endif
+ ret = sb->Trap(sandbox::CrashSIGSYS_Handler, NULL);
+ break;
+ }
+ return ret;
+}
+
void RunSandboxSanityChecks() {
errno = 0;
// Make a ptrace request with an invalid PID.
@@ -172,3 +347,15 @@ bool InitializeBPFSandbox() {
#endif // defined(USE_SECCOMP_BPF)
return false;
}
+
+bool InitializeBPFSandboxForNonSfi() {
+#if defined(USE_SECCOMP_BPF)
+ bool sandbox_is_initialized = content::InitializeSandbox(
hamaji 2014/03/14 12:46:23 I thought we should add something like #if !defi
jln (very slow on Chromium) 2014/03/20 00:54:53 We should not return false in non SFI mode. We sho
hamaji 2014/03/24 15:56:37 Done.
+ scoped_ptr<SandboxBPFPolicy>(new NonSfiNaClBPFSandboxPolicy()));
+ if (sandbox_is_initialized) {
+ RunSandboxSanityChecks();
+ return true;
+ }
+#endif // defined(USE_SECCOMP_BPF)
+ return false;
+}

Powered by Google App Engine
This is Rietveld 408576698