Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / sandbox / linux / seccomp-bpf-helpers / baseline_policy.cc
index d0e53e3..7f4d559 100644 (file)
@@ -6,8 +6,10 @@
 
 #include <errno.h>
 #include <sys/mman.h>
-#include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include "base/logging.h"
 #include "build/build_config.h"
 // Changing this implementation will have an effect on *all* policies.
 // Currently this means: Renderer/Worker, GPU, Flash and NaCl.
 
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::Arg;
+using sandbox::bpf_dsl::Error;
+using sandbox::bpf_dsl::If;
+using sandbox::bpf_dsl::ResultExpr;
+
 namespace sandbox {
 
 namespace {
@@ -30,19 +38,20 @@ bool IsBaselinePolicyAllowed(int sysno) {
          SyscallSets::IsAllowedBasicScheduler(sysno) ||
          SyscallSets::IsAllowedEpoll(sysno) ||
          SyscallSets::IsAllowedFileSystemAccessViaFd(sysno) ||
+         SyscallSets::IsAllowedFutex(sysno) ||
          SyscallSets::IsAllowedGeneralIo(sysno) ||
          SyscallSets::IsAllowedGetOrModifySocket(sysno) ||
          SyscallSets::IsAllowedGettime(sysno) ||
-         SyscallSets::IsAllowedPrctl(sysno) ||
          SyscallSets::IsAllowedProcessStartOrDeath(sysno) ||
          SyscallSets::IsAllowedSignalHandling(sysno) ||
-         SyscallSets::IsFutex(sysno) ||
          SyscallSets::IsGetSimpleId(sysno) ||
          SyscallSets::IsKernelInternalApi(sysno) ||
 #if defined(__arm__)
          SyscallSets::IsArmPrivate(sysno) ||
 #endif
-         SyscallSets::IsKill(sysno) ||
+#if defined(__mips__)
+         SyscallSets::IsMipsPrivate(sysno) ||
+#endif
          SyscallSets::IsAllowedOperationOnFd(sysno);
 }
 
@@ -63,96 +72,139 @@ bool IsBaselinePolicyWatched(int sysno) {
          SyscallSets::IsInotify(sysno) ||
          SyscallSets::IsKernelModule(sysno) ||
          SyscallSets::IsKeyManagement(sysno) ||
+         SyscallSets::IsKill(sysno) ||
          SyscallSets::IsMessageQueue(sysno) ||
          SyscallSets::IsMisc(sysno) ||
 #if defined(__x86_64__)
          SyscallSets::IsNetworkSocketInformation(sysno) ||
 #endif
          SyscallSets::IsNuma(sysno) ||
+         SyscallSets::IsPrctl(sysno) ||
          SyscallSets::IsProcessGroupOrSession(sysno) ||
-         SyscallSets::IsProcessPrivilegeChange(sysno) ||
-#if defined(__i386__)
+#if defined(__i386__) || defined(__mips__)
          SyscallSets::IsSocketCall(sysno) ||
 #endif
 #if defined(__arm__)
          SyscallSets::IsArmPciConfig(sysno) ||
 #endif
+#if defined(__mips__)
+         SyscallSets::IsMipsMisc(sysno) ||
+#endif
          SyscallSets::IsTimer(sysno);
 }
 
 // |fs_denied_errno| is the errno return for denied filesystem access.
-ErrorCode EvaluateSyscallImpl(int fs_denied_errno, SandboxBPF* sandbox,
-                              int sysno) {
+ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
+                               pid_t current_pid,
+                               int sysno) {
+#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
+    defined(MEMORY_SANITIZER)
+  // TCGETS is required by the sanitizers on failure.
+  if (sysno == __NR_ioctl) {
+    return RestrictIoctl();
+  }
+
+  if (sysno == __NR_sched_getaffinity) {
+    return Allow();
+  }
+
+  if (sysno == __NR_sigaltstack) {
+    // Required for better stack overflow detection in ASan. Disallowed in
+    // non-ASan builds.
+    return Allow();
+  }
+#endif  // defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||
+        // defined(MEMORY_SANITIZER)
+
   if (IsBaselinePolicyAllowed(sysno)) {
-    return ErrorCode(ErrorCode::ERR_ALLOWED);
+    return Allow();
   }
 
-#if defined(__x86_64__) || defined(__arm__)
-  if (sysno == __NR_socketpair) {
-    // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
-    COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different);
-    return sandbox->Cond(0, ErrorCode::TP_32BIT, ErrorCode::OP_EQUAL, AF_UNIX,
-                         ErrorCode(ErrorCode::ERR_ALLOWED),
-                         sandbox->Trap(CrashSIGSYS_Handler, NULL));
+  if (sysno == __NR_clone) {
+    return RestrictCloneToThreadsAndEPERMFork();
   }
+
+  if (sysno == __NR_fcntl)
+    return RestrictFcntlCommands();
+
+#if defined(__i386__) || defined(__arm__) || defined(__mips__)
+  if (sysno == __NR_fcntl64)
+    return RestrictFcntlCommands();
 #endif
 
+  // fork() is never used as a system call (clone() is used instead), but we
+  // have seen it in fallback code on Android.
+  if (sysno == __NR_fork) {
+    return Error(EPERM);
+  }
+
+  if (sysno == __NR_futex)
+    return RestrictFutex();
+
   if (sysno == __NR_madvise) {
     // Only allow MADV_DONTNEED (aka MADV_FREE).
-    return sandbox->Cond(2, ErrorCode::TP_32BIT,
-                         ErrorCode::OP_EQUAL, MADV_DONTNEED,
-                         ErrorCode(ErrorCode::ERR_ALLOWED),
-                         ErrorCode(EPERM));
+    const Arg<int> advice(2);
+    return If(advice == MADV_DONTNEED, Allow()).Else(Error(EPERM));
   }
 
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
   if (sysno == __NR_mmap)
-    return RestrictMmapFlags(sandbox);
+    return RestrictMmapFlags();
 #endif
 
-#if defined(__i386__) || defined(__arm__)
+#if defined(__i386__) || defined(__arm__) || defined(__mips__)
   if (sysno == __NR_mmap2)
-    return RestrictMmapFlags(sandbox);
+    return RestrictMmapFlags();
 #endif
 
   if (sysno == __NR_mprotect)
-    return RestrictMprotectFlags(sandbox);
+    return RestrictMprotectFlags();
 
-  if (sysno == __NR_fcntl)
-    return RestrictFcntlCommands(sandbox);
+  if (sysno == __NR_prctl)
+    return sandbox::RestrictPrctl();
 
-#if defined(__i386__) || defined(__arm__)
-  if (sysno == __NR_fcntl64)
-    return RestrictFcntlCommands(sandbox);
+#if defined(__x86_64__) || defined(__arm__) || defined(__mips__)
+  if (sysno == __NR_socketpair) {
+    // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen.
+    COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different);
+    const Arg<int> domain(0);
+    return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS());
+  }
 #endif
 
+  if (SyscallSets::IsKill(sysno)) {
+    return RestrictKillTarget(current_pid, sysno);
+  }
+
   if (SyscallSets::IsFileSystem(sysno) ||
       SyscallSets::IsCurrentDirectory(sysno)) {
-    return ErrorCode(fs_denied_errno);
+    return Error(fs_denied_errno);
   }
 
   if (SyscallSets::IsAnySystemV(sysno)) {
-    return ErrorCode(EPERM);
+    return Error(EPERM);
   }
 
   if (SyscallSets::IsUmask(sysno) ||
       SyscallSets::IsDeniedFileSystemAccessViaFd(sysno) ||
-      SyscallSets::IsDeniedGetOrModifySocket(sysno)) {
-    return ErrorCode(EPERM);
+      SyscallSets::IsDeniedGetOrModifySocket(sysno) ||
+      SyscallSets::IsProcessPrivilegeChange(sysno)) {
+    return Error(EPERM);
   }
 
-#if defined(__i386__)
+#if defined(__i386__) || defined(__mips__)
   if (SyscallSets::IsSocketCall(sysno))
-    return RestrictSocketcallCommand(sandbox);
+    return RestrictSocketcallCommand();
 #endif
 
   if (IsBaselinePolicyWatched(sysno)) {
     // Previously unseen syscalls. TODO(jln): some of these should
     // be denied gracefully right away.
-    return sandbox->Trap(CrashSIGSYS_Handler, NULL);
+    return CrashSIGSYS();
   }
+
   // In any other case crash the program with our SIGSYS handler.
-  return sandbox->Trap(CrashSIGSYS_Handler, NULL);
+  return CrashSIGSYS();
 }
 
 }  // namespace.
@@ -160,16 +212,29 @@ ErrorCode EvaluateSyscallImpl(int fs_denied_errno, SandboxBPF* sandbox,
 // Unfortunately C++03 doesn't allow delegated constructors.
 // Call other constructor when C++11 lands.
 BaselinePolicy::BaselinePolicy()
-    : fs_denied_errno_(EPERM) {}
+    : fs_denied_errno_(EPERM), current_pid_(syscall(__NR_getpid)) {}
 
 BaselinePolicy::BaselinePolicy(int fs_denied_errno)
-    : fs_denied_errno_(fs_denied_errno) {}
+    : fs_denied_errno_(fs_denied_errno), current_pid_(syscall(__NR_getpid)) {}
 
-BaselinePolicy::~BaselinePolicy() {}
+BaselinePolicy::~BaselinePolicy() {
+  // Make sure that this policy is created, used and destroyed by a single
+  // process.
+  DCHECK_EQ(syscall(__NR_getpid), current_pid_);
+}
+
+ResultExpr BaselinePolicy::EvaluateSyscall(int sysno) const {
+  // Sanity check that we're only called with valid syscall numbers.
+  DCHECK(SandboxBPF::IsValidSyscallNumber(sysno));
+  // Make sure that this policy is used in the creating process.
+  if (1 == sysno) {
+    DCHECK_EQ(syscall(__NR_getpid), current_pid_);
+  }
+  return EvaluateSyscallImpl(fs_denied_errno_, current_pid_, sysno);
+}
 
-ErrorCode BaselinePolicy::EvaluateSyscall(SandboxBPF* sandbox,
-                                          int sysno) const {
-  return EvaluateSyscallImpl(fs_denied_errno_, sandbox, sysno);
+ResultExpr BaselinePolicy::InvalidSyscall() const {
+  return CrashSIGSYS();
 }
 
 }  // namespace sandbox.