| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include "native_client/src/trusted/service_runtime/thread_suspension_unwind.h" | 7 #include "native_client/src/trusted/service_runtime/thread_suspension_unwind.h" |
| 8 | 8 |
| 9 #include "native_client/src/trusted/cpu_features/arch/x86/cpu_x86.h" | 9 #include "native_client/src/trusted/cpu_features/arch/x86/cpu_x86.h" |
| 10 #include "native_client/src/trusted/service_runtime/arch/arm/tramp_arm.h" | 10 #include "native_client/src/trusted/service_runtime/arch/arm/tramp_arm.h" |
| 11 #include "native_client/src/trusted/service_runtime/arch/x86_64/tramp_64.h" | 11 #include "native_client/src/trusted/service_runtime/arch/x86_64/tramp_64.h" |
| 12 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" | 12 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h" |
| 13 #include "native_client/src/trusted/service_runtime/nacl_config.h" | 13 #include "native_client/src/trusted/service_runtime/nacl_config.h" |
| 14 #include "native_client/src/trusted/service_runtime/nacl_copy.h" | 14 #include "native_client/src/trusted/service_runtime/nacl_copy.h" |
| 15 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | 15 #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
| 16 | 16 |
| 17 | 17 |
| 18 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 || \ | |
| 19 NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm | |
| 20 | |
| 21 static void GetNaClSyscallSeg(struct NaClApp *nap, | 18 static void GetNaClSyscallSeg(struct NaClApp *nap, |
| 22 uintptr_t *nacl_syscall_seg, | 19 uintptr_t *nacl_syscall_seg, |
| 23 uintptr_t *nacl_syscall_seg_regs_saved) { | 20 uintptr_t *nacl_syscall_seg_regs_saved) { |
| 24 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 | 21 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 |
| 25 NaClCPUFeaturesX86 *features = (NaClCPUFeaturesX86 *) nap->cpu_features; | 22 NaClCPUFeaturesX86 *features = (NaClCPUFeaturesX86 *) nap->cpu_features; |
| 26 if (NaClGetCPUFeatureX86(features, NaClCPUFeatureX86_SSE)) { | 23 if (NaClGetCPUFeatureX86(features, NaClCPUFeatureX86_SSE)) { |
| 27 *nacl_syscall_seg = (uintptr_t) &NaClSyscallSegSSE; | 24 *nacl_syscall_seg = (uintptr_t) &NaClSyscallSegSSE; |
| 28 *nacl_syscall_seg_regs_saved = (uintptr_t) &NaClSyscallSegRegsSavedSSE; | 25 *nacl_syscall_seg_regs_saved = (uintptr_t) &NaClSyscallSegRegsSavedSSE; |
| 29 } else { | 26 } else { |
| 30 *nacl_syscall_seg = (uintptr_t) &NaClSyscallSegNoSSE; | 27 *nacl_syscall_seg = (uintptr_t) &NaClSyscallSegNoSSE; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 regs->stack_ptr += 8; /* Pop user return address */ | 68 regs->stack_ptr += 8; /* Pop user return address */ |
| 72 return 1; | 69 return 1; |
| 73 } | 70 } |
| 74 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm | 71 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm |
| 75 if (regs->prog_ctr >= NACL_TRAMPOLINE_START && | 72 if (regs->prog_ctr >= NACL_TRAMPOLINE_START && |
| 76 regs->prog_ctr < NACL_TRAMPOLINE_END) { | 73 regs->prog_ctr < NACL_TRAMPOLINE_END) { |
| 77 *unwind_case = NACL_UNWIND_in_trampoline; | 74 *unwind_case = NACL_UNWIND_in_trampoline; |
| 78 regs->prog_ctr = NaClSandboxCodeAddr(nap, regs->lr); | 75 regs->prog_ctr = NaClSandboxCodeAddr(nap, regs->lr); |
| 79 return 1; | 76 return 1; |
| 80 } | 77 } |
| 78 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips |
| 79 if (regs->prog_ctr >= NACL_TRAMPOLINE_START && |
| 80 regs->prog_ctr < NACL_TRAMPOLINE_END) { |
| 81 *unwind_case = NACL_UNWIND_in_trampoline; |
| 82 regs->prog_ctr = NaClSandboxCodeAddr(nap, regs->return_addr); |
| 83 return 1; |
| 84 } |
| 81 #endif | 85 #endif |
| 82 | 86 |
| 83 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 | 87 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 |
| 84 if (regs->cs == NaClGetGlobalCs() && | 88 if (regs->cs == NaClGetGlobalCs() && |
| 85 regs->prog_ctr >= nap->pcrel_thunk && | 89 regs->prog_ctr >= nap->pcrel_thunk && |
| 86 regs->prog_ctr < nap->pcrel_thunk_end) { | 90 regs->prog_ctr < nap->pcrel_thunk_end) { |
| 87 *unwind_case = NACL_UNWIND_in_pcrel_thunk; | 91 *unwind_case = NACL_UNWIND_in_pcrel_thunk; |
| 88 regs->stack_ptr += 4 + 8; /* Pop user + trampoline return addresses */ | 92 regs->stack_ptr += 4 + 8; /* Pop user + trampoline return addresses */ |
| 89 return 1; | 93 return 1; |
| 90 } | 94 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 106 regs->stack_ptr += 8; /* Pop user return address */ | 110 regs->stack_ptr += 8; /* Pop user return address */ |
| 107 } | 111 } |
| 108 return 1; | 112 return 1; |
| 109 } | 113 } |
| 110 #endif | 114 #endif |
| 111 | 115 |
| 112 GetNaClSyscallSeg(nap, &nacl_syscall_seg, &nacl_syscall_seg_regs_saved); | 116 GetNaClSyscallSeg(nap, &nacl_syscall_seg, &nacl_syscall_seg_regs_saved); |
| 113 if (regs->prog_ctr >= nacl_syscall_seg && | 117 if (regs->prog_ctr >= nacl_syscall_seg && |
| 114 regs->prog_ctr < nacl_syscall_seg_regs_saved) { | 118 regs->prog_ctr < nacl_syscall_seg_regs_saved) { |
| 115 *unwind_case = NACL_UNWIND_in_syscallseg; | 119 *unwind_case = NACL_UNWIND_in_syscallseg; |
| 116 if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86) { | 120 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32 |
| 117 if (NACL_BUILD_SUBARCH == 32) { | 121 /* Pop user + trampoline return addresses */ |
| 118 /* Pop user + trampoline return addresses */ | 122 regs->stack_ptr += 4 + 8; |
| 119 regs->stack_ptr += 4 + 8; | 123 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64 |
| 120 } else { | 124 /* Pop user return address. */ |
| 121 /* Pop user return address. */ | 125 regs->stack_ptr += 8; |
| 122 regs->stack_ptr += 8; | 126 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips |
| 123 } | 127 /* |
| 124 } | 128 * On MIPS, $ra is not modified from the start of the trampoline to the |
| 129 * point where registers are saved. |
| 130 */ |
| 131 regs->prog_ctr = NaClSandboxCodeAddr(nap, regs->return_addr); |
| 132 #endif |
| 125 return 1; | 133 return 1; |
| 126 } | 134 } |
| 127 | 135 |
| 128 *unwind_case = NACL_UNWIND_after_saving_regs; | 136 *unwind_case = NACL_UNWIND_after_saving_regs; |
| 129 return 0; | 137 return 0; |
| 130 } | 138 } |
| 131 | 139 |
| 132 /* | 140 /* |
| 133 * Given that thread |natp| has been suspended during a | 141 * Given that thread |natp| has been suspended during a |
| 134 * trusted/untrusted context switch and has trusted register state | 142 * trusted/untrusted context switch and has trusted register state |
| 135 * |regs|, this modifies |regs| to contain untrusted register state | 143 * |regs|, this modifies |regs| to contain untrusted register state |
| 136 * (that is, the state the syscall will return with). | 144 * (that is, the state the syscall will return with). |
| 137 */ | 145 */ |
| 138 void NaClGetRegistersForContextSwitch(struct NaClAppThread *natp, | 146 void NaClGetRegistersForContextSwitch(struct NaClAppThread *natp, |
| 139 struct NaClSignalContext *regs, | 147 struct NaClSignalContext *regs, |
| 140 enum NaClUnwindCase *unwind_case) { | 148 enum NaClUnwindCase *unwind_case) { |
| 141 if (Unwind(natp, regs, unwind_case)) { | 149 if (Unwind(natp, regs, unwind_case)) { |
| 142 NaClSignalContextUnsetClobberedRegisters(regs); | 150 NaClSignalContextUnsetClobberedRegisters(regs); |
| 143 } else { | 151 } else { |
| 144 NaClThreadContextToSignalContext(&natp->user, regs); | 152 NaClThreadContextToSignalContext(&natp->user, regs); |
| 145 } | 153 } |
| 146 | 154 |
| 147 if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 || | 155 if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 || |
| 148 (NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm && | 156 (NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm && |
| 149 *unwind_case != NACL_UNWIND_in_trampoline)) { | 157 *unwind_case != NACL_UNWIND_in_trampoline) || |
| 158 (NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips && |
| 159 *unwind_case != NACL_UNWIND_in_trampoline && |
| 160 *unwind_case != NACL_UNWIND_in_syscallseg)) { |
| 150 /* | 161 /* |
| 151 * Read the return address from the untrusted stack. | 162 * Read the return address from the untrusted stack. |
| 152 * NaClCopyInFromUser() can fault or return an error here, but only | 163 * NaClCopyInFromUser() can fault or return an error here, but only |
| 153 * if the thread was suspended just before it was about to crash. | 164 * if the thread was suspended just before it was about to crash. |
| 154 * This can happen if untrusted code JMP'd to the trampoline with a | 165 * This can happen if untrusted code JMP'd to the trampoline with a |
| 155 * bad stack pointer or if the thread was racing with an munmap(). | 166 * bad stack pointer or if the thread was racing with an munmap(). |
| 156 */ | 167 */ |
| 157 nacl_reg_t user_ret = 0; | 168 nacl_reg_t user_ret = 0; |
| 158 if (!NaClCopyInFromUser(natp->nap, &user_ret, | 169 if (!NaClCopyInFromUser(natp->nap, &user_ret, |
| 159 (uint32_t) (regs->stack_ptr + NACL_USERRET_FIX), | 170 (uint32_t) (regs->stack_ptr + NACL_USERRET_FIX), |
| 160 sizeof(user_ret))) { | 171 sizeof(user_ret))) { |
| 161 NaClLog(LOG_WARNING, "NaClGetRegistersForContextSwitch: " | 172 NaClLog(LOG_WARNING, "NaClGetRegistersForContextSwitch: " |
| 162 "Failed to read return address; using dummy value\n"); | 173 "Failed to read return address; using dummy value\n"); |
| 163 } | 174 } |
| 164 regs->prog_ctr = NaClSandboxCodeAddr(natp->nap, user_ret); | 175 regs->prog_ctr = NaClSandboxCodeAddr(natp->nap, user_ret); |
| 165 } | 176 } |
| 166 } | 177 } |
| 167 | |
| 168 #else | |
| 169 | |
| 170 /* TODO(mseaborn): Extend this to handle MIPS. */ | |
| 171 void NaClGetRegistersForContextSwitch(struct NaClAppThread *natp, | |
| 172 struct NaClSignalContext *regs, | |
| 173 enum NaClUnwindCase *unwind_case) { | |
| 174 UNREFERENCED_PARAMETER(natp); | |
| 175 UNREFERENCED_PARAMETER(regs); | |
| 176 *unwind_case = 0; | |
| 177 } | |
| 178 | |
| 179 #endif | |
| OLD | NEW |