LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - sel_ldr-inl.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 64 59 92.2 %
Date: 2014-06-18 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*******************************************************************************
       8                 :  *
       9                 :  * DO NOT INCLUDE EXCEPT FROM sel_ldr.h
      10                 :  *
      11                 :  ******************************************************************************/
      12                 : 
      13                 : /*
      14                 :  * Routines to translate addresses between user and "system" or
      15                 :  * service runtime addresses.  the *Addr* versions will return
      16                 :  * kNaClBadAddress if the user address is outside of the user address
      17                 :  * space, e.g., if the input addresses for *UserToSys* is outside of
      18                 :  * (1<<nap->addr_bits), and correspondingly for *SysToUser* if the
      19                 :  * input system address does not correspond to a user address.
      20                 :  * Generally, the *Addr* versions are used when the addresses come
      21                 :  * from untrusted usre code, and kNaClBadAddress would translate to an
      22                 :  * EINVAL return from a syscall.  The *Range code ensures that the
      23                 :  * entire address range is in the user address space.
      24                 :  *
      25                 :  * Note that just because an address is within the address space, it
      26                 :  * doesn't mean that it is safe to acceess the memory: the page may be
      27                 :  * protected against access.
      28                 :  *
      29                 :  * The non-*Addr* versions abort the program rather than return an
      30                 :  * error indication.
      31                 :  */
      32                 : 
      33                 : /*
      34                 :  * address translation routines.  after a NaClApp is started, the
      35                 :  * member variables accessed by these routines are read-only, so no
      36                 :  * locking is needed to use these functions, as long as the NaClApp
      37                 :  * structure doesn't get destructed/deallocated.
      38                 :  *
      39                 :  * the first is used internally when a NULL pointer is okay, typically
      40                 :  * for address manipulation.
      41                 :  *
      42                 :  * the next two are for syscalls to do address translation, e.g., for
      43                 :  * system calls; -1 indicates an error, so the syscall can return
      44                 :  * EINVAL or EFAULT or whatever is appropriate.
      45                 :  *
      46                 :  * the latter two interfaces are for use everywhere else in the loader
      47                 :  * / service runtime and will log a fatal error and abort the process
      48                 :  * when an error is detected.  (0 is not a good error indicator, since
      49                 :  * 0 is a valid user address.)
      50                 :  */
      51                 : 
      52                 : #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
      53                 : 
      54              38 : static INLINE uintptr_t NaClUserToSysAddrNullOkay(struct NaClApp  *nap,
      55              38 :                                                   uintptr_t       uaddr) {
      56              38 :   if (((uintptr_t) 1U << nap->addr_bits <= uaddr)) {
      57               0 :     return kNaClBadAddress;
      58                 :   }
      59              38 :   return uaddr + nap->mem_start;
      60              38 : }
      61                 : 
      62           21648 : static INLINE uintptr_t NaClUserToSysAddr(struct NaClApp  *nap,
      63           21648 :                                           uintptr_t       uaddr) {
      64           43282 :   if (0 == uaddr || ((uintptr_t) 1U << nap->addr_bits) <= uaddr) {
      65              14 :     return kNaClBadAddress;
      66                 :   }
      67           21634 :   return uaddr + nap->mem_start;
      68           21648 : }
      69                 : 
      70           57006 : static INLINE int NaClIsUserAddr(struct NaClApp  *nap,
      71           57006 :                                  uintptr_t       sysaddr) {
      72                 :   /*
      73                 :    * Note that NaClIsUserAddr() is used in the Windows debug exception
      74                 :    * handler so must remain safe to use on a copy of NaClApp.
      75                 :    */
      76          110602 :   return nap->mem_start <= sysaddr &&
      77                 :          sysaddr < nap->mem_start + ((uintptr_t) 1U << nap->addr_bits);
      78           57006 : }
      79                 : 
      80         3072626 : static INLINE uintptr_t NaClUserToSysAddrRange(struct NaClApp  *nap,
      81         3072626 :                                                uintptr_t       uaddr,
      82         3072626 :                                                size_t          count) {
      83         3072626 :   uintptr_t end_addr;
      84                 : 
      85         3072626 :   if (0 == uaddr) {
      86               3 :     return kNaClBadAddress;
      87                 :   }
      88         3072623 :   end_addr = uaddr + count;
      89         3072623 :   if (end_addr < uaddr) {
      90                 :     /* unsigned wraparound */
      91               1 :     return kNaClBadAddress;
      92                 :   }
      93         3072622 :   if (((uintptr_t) 1U << nap->addr_bits) < end_addr) {
      94               7 :     return kNaClBadAddress;
      95                 :   }
      96         3072614 :   return uaddr + nap->mem_start;
      97         3072625 : }
      98                 : 
      99          118825 : static INLINE uintptr_t NaClUserToSys(struct NaClApp  *nap,
     100          118825 :                                       uintptr_t       uaddr) {
     101          237650 :   if (0 == uaddr || ((uintptr_t) 1U << nap->addr_bits) <= uaddr) {
     102               0 :     NaClLog(LOG_FATAL,
     103                 :             "NaClUserToSys: uaddr 0x%08" NACL_PRIxPTR ", "
     104                 :             "addr space %" NACL_PRId8 " bits\n",
     105                 :             uaddr, nap->addr_bits);
     106               0 :   }
     107          118825 :   return uaddr + nap->mem_start;
     108                 : }
     109                 : 
     110          142086 : static INLINE uintptr_t NaClSysToUser(struct NaClApp  *nap,
     111          142086 :                                       uintptr_t       sysaddr) {
     112          284172 :   if (sysaddr < nap->mem_start ||
     113                 :       nap->mem_start + ((uintptr_t) 1U << nap->addr_bits) <= sysaddr) {
     114               0 :     NaClLog(LOG_FATAL,
     115                 :             ("NaClSysToUser: sysaddr 0x%08" NACL_PRIxPTR ","
     116                 :              " mem_start 0x%08" NACL_PRIxPTR ","
     117                 :              " addr space %" NACL_PRId8 " bits\n"),
     118                 :             sysaddr, nap->mem_start, nap->addr_bits);
     119               0 :   }
     120          142086 :   return sysaddr - nap->mem_start;
     121                 : }
     122                 : 
     123                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
     124                 : /*
     125                 :  * For x86-64 sandboxing, %rsp and %rbp are system addresses already.
     126                 :  */
     127         3538671 : static INLINE uintptr_t NaClUserToSysStackAddr(struct NaClApp *nap,
     128         3538671 :                                                uintptr_t      stackaddr) {
     129         7077342 :   UNREFERENCED_PARAMETER(nap);
     130         3538671 :   return stackaddr;
     131                 : }
     132                 : 
     133           21151 : static INLINE uintptr_t NaClSysToUserStackAddr(struct NaClApp *nap,
     134           21151 :                                                uintptr_t      stackaddr) {
     135           42302 :   UNREFERENCED_PARAMETER(nap);
     136           21151 :   return stackaddr;
     137                 : }
     138                 : 
     139                 : #else
     140                 : 
     141                 : static INLINE uintptr_t NaClUserToSysStackAddr(struct NaClApp *nap,
     142                 :                                                uintptr_t      stackaddr) {
     143                 :   return NaClUserToSys(nap, stackaddr);
     144                 : }
     145                 : 
     146                 : static INLINE uintptr_t NaClSysToUserStackAddr(struct NaClApp *nap,
     147                 :                                                uintptr_t      stackaddr) {
     148                 :   return NaClSysToUser(nap, stackaddr);
     149                 : }
     150                 : 
     151                 : #endif
     152                 : 
     153                 : /*
     154                 :  * Normalize a user address space address.  This function is really a
     155                 :  * no-op for 32-bit sandboxes, but for x86-64 where rsp contains a
     156                 :  * true 64-bit address, we must discard the high 32 bits to make the
     157                 :  * stack address a proper user-space address.  After normalization,
     158                 :  * the address can be used with NaClUserToSys etc.
     159                 :  */
     160         3538673 : static INLINE uint32_t NaClRawUserStackAddrNormalize(uintptr_t  stack_addr) {
     161         3538673 :   return (uint32_t) stack_addr;
     162                 : }
     163                 : 
     164             553 : static INLINE uintptr_t NaClEndOfStaticText(struct NaClApp *nap) {
     165             553 :   return nap->static_text_end;
     166                 : }
     167                 : 
     168         3544424 : static INLINE uintptr_t NaClSandboxCodeAddr(struct NaClApp *nap,
     169         3544424 :                                             uintptr_t addr) {
     170                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
     171                 :   /*
     172                 :    * If misaligned, round up to the following bundle boundary.
     173                 :    * With the original nacl-gcc toolchain, a return address is
     174                 :    * always on a bundle boundary, so this is always a no-op and
     175                 :    * the ABI specification was that a misaligned return address
     176                 :    * has undefined results.  With the next-generation gcc
     177                 :    * toolchain, a return address on the stack may be mid-bundle
     178                 :    * and the ABI specification is that the real address to use is
     179                 :    * found by rounding up to the following bundle.
     180                 :    */
     181         3544424 :   addr += (uintptr_t) nap->bundle_size - 1;
     182         3544424 :   addr &= ~((uintptr_t) nap->bundle_size - 1);
     183                 : # if NACL_BUILD_SUBARCH == 32
     184                 :   return addr;
     185                 : # elif NACL_BUILD_SUBARCH == 64
     186         3544424 :   return nap->mem_start + (uint32_t) addr;
     187                 : # else
     188                 : #  error "What kind of x86 are we on anyway?!?"
     189                 : # endif
     190                 : #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
     191                 :   UNREFERENCED_PARAMETER(nap);
     192                 :   addr &= ~NACL_CONTROL_FLOW_MASK;
     193                 :   return addr;
     194                 : #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
     195                 :   UNREFERENCED_PARAMETER(nap);
     196                 :   return addr & NACL_CONTROL_FLOW_MASK;
     197                 : #else
     198                 : # error "What architecture are we on?!?"
     199                 : #endif
     200                 : }
     201                 : 
     202           20774 : static INLINE int NaClIsValidJumpTarget(struct NaClApp *nap,
     203           20774 :                                         uintptr_t addr) {
     204           20774 :   if (0 != (addr & (((uintptr_t) nap->bundle_size) - 1))) {
     205               3 :     return 0;
     206                 :   }
     207           20771 :   return addr < nap->dynamic_text_end;
     208           20774 : }

Generated by: LCOV version 1.7