Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Note: any code in this file MUST be async-signal safe. | |
| 6 | |
| 7 #include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" | |
| 8 | |
| 9 #include <unistd.h> | |
| 10 | |
| 11 #include "base/basictypes.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/posix/eintr_wrapper.h" | |
| 14 #include "build/build_config.h" | |
| 15 #include "sandbox/linux/seccomp-bpf/sandbox_bpf.h" | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 inline bool IsArchitectureX86_64() { | |
| 20 #if defined(__x86_64__) | |
| 21 return true; | |
| 22 #else | |
| 23 return false; | |
| 24 #endif | |
| 25 } | |
| 26 | |
| 27 // Write |error_message| to stderr. Similar to RawLog(), but a bit more careful | |
| 28 // about async-signal safety. |size| is the size to write and should typically | |
| 29 // not include a terminating \0. | |
| 30 void WriteToStdErr(const char* error_message, size_t size) { | |
| 31 while (size > 0) { | |
| 32 // TODO(jln): query the current policy to check if send() is available and | |
| 33 // use it to perform a non blocking write. | |
|
Jorge Lucangeli Obes
2013/12/05 16:46:30
nit: non-blocking.
jln (very slow on Chromium)
2013/12/05 18:02:46
Done.
| |
| 34 const int ret = HANDLE_EINTR(write(STDERR_FILENO, error_message, size)); | |
| 35 // We can't handle any type of error here. | |
| 36 if (ret <= 0 || static_cast<size_t>(ret) > size) break; | |
| 37 size -= ret; | |
| 38 error_message += ret; | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 // Print a seccomp-bpf failure to handle |sysno| to stderr in an | |
| 43 // async-signal safe way. | |
| 44 void PrintSyscallError(uint32_t sysno) { | |
| 45 if (sysno >= 1024) | |
| 46 sysno = 0; | |
| 47 // TODO(markus): replace with async-signal safe snprintf when available. | |
| 48 const size_t kNumDigits = 4; | |
| 49 char sysno_base10[kNumDigits]; | |
| 50 uint32_t rem = sysno; | |
| 51 uint32_t mod = 0; | |
| 52 for (int i = kNumDigits - 1; i >= 0; i--) { | |
| 53 mod = rem % 10; | |
| 54 rem /= 10; | |
| 55 sysno_base10[i] = '0' + mod; | |
| 56 } | |
| 57 static const char kSeccompErrorPrefix[] = | |
| 58 __FILE__":**CRASHING**:seccomp-bpf failure in syscall "; | |
| 59 static const char kSeccompErrorPostfix[] = "\n"; | |
| 60 WriteToStdErr(kSeccompErrorPrefix, sizeof(kSeccompErrorPrefix) - 1); | |
| 61 WriteToStdErr(sysno_base10, sizeof(sysno_base10)); | |
| 62 WriteToStdErr(kSeccompErrorPostfix, sizeof(kSeccompErrorPostfix) - 1); | |
| 63 } | |
| 64 | |
| 65 } // namespace. | |
| 66 | |
| 67 namespace sandbox { | |
| 68 | |
| 69 intptr_t CrashSIGSYS_Handler(const struct arch_seccomp_data& args, void* aux) { | |
| 70 uint32_t syscall = args.nr; | |
| 71 if (syscall >= 1024) | |
| 72 syscall = 0; | |
| 73 PrintSyscallError(syscall); | |
| 74 | |
| 75 // Encode 8-bits of the 1st two arguments too, so we can discern which socket | |
| 76 // type, which fcntl, ... etc., without being likely to hit a mapped | |
| 77 // address. | |
| 78 // Do not encode more bits here without thinking about increasing the | |
| 79 // likelihood of collision with mapped pages. | |
| 80 syscall |= ((args.args[0] & 0xffUL) << 12); | |
| 81 syscall |= ((args.args[1] & 0xffUL) << 20); | |
| 82 // Purposefully dereference the syscall as an address so it'll show up very | |
| 83 // clearly and easily in crash dumps. | |
| 84 volatile char* addr = reinterpret_cast<volatile char*>(syscall); | |
| 85 *addr = '\0'; | |
| 86 // In case we hit a mapped address, hit the null page with just the syscall, | |
| 87 // for paranoia. | |
| 88 syscall &= 0xfffUL; | |
| 89 addr = reinterpret_cast<volatile char*>(syscall); | |
| 90 *addr = '\0'; | |
| 91 for (;;) | |
| 92 _exit(1); | |
| 93 } | |
| 94 | |
| 95 // TODO(jln): refactor the reporting functions. | |
| 96 | |
| 97 intptr_t SIGSYSCloneFailure(const struct arch_seccomp_data& args, void* aux) { | |
| 98 // "flags" in the first argument in the kernel's clone(). | |
|
Jorge Lucangeli Obes
2013/12/05 16:46:30
"is" the first argument...
jln (very slow on Chromium)
2013/12/05 18:02:46
Done.
| |
| 99 // Mark as volatile to be able to find the value on the stack in a minidump. | |
| 100 #if !defined(NDEBUG) | |
| 101 RAW_LOG(ERROR, __FILE__":**CRASHING**:clone() failure\n"); | |
| 102 #endif | |
| 103 volatile uint64_t clone_flags = args.args[0]; | |
| 104 volatile char* addr; | |
| 105 if (IsArchitectureX86_64()) { | |
| 106 addr = reinterpret_cast<volatile char*>(clone_flags & 0xFFFFFF); | |
| 107 *addr = '\0'; | |
| 108 } | |
| 109 // Hit the NULL page if this fails to fault. | |
| 110 addr = reinterpret_cast<volatile char*>(clone_flags & 0xFFF); | |
| 111 *addr = '\0'; | |
| 112 for (;;) | |
| 113 _exit(1); | |
| 114 } | |
| 115 | |
| 116 intptr_t SIGSYSPrctlFailure(const struct arch_seccomp_data& args, | |
| 117 void* /* aux */) { | |
| 118 // Mark as volatile to be able to find the value on the stack in a minidump. | |
| 119 #if !defined(NDEBUG) | |
| 120 RAW_LOG(ERROR, __FILE__":**CRASHING**:prctl() failure\n"); | |
| 121 #endif | |
| 122 volatile uint64_t option = args.args[0]; | |
| 123 volatile char* addr = | |
| 124 reinterpret_cast<volatile char*>(option & 0xFFF); | |
| 125 *addr = '\0'; | |
| 126 for (;;) | |
| 127 _exit(1); | |
| 128 } | |
| 129 | |
| 130 intptr_t SIGSYSIoctlFailure(const struct arch_seccomp_data& args, | |
| 131 void* /* aux */) { | |
| 132 // Make "request" volatile so that we can see it on the stack in a minidump. | |
| 133 #if !defined(NDEBUG) | |
| 134 RAW_LOG(ERROR, __FILE__":**CRASHING**:ioctl() failure\n"); | |
| 135 #endif | |
| 136 volatile uint64_t request = args.args[1]; | |
| 137 volatile char* addr = reinterpret_cast<volatile char*>(request & 0xFFFF); | |
| 138 *addr = '\0'; | |
| 139 // Hit the NULL page if this fails. | |
| 140 addr = reinterpret_cast<volatile char*>(request & 0xFFF); | |
| 141 *addr = '\0'; | |
| 142 for (;;) | |
| 143 _exit(1); | |
| 144 } | |
| 145 | |
| 146 } // namespace sandbox. | |
| OLD | NEW |