LCOV - code coverage report
Current view: top level - lib/malloc - map_anon.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 32 43 74.4 %
Date: 2021-11-24 03:28:48 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2003-2004, Roger Dingledine
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : /**
       7             :  * \file map_anon.c
       8             :  * \brief Manage anonymous mappings.
       9             :  **/
      10             : 
      11             : #include "orconfig.h"
      12             : #include "lib/malloc/map_anon.h"
      13             : #include "lib/malloc/malloc.h"
      14             : #include "lib/err/torerr.h"
      15             : 
      16             : #ifdef HAVE_SYS_MMAN_H
      17             : #include <sys/mman.h>
      18             : #endif
      19             : #ifdef HAVE_SYS_TYPES_H
      20             : #include <sys/types.h>
      21             : #endif
      22             : #ifdef HAVE_MACH_VM_INHERIT_H
      23             : #include <mach/vm_inherit.h>
      24             : #endif
      25             : 
      26             : #ifdef _WIN32
      27             : #include <windows.h>
      28             : #endif
      29             : 
      30             : #include <string.h>
      31             : #include <errno.h>
      32             : 
      33             : /**
      34             :  * Macro to get the high bytes of a size_t, if there are high bytes.
      35             :  * Windows needs this; other operating systems define a size_t that does
      36             :  * what it should.
      37             :  */
      38             : #if SIZEOF_SIZE_T > 4
      39             : #define HIGH_SIZE_T_BYTES(sz) ((sz) >> 32)
      40             : #else
      41             : #define HIGH_SIZE_T_BYTES(sz) (0)
      42             : #endif
      43             : 
      44             : /* Here we define a MINHERIT macro that is minherit() or madvise(), depending
      45             :  * on what we actually want.
      46             :  *
      47             :  * If there's a flag that sets pages to zero after fork, we define FLAG_ZERO
      48             :  * to be that flag.  If there's a flag unmaps pages after fork, we define
      49             :  * FLAG_NOINHERIT to be that flag.
      50             :  */
      51             : #if defined(HAVE_MINHERIT)
      52             : #define MINHERIT minherit
      53             : 
      54             : #ifdef INHERIT_ZERO
      55             : #define FLAG_ZERO INHERIT_ZERO
      56             : #elif defined(MAP_INHERIT_ZERO)
      57             : #define FLAG_ZERO MAP_INHERIT_ZERO
      58             : #endif
      59             : #ifdef INHERIT_NONE
      60             : #define FLAG_NOINHERIT INHERIT_NONE
      61             : #elif defined(VM_INHERIT_NONE)
      62             : #define FLAG_NOINHERIT VM_INHERIT_NONE
      63             : #elif defined(MAP_INHERIT_NONE)
      64             : #define FLAG_NOINHERIT MAP_INHERIT_NONE
      65             : #endif /* defined(INHERIT_NONE) || ... */
      66             : 
      67             : #elif defined(HAVE_MADVISE)
      68             : 
      69             : #define MINHERIT madvise
      70             : 
      71             : #ifdef MADV_WIPEONFORK
      72             : #define FLAG_ZERO MADV_WIPEONFORK
      73             : #endif
      74             : #ifdef MADV_DONTFORK
      75             : #define FLAG_NOINHERIT MADV_DONTFORK
      76             : #endif
      77             : 
      78             : #endif /* defined(HAVE_MINHERIT) || ... */
      79             : 
      80             : #if defined(HAVE_MINHERIT) && !defined(FLAG_ZERO) && !defined(FLAG_NOINHERIT)
      81             : #warning "minherit() is defined, but FLAG_ZERO/NOINHERIT are not."
      82             : #warning "This is probably a bug in Tor's support for this platform."
      83             : #endif
      84             : 
      85             : /**
      86             :  * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from being swapped
      87             :  * to disk.  Return 0 on success or if the facility is not available on this
      88             :  * OS; return -1 on failure.
      89             :  */
      90             : static int
      91         171 : lock_mem(void *mem, size_t sz)
      92             : {
      93             : #ifdef _WIN32
      94             :   return VirtualLock(mem, sz) ? 0 : -1;
      95             : #elif defined(HAVE_MLOCK)
      96             :   return mlock(mem, sz);
      97             : #else
      98         171 :   (void) mem;
      99         171 :   (void) sz;
     100             : 
     101         171 :   return 0;
     102             : #endif /* defined(_WIN32) || ... */
     103             : }
     104             : 
     105             : /**
     106             :  * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from appearing in
     107             :  * a core dump.  Return 0 on success or if the facility is not available on
     108             :  * this OS; return -1 on failure.
     109             :  */
     110             : static int
     111         171 : nodump_mem(void *mem, size_t sz)
     112             : {
     113             : #if defined(MADV_DONTDUMP)
     114         171 :   int rv = madvise(mem, sz, MADV_DONTDUMP);
     115         171 :   if (rv == 0) {
     116             :     return 0;
     117           0 :   } else if (errno == ENOSYS || errno == EINVAL) {
     118             :     return 0; // syscall not supported, or flag not supported.
     119             :   } else {
     120           0 :     tor_log_err_sigsafe("Unexpected error from madvise: ",
     121             :                         strerror(errno),
     122             :                         NULL);
     123           0 :     return -1;
     124             :   }
     125             : #else /* !defined(MADV_DONTDUMP) */
     126             :   (void) mem;
     127             :   (void) sz;
     128             :   return 0;
     129             : #endif /* defined(MADV_DONTDUMP) */
     130             : }
     131             : 
     132             : /**
     133             :  * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from being
     134             :  * accessible in child processes -- ideally by having them set to 0 after a
     135             :  * fork, and if that doesn't work, by having them unmapped after a fork.
     136             :  * Return 0 on success or if the facility is not available on this OS; return
     137             :  * -1 on failure.
     138             :  *
     139             :  * If we successfully make the memory uninheritable, adjust the value of
     140             :  * *<b>inherit_result_out</b>.
     141             :  */
     142             : static int
     143         172 : noinherit_mem(void *mem, size_t sz, inherit_res_t *inherit_result_out)
     144             : {
     145             : #ifdef FLAG_ZERO
     146         172 :   int r = MINHERIT(mem, sz, FLAG_ZERO);
     147         172 :   if (r == 0) {
     148         172 :     *inherit_result_out = INHERIT_RES_ZERO;
     149         172 :     return 0;
     150             :   }
     151             : #endif /* defined(FLAG_ZERO) */
     152             : 
     153             : #ifdef FLAG_NOINHERIT
     154           0 :   int r2 = MINHERIT(mem, sz, FLAG_NOINHERIT);
     155           0 :   if (r2 == 0) {
     156           0 :     *inherit_result_out = INHERIT_RES_DROP;
     157           0 :     return 0;
     158             :   }
     159             : #endif /* defined(FLAG_NOINHERIT) */
     160             : 
     161             : #if defined(FLAG_ZERO) || defined(FLAG_NOINHERIT)
     162             :   /* At least one operation was tried, and neither succeeded. */
     163             : 
     164           0 :   if (errno == ENOSYS || errno == EINVAL) {
     165             :     /* Syscall not supported, or flag not supported. */
     166             :     return 0;
     167             :   } else {
     168           0 :     tor_log_err_sigsafe("Unexpected error from minherit: ",
     169             :                         strerror(errno),
     170             :                         NULL);
     171           0 :     return -1;
     172             :   }
     173             : #else /* !(defined(FLAG_ZERO) || defined(FLAG_NOINHERIT)) */
     174             :   (void)inherit_result_out;
     175             :   (void)mem;
     176             :   (void)sz;
     177             :   return 0;
     178             : #endif /* defined(FLAG_ZERO) || defined(FLAG_NOINHERIT) */
     179             : }
     180             : 
     181             : /**
     182             :  * Return a new anonymous memory mapping that holds <b>sz</b> bytes.
     183             :  *
     184             :  * Memory mappings are unlike the results from malloc() in that they are
     185             :  * handled separately by the operating system, and as such can have different
     186             :  * kernel-level flags set on them.
     187             :  *
     188             :  * The "flags" argument may be zero or more of ANONMAP_PRIVATE and
     189             :  * ANONMAP_NOINHERIT.
     190             :  *
     191             :  * Memory returned from this function must be released with
     192             :  * tor_munmap_anonymous().
     193             :  *
     194             :  * If <b>inherit_result_out</b> is non-NULL, set it to one of
     195             :  * INHERIT_RES_KEEP, INHERIT_RES_DROP, or INHERIT_RES_ZERO, depending on the
     196             :  * properties of the returned memory.
     197             :  *
     198             :  * [Note: OS people use the word "anonymous" here to mean that the memory
     199             :  * isn't associated with any file. This has *nothing* to do with the kind of
     200             :  * anonymity that Tor is trying to provide.]
     201             :  */
     202             : void *
     203         174 : tor_mmap_anonymous(size_t sz, unsigned flags,
     204             :                    inherit_res_t *inherit_result_out)
     205             : {
     206         174 :   void *ptr;
     207         174 :   inherit_res_t itmp=0;
     208         174 :   if (inherit_result_out == NULL) {
     209           0 :     inherit_result_out = &itmp;
     210             :   }
     211         174 :   *inherit_result_out = INHERIT_RES_KEEP;
     212             : 
     213             : #if defined(_WIN32)
     214             :   HANDLE mapping = CreateFileMapping(INVALID_HANDLE_VALUE,
     215             :                                      NULL, /*attributes*/
     216             :                                      PAGE_READWRITE,
     217             :                                      HIGH_SIZE_T_BYTES(sz),
     218             :                                      sz & 0xffffffff,
     219             :                                      NULL /* name */);
     220             :   raw_assert(mapping != NULL);
     221             :   ptr = MapViewOfFile(mapping, FILE_MAP_WRITE,
     222             :                       0, 0, /* Offset */
     223             :                       0 /* Extend to end of mapping */);
     224             :   raw_assert(ptr);
     225             :   CloseHandle(mapping); /* mapped view holds a reference */
     226             : #elif defined(HAVE_SYS_MMAN_H)
     227         174 :   ptr = mmap(NULL, sz,
     228             :              PROT_READ|PROT_WRITE,
     229             :              MAP_ANON|MAP_PRIVATE,
     230             :              -1, 0);
     231         174 :   raw_assert(ptr != MAP_FAILED);
     232         174 :   raw_assert(ptr != NULL);
     233             : #else
     234             :   ptr = tor_malloc_zero(sz);
     235             : #endif /* defined(_WIN32) || ... */
     236             : 
     237         174 :   if (flags & ANONMAP_PRIVATE) {
     238         171 :     int lock_result = lock_mem(ptr, sz);
     239         171 :     raw_assert(lock_result == 0);
     240         171 :     int nodump_result = nodump_mem(ptr, sz);
     241         171 :     raw_assert(nodump_result == 0);
     242             :   }
     243             : 
     244         174 :   if (flags & ANONMAP_NOINHERIT) {
     245         172 :     int noinherit_result = noinherit_mem(ptr, sz, inherit_result_out);
     246         172 :     raw_assert(noinherit_result == 0);
     247             :   }
     248             : 
     249         174 :   return ptr;
     250             : }
     251             : 
     252             : /**
     253             :  * Release <b>sz</b> bytes of memory that were previously mapped at
     254             :  * <b>mapping</b> by tor_mmap_anonymous().
     255             :  **/
     256             : void
     257          32 : tor_munmap_anonymous(void *mapping, size_t sz)
     258             : {
     259          32 :   if (!mapping)
     260             :     return;
     261             : 
     262             : #if defined(_WIN32)
     263             :   (void)sz;
     264             :   UnmapViewOfFile(mapping);
     265             : #elif defined(HAVE_SYS_MMAN_H)
     266          31 :   munmap(mapping, sz);
     267             : #else
     268             :   (void)sz;
     269             :   tor_free(mapping);
     270             : #endif /* defined(_WIN32) || ... */
     271             : }

Generated by: LCOV version 1.14