Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(475)

Unified Diff: src/trap-handler/handler-outside.cc

Issue 2371833007: [wasm] Initial signal handler (Closed)
Patch Set: Make sure guard pages get set up when resizing from 0 to more than 0 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/trap-handler/handler-inside.cc ('k') | src/trap-handler/handler-shared.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/trap-handler/handler-outside.cc
diff --git a/src/trap-handler/handler-outside.cc b/src/trap-handler/handler-outside.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ea1500e67e67ecbff6cbb528c0ef996bb5ecb0f5
--- /dev/null
+++ b/src/trap-handler/handler-outside.cc
@@ -0,0 +1,191 @@
+// Copyright 2017 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// PLEASE READ BEFORE CHANGING THIS FILE!
+//
+// This file implements the support code for the out of bounds signal handler.
+// Nothing in here actually runs in the signal handler, but the code here
+// manipulates data structures used by the signal handler so we still need to be
+// careful. In order to minimize this risk, here are some rules to follow.
+//
+// 1. Avoid introducing new external dependencies. The files in src/trap-handler
+// should be as self-contained as possible to make it easy to audit the code.
+//
+// 2. Any changes must be reviewed by someone from the crash reporting
+// or security team. Se OWNERS for suggested reviewers.
+//
+// For more information, see https://goo.gl/yMeyUY.
+//
+// For the code that runs in the signal handler itself, see handler-inside.cc.
+
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atomic>
+#include <limits>
+
+#include "src/trap-handler/trap-handler-internal.h"
+#include "src/trap-handler/trap-handler.h"
+
+namespace {
+size_t gNextCodeObject = 0;
+}
+
+namespace v8 {
+namespace internal {
+namespace trap_handler {
+
+const size_t kInitialCodeObjectSize = 1024;
+const size_t kCodeObjectGrowthFactor = 2;
+
+constexpr size_t HandlerDataSize(size_t num_protected_instructions) {
+ return offsetof(CodeProtectionInfo, instructions) +
+ num_protected_instructions * sizeof(ProtectedInstructionData);
+}
+
+CodeProtectionInfo* CreateHandlerData(
+ void* base, size_t size, size_t num_protected_instructions,
+ ProtectedInstructionData* protected_instructions) {
+ const size_t alloc_size = HandlerDataSize(num_protected_instructions);
+ CodeProtectionInfo* data =
+ reinterpret_cast<CodeProtectionInfo*>(malloc(alloc_size));
+
+ if (data == nullptr) {
+ return nullptr;
+ }
+
+ data->base = base;
+ data->size = size;
+ data->num_protected_instructions = num_protected_instructions;
+
+ memcpy(data->instructions, protected_instructions,
+ num_protected_instructions * sizeof(ProtectedInstructionData));
+
+ return data;
+}
+
+void UpdateHandlerDataCodePointer(int index, void* base) {
+ MetadataLock lock;
+ if (static_cast<size_t>(index) >= gNumCodeObjects) {
+ abort();
+ }
+ CodeProtectionInfo* data = gCodeObjects[index].code_info;
+ data->base = base;
+}
+
+int RegisterHandlerData(void* base, size_t size,
+ size_t num_protected_instructions,
+ ProtectedInstructionData* protected_instructions) {
+ // TODO(eholk): in debug builds, make sure this data isn't already registered.
+
+ CodeProtectionInfo* data = CreateHandlerData(
+ base, size, num_protected_instructions, protected_instructions);
+
+ if (data == nullptr) {
+ abort();
+ }
+
+ MetadataLock lock;
+
+ size_t i = gNextCodeObject;
+
+ // Explicitly convert std::numeric_limits<int>::max() to unsigned to avoid
+ // compiler warnings about signed/unsigned comparisons. We aren't worried
+ // about sign extension because we know std::numeric_limits<int>::max() is
+ // positive.
+ const size_t int_max = std::numeric_limits<int>::max();
+
+ // We didn't find an opening in the available space, so grow.
+ if (i == gNumCodeObjects) {
+ size_t new_size = gNumCodeObjects > 0
+ ? gNumCodeObjects * kCodeObjectGrowthFactor
+ : kInitialCodeObjectSize;
+
+ // Because we must return an int, there is no point in allocating space for
+ // more objects than can fit in an int.
+ if (new_size > int_max) {
+ new_size = int_max;
+ }
+ if (new_size == gNumCodeObjects) {
+ return -1;
+ }
+
+ // Now that we know our new size is valid, we can go ahead and realloc the
+ // array.
+ gCodeObjects = static_cast<CodeProtectionInfoListEntry*>(
+ realloc(gCodeObjects, sizeof(*gCodeObjects) * new_size));
+
+ if (gCodeObjects == nullptr) {
+ abort();
+ }
+
+ memset(gCodeObjects + gNumCodeObjects, 0,
+ sizeof(*gCodeObjects) * (new_size - gNumCodeObjects));
+ gNumCodeObjects = new_size;
+ }
+
+ DCHECK(gCodeObjects[i].code_info == nullptr);
+
+ // Find out where the next entry should go.
+ if (gCodeObjects[i].next_free == 0) {
+ // if this is a fresh entry, use the next one.
+ gNextCodeObject = i + 1;
+ DCHECK(gNextCodeObject == gNumCodeObjects ||
+ (gCodeObjects[gNextCodeObject].code_info == nullptr &&
+ gCodeObjects[gNextCodeObject].next_free == 0));
+ } else {
+ gNextCodeObject = gCodeObjects[i].next_free - 1;
+ }
+
+ if (i <= int_max) {
+ gCodeObjects[i].code_info = data;
+ return static_cast<int>(i);
+ } else {
+ return -1;
+ }
+}
+
+void ReleaseHandlerData(int index) {
+ // Remove the data from the global list if it's there.
+ CodeProtectionInfo* data = nullptr;
+ {
+ MetadataLock lock;
+
+ data = gCodeObjects[index].code_info;
+ gCodeObjects[index].code_info = nullptr;
+
+ // +1 because we reserve {next_entry == 0} to indicate a fresh list entry.
+ gCodeObjects[index].next_free = gNextCodeObject + 1;
+ gNextCodeObject = index;
+ }
+ // TODO(eholk): on debug builds, ensure there are no more copies in
+ // the list.
+ free(data);
+}
+
+bool RegisterDefaultSignalHandler() {
+#if V8_TRAP_HANDLER_SUPPORTED
+ struct sigaction action;
+ action.sa_sigaction = HandleSignal;
+ action.sa_flags = SA_SIGINFO;
+ sigemptyset(&action.sa_mask);
+ // {sigaction} installs a new custom segfault handler. On success, it returns
+ // 0. If we get a nonzero value, we report an error to the caller by returning
+ // false.
+ if (sigaction(SIGSEGV, &action, nullptr) != 0) {
+ return false;
+ }
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+} // namespace trap_handler
+} // namespace internal
+} // namespace v8
« no previous file with comments | « src/trap-handler/handler-inside.cc ('k') | src/trap-handler/handler-shared.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698