LCOV - code coverage report
Current view: top level - src/trap-handler - handler-outside.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 50 53 94.3 %
Date: 2017-04-26 Functions: 5 5 100.0 %

          Line data    Source code
       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 support code for the out of bounds signal handler.
       8             : // Nothing in here actually runs in the signal handler, but the code here
       9             : // manipulates data structures used by the signal handler so we still need to be
      10             : // careful. In order to minimize this risk, here are some rules to follow.
      11             : //
      12             : // 1. Avoid introducing new external dependencies. The files in src/trap-handler
      13             : //    should be as self-contained as possible to make it easy to audit the code.
      14             : //
      15             : // 2. Any changes must be reviewed by someone from the crash reporting
      16             : //    or security team. Se OWNERS for suggested reviewers.
      17             : //
      18             : // For more information, see https://goo.gl/yMeyUY.
      19             : //
      20             : // For the code that runs in the signal handler itself, see handler-inside.cc.
      21             : 
      22             : #include <signal.h>
      23             : #include <stddef.h>
      24             : #include <stdio.h>
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : 
      28             : #include <atomic>
      29             : #include <limits>
      30             : 
      31             : #include "src/trap-handler/trap-handler-internal.h"
      32             : #include "src/trap-handler/trap-handler.h"
      33             : 
      34             : namespace {
      35             : size_t gNextCodeObject = 0;
      36             : }
      37             : 
      38             : namespace v8 {
      39             : namespace internal {
      40             : namespace trap_handler {
      41             : 
      42             : const size_t kInitialCodeObjectSize = 1024;
      43             : const size_t kCodeObjectGrowthFactor = 2;
      44             : 
      45             : constexpr size_t HandlerDataSize(size_t num_protected_instructions) {
      46             :   return offsetof(CodeProtectionInfo, instructions) +
      47         336 :          num_protected_instructions * sizeof(ProtectedInstructionData);
      48             : }
      49             : 
      50         336 : CodeProtectionInfo* CreateHandlerData(
      51             :     void* base, size_t size, size_t num_protected_instructions,
      52             :     ProtectedInstructionData* protected_instructions) {
      53             :   const size_t alloc_size = HandlerDataSize(num_protected_instructions);
      54             :   CodeProtectionInfo* data =
      55         336 :       reinterpret_cast<CodeProtectionInfo*>(malloc(alloc_size));
      56             : 
      57         336 :   if (data == nullptr) {
      58             :     return nullptr;
      59             :   }
      60             : 
      61         336 :   data->base = base;
      62         336 :   data->size = size;
      63         336 :   data->num_protected_instructions = num_protected_instructions;
      64             : 
      65             :   memcpy(data->instructions, protected_instructions,
      66         336 :          num_protected_instructions * sizeof(ProtectedInstructionData));
      67             : 
      68         336 :   return data;
      69             : }
      70             : 
      71          42 : void UpdateHandlerDataCodePointer(int index, void* base) {
      72          42 :   MetadataLock lock;
      73          42 :   if (static_cast<size_t>(index) >= gNumCodeObjects) {
      74           0 :     abort();
      75             :   }
      76          42 :   CodeProtectionInfo* data = gCodeObjects[index].code_info;
      77          42 :   data->base = base;
      78          42 : }
      79             : 
      80         336 : int RegisterHandlerData(void* base, size_t size,
      81             :                         size_t num_protected_instructions,
      82             :                         ProtectedInstructionData* protected_instructions) {
      83             :   // TODO(eholk): in debug builds, make sure this data isn't already registered.
      84             : 
      85             :   CodeProtectionInfo* data = CreateHandlerData(
      86         336 :       base, size, num_protected_instructions, protected_instructions);
      87             : 
      88         336 :   if (data == nullptr) {
      89           0 :     abort();
      90             :   }
      91             : 
      92         336 :   MetadataLock lock;
      93             : 
      94         336 :   size_t i = gNextCodeObject;
      95             : 
      96             :   // Explicitly convert std::numeric_limits<int>::max() to unsigned to avoid
      97             :   // compiler warnings about signed/unsigned comparisons. We aren't worried
      98             :   // about sign extension because we know std::numeric_limits<int>::max() is
      99             :   // positive.
     100             :   const size_t int_max = std::numeric_limits<int>::max();
     101             : 
     102             :   // We didn't find an opening in the available space, so grow.
     103         336 :   if (i == gNumCodeObjects) {
     104             :     size_t new_size = gNumCodeObjects > 0
     105             :                           ? gNumCodeObjects * kCodeObjectGrowthFactor
     106          72 :                           : kInitialCodeObjectSize;
     107             : 
     108             :     // Because we must return an int, there is no point in allocating space for
     109             :     // more objects than can fit in an int.
     110          72 :     if (new_size > int_max) {
     111             :       new_size = int_max;
     112             :     }
     113          72 :     if (new_size == gNumCodeObjects) {
     114             :       return -1;
     115             :     }
     116             : 
     117             :     // Now that we know our new size is valid, we can go ahead and realloc the
     118             :     // array.
     119             :     gCodeObjects = static_cast<CodeProtectionInfoListEntry*>(
     120          72 :         realloc(gCodeObjects, sizeof(*gCodeObjects) * new_size));
     121             : 
     122          72 :     if (gCodeObjects == nullptr) {
     123           0 :       abort();
     124             :     }
     125             : 
     126          72 :     memset(gCodeObjects + gNumCodeObjects, 0,
     127          72 :            sizeof(*gCodeObjects) * (new_size - gNumCodeObjects));
     128          72 :     gNumCodeObjects = new_size;
     129             :   }
     130             : 
     131             :   DCHECK(gCodeObjects[i].code_info == nullptr);
     132             : 
     133             :   // Find out where the next entry should go.
     134         336 :   if (gCodeObjects[i].next_free == 0) {
     135             :     // if this is a fresh entry, use the next one.
     136         284 :     gNextCodeObject = i + 1;
     137             :     DCHECK(gNextCodeObject == gNumCodeObjects ||
     138             :            (gCodeObjects[gNextCodeObject].code_info == nullptr &&
     139             :             gCodeObjects[gNextCodeObject].next_free == 0));
     140             :   } else {
     141          52 :     gNextCodeObject = gCodeObjects[i].next_free - 1;
     142             :   }
     143             : 
     144         336 :   if (i <= int_max) {
     145         336 :     gCodeObjects[i].code_info = data;
     146         336 :     return static_cast<int>(i);
     147             :   } else {
     148             :     return -1;
     149         336 :   }
     150             : }
     151             : 
     152         188 : void ReleaseHandlerData(int index) {
     153             :   // Remove the data from the global list if it's there.
     154             :   CodeProtectionInfo* data = nullptr;
     155             :   {
     156         188 :     MetadataLock lock;
     157             : 
     158         188 :     data = gCodeObjects[index].code_info;
     159         188 :     gCodeObjects[index].code_info = nullptr;
     160             : 
     161             :     // +1 because we reserve {next_entry == 0} to indicate a fresh list entry.
     162         188 :     gCodeObjects[index].next_free = gNextCodeObject + 1;
     163         188 :     gNextCodeObject = index;
     164             :   }
     165             :   // TODO(eholk): on debug builds, ensure there are no more copies in
     166             :   // the list.
     167         188 :   free(data);
     168         188 : }
     169             : 
     170        4618 : bool RegisterDefaultSignalHandler() {
     171             : #if V8_TRAP_HANDLER_SUPPORTED
     172             :   struct sigaction action;
     173        4618 :   action.sa_sigaction = HandleSignal;
     174        4618 :   action.sa_flags = SA_SIGINFO;
     175        4618 :   sigemptyset(&action.sa_mask);
     176             :   // {sigaction} installs a new custom segfault handler. On success, it returns
     177             :   // 0. If we get a nonzero value, we report an error to the caller by returning
     178             :   // false.
     179        4618 :   if (sigaction(SIGSEGV, &action, nullptr) != 0) {
     180             :     return false;
     181             :   }
     182             : 
     183        4618 :   return true;
     184             : #else
     185             :   return false;
     186             : #endif
     187             : }
     188             : 
     189             : }  // namespace trap_handler
     190             : }  // namespace internal
     191             : }  // namespace v8

Generated by: LCOV version 1.10