1 | // Copyright 2017 the V8 project 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 | // PLEASE READ BEFORE CHANGING THIS FILE! |
6 | // |
7 | // This file implements the out of bounds trap handler for |
8 | // WebAssembly. Trap handlers are notoriously difficult to get |
9 | // right, and getting it wrong can lead to security |
10 | // vulnerabilities. In order to minimize this risk, here are some |
11 | // rules to follow. |
12 | // |
13 | // 1. Do not introduce any new external dependencies. This file needs |
14 | // to be self contained so it is easy to audit everything that a |
15 | // trap handler might do. |
16 | // |
17 | // 2. Any changes must be reviewed by someone from the crash reporting |
18 | // or security team. See OWNERS for suggested reviewers. |
19 | // |
20 | // For more information, see https://goo.gl/yMeyUY. |
21 | // |
22 | // This file contains most of the code that actually runs in a trap handler |
23 | // context. Some additional code is used both inside and outside the trap |
24 | // handler. This code can be found in handler-shared.cc. |
25 | |
26 | #include "src/trap-handler/trap-handler-internal.h" |
27 | #include "src/trap-handler/trap-handler.h" |
28 | |
29 | namespace v8 { |
30 | namespace internal { |
31 | namespace trap_handler { |
32 | |
33 | #if V8_TRAP_HANDLER_SUPPORTED |
34 | |
35 | // This function contains the platform independent portions of fault |
36 | // classification. |
37 | bool TryFindLandingPad(uintptr_t fault_addr, uintptr_t* landing_pad) { |
38 | // TODO(eholk): broad code range check |
39 | |
40 | // Taking locks in the trap handler is risky because a fault in the trap |
41 | // handler itself could lead to a deadlock when attempting to acquire the |
42 | // lock again. We guard against this case with g_thread_in_wasm_code. The |
43 | // lock may only be taken when not executing Wasm code (an assert in |
44 | // MetadataLock's constructor ensures this). The trap handler will bail |
45 | // out before trying to take the lock if g_thread_in_wasm_code is not set. |
46 | MetadataLock lock_holder; |
47 | |
48 | for (size_t i = 0; i < gNumCodeObjects; ++i) { |
49 | const CodeProtectionInfo* data = gCodeObjects[i].code_info; |
50 | if (data == nullptr) { |
51 | continue; |
52 | } |
53 | const Address base = data->base; |
54 | |
55 | if (fault_addr >= base && fault_addr < base + data->size) { |
56 | // Hurray, we found the code object. Check for protected addresses. |
57 | const ptrdiff_t offset = fault_addr - base; |
58 | |
59 | for (unsigned i = 0; i < data->num_protected_instructions; ++i) { |
60 | if (data->instructions[i].instr_offset == offset) { |
61 | // Hurray again, we found the actual instruction. |
62 | *landing_pad = data->instructions[i].landing_offset + base; |
63 | |
64 | gRecoveredTrapCount.store( |
65 | gRecoveredTrapCount.load(std::memory_order_relaxed) + 1, |
66 | std::memory_order_relaxed); |
67 | |
68 | return true; |
69 | } |
70 | } |
71 | } |
72 | } |
73 | return false; |
74 | } |
75 | #endif // V8_TRAP_HANDLER_SUPPORTED |
76 | |
77 | } // namespace trap_handler |
78 | } // namespace internal |
79 | } // namespace v8 |
80 | |