| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" | 5 #include "components/nacl/loader/nonsfi/nonsfi_sandbox.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <linux/futex.h> | 9 #include <linux/futex.h> |
| 10 #include <linux/net.h> | 10 #include <linux/net.h> |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 // We allow following cases: | 54 // We allow following cases: |
| 55 // 1. F_SETFD + FD_CLOEXEC: libevent's epoll_init uses this. | 55 // 1. F_SETFD + FD_CLOEXEC: libevent's epoll_init uses this. |
| 56 // 2. F_GETFL: Used by SetNonBlocking in | 56 // 2. F_GETFL: Used by SetNonBlocking in |
| 57 // message_pump_libevent.cc and Channel::ChannelImpl::CreatePipe | 57 // message_pump_libevent.cc and Channel::ChannelImpl::CreatePipe |
| 58 // in ipc_channel_posix.cc. Note that the latter does not work | 58 // in ipc_channel_posix.cc. Note that the latter does not work |
| 59 // with EPERM. | 59 // with EPERM. |
| 60 // 3. F_SETFL: Used by evutil_make_socket_nonblocking in | 60 // 3. F_SETFL: Used by evutil_make_socket_nonblocking in |
| 61 // libevent and SetNonBlocking. As the latter mix O_NONBLOCK to | 61 // libevent and SetNonBlocking. As the latter mix O_NONBLOCK to |
| 62 // the return value of F_GETFL, so we need to allow O_ACCMODE in | 62 // the return value of F_GETFL, so we need to allow O_ACCMODE in |
| 63 // addition to O_NONBLOCK. | 63 // addition to O_NONBLOCK. |
| 64 const unsigned long denied_mask = ~(O_ACCMODE | O_NONBLOCK); | 64 const uint64_t kAllowedMask = O_ACCMODE | O_NONBLOCK; |
| 65 return If((cmd == F_SETFD && long_arg == FD_CLOEXEC) || cmd == F_GETFL || | 65 return If((cmd == F_SETFD && long_arg == FD_CLOEXEC) || cmd == F_GETFL || |
| 66 (cmd == F_SETFL && (long_arg & denied_mask) == 0), | 66 (cmd == F_SETFL && (long_arg & ~kAllowedMask) == 0), |
| 67 Allow()).Else(CrashSIGSYS()); | 67 Allow()).Else(CrashSIGSYS()); |
| 68 } | 68 } |
| 69 | 69 |
| 70 ResultExpr RestrictClone() { | 70 ResultExpr RestrictClone() { |
| 71 // We allow clone only for new thread creation. | 71 // We allow clone only for new thread creation. |
| 72 const Arg<int> flags(0); | 72 const Arg<int> flags(0); |
| 73 return If(flags == (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | | 73 return If(flags == (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | |
| 74 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | | 74 CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | |
| 75 CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID), | 75 CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID), |
| 76 Allow()).Else(CrashSIGSYSClone()); | 76 Allow()).Else(CrashSIGSYSClone()); |
| 77 } | 77 } |
| 78 | 78 |
| 79 ResultExpr RestrictFutexOperation() { | 79 ResultExpr RestrictFutexOperation() { |
| 80 // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes. | 80 // TODO(hamaji): Allow only FUTEX_PRIVATE_FLAG futexes. |
| 81 const int kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME; | 81 const uint64_t kAllowedFutexFlags = FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME; |
| 82 const int kOperationMask = ~kAllowedFutexFlags; | |
| 83 const Arg<int> op(1); | 82 const Arg<int> op(1); |
| 84 return Switch(op & kOperationMask) | 83 return Switch(op & ~kAllowedFutexFlags) |
| 85 .CASES((FUTEX_WAIT, | 84 .CASES((FUTEX_WAIT, |
| 86 FUTEX_WAKE, | 85 FUTEX_WAKE, |
| 87 FUTEX_REQUEUE, | 86 FUTEX_REQUEUE, |
| 88 FUTEX_CMP_REQUEUE, | 87 FUTEX_CMP_REQUEUE, |
| 89 FUTEX_WAKE_OP, | 88 FUTEX_WAKE_OP, |
| 90 FUTEX_WAIT_BITSET, | 89 FUTEX_WAIT_BITSET, |
| 91 FUTEX_WAKE_BITSET), | 90 FUTEX_WAKE_BITSET), |
| 92 Allow()) | 91 Allow()) |
| 93 .Default(CrashSIGSYSFutex()); | 92 .Default(CrashSIGSYSFutex()); |
| 94 } | 93 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 106 const Arg<int> call(0); | 105 const Arg<int> call(0); |
| 107 return If(call == SYS_SOCKETPAIR || call == SYS_SHUTDOWN || | 106 return If(call == SYS_SOCKETPAIR || call == SYS_SHUTDOWN || |
| 108 call == SYS_SENDMSG || call == SYS_RECVMSG, | 107 call == SYS_SENDMSG || call == SYS_RECVMSG, |
| 109 Allow()).Else(CrashSIGSYS()); | 108 Allow()).Else(CrashSIGSYS()); |
| 110 } | 109 } |
| 111 #endif | 110 #endif |
| 112 | 111 |
| 113 ResultExpr RestrictMprotect() { | 112 ResultExpr RestrictMprotect() { |
| 114 // TODO(jln, keescook, drewry): Limit the use of mprotect by adding | 113 // TODO(jln, keescook, drewry): Limit the use of mprotect by adding |
| 115 // some features to linux kernel. | 114 // some features to linux kernel. |
| 116 const uint32_t denied_mask = ~(PROT_READ | PROT_WRITE | PROT_EXEC); | 115 const uint64_t kAllowedMask = PROT_READ | PROT_WRITE | PROT_EXEC; |
| 117 const Arg<int> prot(2); | 116 const Arg<int> prot(2); |
| 118 return If((prot & denied_mask) == 0, Allow()).Else(CrashSIGSYS()); | 117 return If((prot & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()); |
| 119 } | 118 } |
| 120 | 119 |
| 121 ResultExpr RestrictMmap() { | 120 ResultExpr RestrictMmap() { |
| 122 const uint32_t denied_flag_mask = ~(MAP_SHARED | MAP_PRIVATE | | 121 const uint64_t kAllowedFlagMask = |
| 123 MAP_ANONYMOUS | MAP_STACK | MAP_FIXED); | 122 MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_FIXED; |
| 124 // When PROT_EXEC is specified, IRT mmap of Non-SFI NaCl helper | 123 // When PROT_EXEC is specified, IRT mmap of Non-SFI NaCl helper |
| 125 // calls mmap without PROT_EXEC and then adds PROT_EXEC by mprotect, | 124 // calls mmap without PROT_EXEC and then adds PROT_EXEC by mprotect, |
| 126 // so we do not need to allow PROT_EXEC in mmap. | 125 // so we do not need to allow PROT_EXEC in mmap. |
| 127 const uint32_t denied_prot_mask = ~(PROT_READ | PROT_WRITE); | 126 const uint64_t kAllowedProtMask = PROT_READ | PROT_WRITE; |
| 128 const Arg<int> prot(2), flags(3); | 127 const Arg<int> prot(2), flags(3); |
| 129 return If((prot & denied_prot_mask) == 0 && (flags & denied_flag_mask) == 0, | 128 return If((prot & ~kAllowedProtMask) == 0 && (flags & ~kAllowedFlagMask) == 0, |
| 130 Allow()).Else(CrashSIGSYS()); | 129 Allow()).Else(CrashSIGSYS()); |
| 131 } | 130 } |
| 132 | 131 |
| 133 #if defined(__x86_64__) || defined(__arm__) | 132 #if defined(__x86_64__) || defined(__arm__) |
| 134 ResultExpr RestrictSocketpair() { | 133 ResultExpr RestrictSocketpair() { |
| 135 // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen. | 134 // Only allow AF_UNIX, PF_UNIX. Crash if anything else is seen. |
| 136 COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different); | 135 COMPILE_ASSERT(AF_UNIX == PF_UNIX, af_unix_pf_unix_different); |
| 137 const Arg<int> domain(0); | 136 const Arg<int> domain(0); |
| 138 return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS()); | 137 return If(domain == AF_UNIX, Allow()).Else(CrashSIGSYS()); |
| 139 } | 138 } |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 scoped_ptr<sandbox::bpf_dsl::SandboxBPFDSLPolicy>( | 305 scoped_ptr<sandbox::bpf_dsl::SandboxBPFDSLPolicy>( |
| 307 new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy())); | 306 new nacl::nonsfi::NaClNonSfiBPFSandboxPolicy())); |
| 308 if (!sandbox_is_initialized) | 307 if (!sandbox_is_initialized) |
| 309 return false; | 308 return false; |
| 310 RunSandboxSanityChecks(); | 309 RunSandboxSanityChecks(); |
| 311 return true; | 310 return true; |
| 312 } | 311 } |
| 313 | 312 |
| 314 } // namespace nonsfi | 313 } // namespace nonsfi |
| 315 } // namespace nacl | 314 } // namespace nacl |
| OLD | NEW |