LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - sel_ldr.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 4 4 100.0 %
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                 :  * NaCl Simple/secure ELF loader (NaCl SEL).
       9                 :  *
      10                 :  * This loader can only process NaCl object files as produced using
      11                 :  * the NaCl toolchain.  Other ELF files will be rejected.
      12                 :  *
      13                 :  * The primary function, NaClAppLoadFile, parses an ELF file,
      14                 :  * allocates memory, loads the relocatable image from the ELF file
      15                 :  * into memory, and performs relocation.  NaClAppRun runs the
      16                 :  * resultant program.
      17                 :  *
      18                 :  * This loader is written in C so that it can be used by C-only as
      19                 :  * well as C++ applications.  Other languages should also be able to
      20                 :  * use their foreign-function interfaces to invoke C code.
      21                 :  *
      22                 :  * This loader must be part of the NaCl TCB, since it directly handles
      23                 :  * externally supplied input (the ELF file).  Any security
      24                 :  * vulnerabilities in handling the ELF image, e.g., buffer or integer
      25                 :  * overflows, can put the application at risk.
      26                 :  */
      27                 : 
      28                 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_
      29                 : #define NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_ 1
      30                 : 
      31                 : #include "native_client/src/include/atomic_ops.h"
      32                 : #include "native_client/src/include/nacl_base.h"
      33                 : #include "native_client/src/include/portability.h"
      34                 : #include "native_client/src/include/elf.h"
      35                 : 
      36                 : #include "native_client/src/public/nacl_app.h"
      37                 : 
      38                 : #include "native_client/src/shared/platform/nacl_host_desc.h"
      39                 : #include "native_client/src/shared/platform/nacl_log.h"
      40                 : #include "native_client/src/shared/platform/nacl_threads.h"
      41                 : 
      42                 : #include "native_client/src/shared/srpc/nacl_srpc.h"
      43                 : 
      44                 : #include "native_client/src/trusted/interval_multiset/nacl_interval_multiset.h"
      45                 : #include "native_client/src/trusted/interval_multiset/nacl_interval_range_tree.h"
      46                 : 
      47                 : #include "native_client/src/trusted/service_runtime/dyn_array.h"
      48                 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
      49                 : #include "native_client/src/trusted/service_runtime/nacl_kernel_service.h"
      50                 : #include "native_client/src/trusted/service_runtime/nacl_resource.h"
      51                 : #include "native_client/src/trusted/service_runtime/nacl_secure_service.h"
      52                 : #include "native_client/src/trusted/service_runtime/name_service/name_service.h"
      53                 : #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
      54                 : #include "native_client/src/trusted/service_runtime/sel_mem.h"
      55                 : #include "native_client/src/trusted/service_runtime/sel_rt.h"
      56                 : #include "native_client/src/trusted/service_runtime/sel_util.h"
      57                 : #include "native_client/src/trusted/service_runtime/sys_futex.h"
      58                 : 
      59                 : #include "native_client/src/trusted/validator/ncvalidate.h"
      60                 : 
      61                 : EXTERN_C_BEGIN
      62                 : 
      63                 : #define NACL_SERVICE_PORT_DESCRIPTOR    3
      64                 : #define NACL_SERVICE_ADDRESS_DESCRIPTOR 4
      65                 : 
      66                 : #define NACL_DEFAULT_STACK_MAX  (16 << 20)  /* main thread stack */
      67                 : 
      68                 : struct NaClAppThread;
      69                 : struct NaClDesc;  /* see native_client/src/trusted/desc/nacl_desc_base.h */
      70                 : struct NaClDynamicRegion;
      71                 : struct NaClRuntimeHostInterface;
      72                 : struct NaClDescQuotaInterface;
      73                 : struct NaClSignalContext;
      74                 : struct NaClThreadInterface;  /* see sel_ldr_thread_interface.h */
      75                 : struct NaClValidationCache;
      76                 : struct NaClValidationMetadata;
      77                 : 
      78                 : struct NaClDebugCallbacks {
      79                 :   void (*thread_create_hook)(struct NaClAppThread *natp);
      80                 :   void (*thread_exit_hook)(struct NaClAppThread *natp);
      81                 :   void (*process_exit_hook)(void);
      82                 : };
      83                 : 
      84                 : enum NaClResourcePhase {
      85                 :   NACL_RESOURCE_PHASE_START,
      86                 :   NACL_RESOURCE_PHASE_RUNTIME_HOST
      87                 : };
      88                 : 
      89                 : #if NACL_WINDOWS
      90                 : enum NaClDebugExceptionHandlerState {
      91                 :   NACL_DEBUG_EXCEPTION_HANDLER_NOT_STARTED,
      92                 :   NACL_DEBUG_EXCEPTION_HANDLER_STARTED,
      93                 :   NACL_DEBUG_EXCEPTION_HANDLER_FAILED
      94                 : };
      95                 : /*
      96                 :  * Callback function used to request that an exception handler be
      97                 :  * attached using the Windows debug API.  See sel_main_chrome.h.
      98                 :  */
      99                 : typedef int (*NaClAttachDebugExceptionHandlerFunc)(const void *info,
     100                 :                                                    size_t size);
     101                 : #endif
     102                 : 
     103                 : struct NaClSpringboardInfo {
     104                 :   /* These are addresses in untrusted address space (relative to mem_start). */
     105                 :   uint32_t start_addr;
     106                 :   uint32_t end_addr;
     107                 : };
     108                 : 
     109                 : struct NaClApp {
     110                 :   /*
     111                 :    * public, user settable prior to app start.
     112                 :    */
     113                 :   uint8_t                   addr_bits;
     114                 :   uintptr_t                 stack_size;
     115                 :   uint32_t                  initial_nexe_max_code_bytes;
     116                 :   /*
     117                 :    * stack_size is the maximum size of the (main) stack.  The stack
     118                 :    * memory is eager allocated (mapped in w/o MAP_NORESERVE) so
     119                 :    * there must be enough swap space; page table entries are not
     120                 :    * populated (no MAP_POPULATE), so actual accesses will likely
     121                 :    * incur page faults.
     122                 :    */
     123                 : 
     124                 :   /*
     125                 :    * Determined at load time; OS-determined.
     126                 :    * Read-only after load, so accesses do not require locking.
     127                 :    */
     128                 :   uintptr_t                 mem_start;
     129                 : 
     130                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
     131                 :   uintptr_t                 pcrel_thunk;
     132                 :   uintptr_t                 pcrel_thunk_end;
     133                 : #endif
     134                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
     135                 :   uintptr_t                 nacl_syscall_addr;
     136                 :   uintptr_t                 get_tls_fast_path1_addr;
     137                 :   uintptr_t                 get_tls_fast_path2_addr;
     138                 : #endif
     139                 : 
     140                 :   /* only used for ET_EXEC:  for CS restriction */
     141                 :   uintptr_t                 static_text_end;
     142                 :   /*
     143                 :    * relative to mem_start; ro after app starts. memsz from phdr
     144                 :    */
     145                 : 
     146                 :   /*
     147                 :    * The dynamic code area follows the static code area.  These fields
     148                 :    * are both set to static_text_end if the dynamic code area has zero
     149                 :    * size.
     150                 :    */
     151                 :   uintptr_t                 dynamic_text_start;
     152                 :   uintptr_t                 dynamic_text_end;
     153                 : 
     154                 :   /*
     155                 :    * rodata_start and data_start may be 0 if these segments are not
     156                 :    * present in the executable.
     157                 :    */
     158                 :   uintptr_t                 rodata_start;  /* initialized data, ro */
     159                 :   uintptr_t                 data_start;    /* initialized data/bss, rw */
     160                 :   /*
     161                 :    * Various region sizes must be a multiple of NACL_MAP_PAGESIZE
     162                 :    * before the NaCl app can run.  The sizes from the ELF file
     163                 :    * (p_filesz field) might not be -- that would waste space for
     164                 :    * padding -- and while we could use p_memsz to specify padding, but
     165                 :    * we will record the virtual addresses of the start of the segments
     166                 :    * and figure out the gap between the p_vaddr + p_filesz of one
     167                 :    * segment and p_vaddr of the next to determine padding.
     168                 :    */
     169                 : 
     170                 :   uintptr_t                 data_end;
     171                 :   /* see break_addr below */
     172                 : 
     173                 :   /*
     174                 :    * initial_entry_pt is the first address in untrusted code to jump
     175                 :    * to.  When using the IRT (integrated runtime), this is provided by
     176                 :    * the IRT library, and user_entry_pt is the entry point in the user
     177                 :    * executable.  Otherwise, initial_entry_pt is in the user
     178                 :    * executable and user_entry_pt is zero.
     179                 :    */
     180                 :   uintptr_t                 initial_entry_pt;
     181                 :   uintptr_t                 user_entry_pt;
     182                 : 
     183                 :   /*
     184                 :    * bundle_size is the bundle alignment boundary for validation (16
     185                 :    * or 32), so int is okay.  This value must be a power of 2.
     186                 :    */
     187                 :   int                       bundle_size;
     188                 : 
     189                 :   /* common to both ELF executables and relocatable load images */
     190                 : 
     191                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
     192                 :   /* Addresses of trusted springboard code for switching to untrusted code. */
     193                 :   struct NaClSpringboardInfo syscall_return_springboard;
     194                 :   struct NaClSpringboardInfo all_regs_springboard;
     195                 : #endif
     196                 : 
     197                 :   /*
     198                 :    * The socket at which the app should be accepting connections.  The
     199                 :    * corresponding socket address are made available by the JavaScript
     200                 :    * bridge to other NaCl modules.
     201                 :    */
     202                 :   struct NaClDesc           *service_port;
     203                 :   struct NaClDesc           *service_address;
     204                 : 
     205                 :   struct NaClDesc           *secure_service_port;
     206                 :   struct NaClDesc           *secure_service_address;
     207                 : 
     208                 :   struct NaClDesc           *bootstrap_channel;
     209                 : 
     210                 :   /*
     211                 :    * The IRT may be supplied by an SRPC call via the command channel,
     212                 :    * or by the irt_fd member in struct NaClChromeMainArgs in the case
     213                 :    * of sel_main_chrome (the embedded service runtime), or by the -B
     214                 :    * command line argument in the case of sel_main (the standalone
     215                 :    * service runtime process).  We let the command channel have
     216                 :    * priority.
     217                 :    */
     218                 :   int irt_loaded;  /* bool */
     219                 : 
     220                 :   /*
     221                 :    * The main NaCl executable may already be validated during ELF
     222                 :    * loading, where after a validation cache hit the code gets mmapped
     223                 :    * into memory if the file descriptor is "blessed" as referring to a
     224                 :    * file which the embedding environment guarantees to be effectively
     225                 :    * immutable.  If it did not validate or the file descriptor is not
     226                 :    * blessed, then the code is read into memory, and we will validate
     227                 :    * it later in the code path, in NaClAppLoadFileAslr.
     228                 :    */
     229                 :   int main_exe_prevalidated;  /* bool */
     230                 : 
     231                 :   struct NaClMutex          mu;
     232                 :   struct NaClCondVar        cv;
     233                 : 
     234                 : #if NACL_WINDOWS
     235                 :   /*
     236                 :    * invariant: !(vm_hole_may_exist && threads_launching != 0).
     237                 :    * vm_hole_may_exist is set while mmap/munmap manipulates the memory
     238                 :    * map, and threads_launching is set while a thread is launching
     239                 :    * (and a trusted thread stack is being allocated).
     240                 :    *
     241                 :    * strictly speaking, vm_hole_may_exist need not be present, since
     242                 :    * the vm code ensures that 0 == threads_launching and then holds
     243                 :    * the lock for the duration of the VM operation.  it is safer this
     244                 :    * way, in case we later introduce code that might want to
     245                 :    * temporarily drop the process lock.
     246                 :    */
     247                 :   int                       vm_hole_may_exist;
     248                 :   int                       threads_launching;
     249                 : #endif
     250                 : 
     251                 :   /*
     252                 :    * An array of NaCl syscall handlers. The length of the array must be
     253                 :    * at least NACL_MAX_SYSCALLS.
     254                 :    */
     255                 :   struct NaClSyscallTableEntry *syscall_table;
     256                 : 
     257                 :   /*
     258                 :    * Name service must launch after mu, cv, vm_hole_may_exit,
     259                 :    * threads_launching are initialized.
     260                 :    */
     261                 :   struct NaClNameService    *name_service;  /* default name server */
     262                 :   struct NaClDesc           *name_service_conn_cap;
     263                 : 
     264                 :   struct NaClSecureService          *secure_service;
     265                 : 
     266                 :   struct NaClKernelService          *kernel_service;
     267                 : 
     268                 :   struct NaClResourceNaClApp        resources;
     269                 :   enum NaClResourcePhase            resource_phase;
     270                 : 
     271                 :   struct NaClRuntimeHostInterface   *runtime_host_interface;
     272                 :   struct NaClDescQuotaInterface     *desc_quota_interface;
     273                 : 
     274                 :   /*
     275                 :    * The ordering in this enum is important. We use the ordering
     276                 :    * to check that the status of module initialization; the state
     277                 :    * is really being used as a state machine. Please do not change
     278                 :    * the ordering, if you need to add a new state please do so at
     279                 :    * the appropriate position dependending on a module loading phase.
     280                 :    */
     281                 : 
     282                 :   enum NaClModuleInitializationState {
     283                 :     NACL_MODULE_UNINITIALIZED = 0,
     284                 :     NACL_MODULE_LOADING,
     285                 :     NACL_MODULE_LOADED,
     286                 :     NACL_MODULE_STARTING,
     287                 :     NACL_MODULE_STARTED,
     288                 :     NACL_MODULE_ERROR
     289                 :   }                                 module_initialization_state;
     290                 :   NaClErrorCode                     module_load_status;
     291                 : 
     292                 :   /*
     293                 :    * runtime info below, thread state, etc; initialized only when app
     294                 :    * is run.  Mutex mu protects access to mem_map and other member
     295                 :    * variables while the application is running and may be
     296                 :    * multithreaded; thread, desc members have their own locks.  At
     297                 :    * other times it is assumed that only one thread is
     298                 :    * constructing/loading the NaClApp and that no mutual exclusion is
     299                 :    * needed.
     300                 :    */
     301                 : 
     302                 :   /*
     303                 :    * memory map is in user addresses.
     304                 :    */
     305                 :   struct NaClVmmap          mem_map;
     306                 : 
     307                 :   struct NaClIntervalMultiset *mem_io_regions;
     308                 : 
     309                 :   /*
     310                 :    * This is the effector interface object that is used to manipulate
     311                 :    * NaCl apps by the objects in the NaClDesc class hierarchy.  This
     312                 :    * is used by this NaClApp when making NaClDesc method calls from
     313                 :    * syscall handlers.  Currently, this is when NaClDesc objects need
     314                 :    * to manipulate the untrusted address space -- the mmap
     315                 :    * implementation need to unmap the untrusted pages, and on Windows
     316                 :    * this requires different calls depending on how the pages were
     317                 :    * created.
     318                 :    */
     319                 :   struct NaClDescEffector   *effp;
     320                 : 
     321                 :   /*
     322                 :    * may reject nexes that are incompatible w/ dynamic-text in the near future
     323                 :    */
     324                 :   int                       enable_dyncode_syscalls;
     325                 :   int                       use_shm_for_dynamic_text;
     326                 :   struct NaClDesc           *text_shm;
     327                 :   struct NaClMutex          dynamic_load_mutex;
     328                 :   /*
     329                 :    * This records which pages in text_shm have been allocated.  When a
     330                 :    * page is allocated, it is filled with halt instructions and then
     331                 :    * made executable by untrusted code.
     332                 :    */
     333                 :   uint8_t                   *dynamic_page_bitmap;
     334                 : 
     335                 :   /*
     336                 :    * The array of dynamic_regions is maintained in sorted order
     337                 :    * Accesses must be protected by dynamic_load_mutex.
     338                 :    */
     339                 :   struct NaClDynamicRegion  *dynamic_regions;
     340                 :   int                       num_dynamic_regions;
     341                 :   int                       dynamic_regions_allocated;
     342                 : 
     343                 :   /*
     344                 :    * These variables are used for caching mapped writable views of the
     345                 :    * dynamic text segment.  See CachedMapWritableText in nacl_text.c.
     346                 :    * Accesses must be protected by dynamic_load_mutex
     347                 :    */
     348                 :   uint32_t                  dynamic_mapcache_offset;
     349                 :   uint32_t                  dynamic_mapcache_size;
     350                 :   uintptr_t                 dynamic_mapcache_ret;
     351                 : 
     352                 :   /*
     353                 :    * Monotonically increasing generation number used for deletion
     354                 :    * Accesses must be protected by dynamic_load_mutex
     355                 :    */
     356                 :   int                       dynamic_delete_generation;
     357                 : 
     358                 : 
     359                 :   int                       running;
     360                 :   int                       exit_status;
     361                 : 
     362                 :   NaClCPUFeatures           *cpu_features;
     363                 :   int                       fixed_feature_cpu_mode;
     364                 :   struct NaClValidationCache *validation_cache;
     365                 :   int                       ignore_validator_result;
     366                 :   int                       skip_validator;
     367                 :   int                       validator_stub_out_mode;
     368                 : 
     369                 :   int                       enable_list_mappings;
     370                 :   /* Whether or not the app is a PNaCl app.  Boolean. */
     371                 :   int                       pnacl_mode;
     372                 : 
     373                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
     374                 :   uint16_t                  code_seg_sel;
     375                 :   uint16_t                  data_seg_sel;
     376                 : #endif
     377                 : 
     378                 :   uintptr_t                 break_addr;   /* user addr */
     379                 :   /* data_end <= break_addr is an invariant */
     380                 : 
     381                 :   /*
     382                 :    * Thread table lock threads_mu is higher in the locking order than
     383                 :    * the thread locks, i.e., threads_mu must be acqured w/o holding
     384                 :    * any per-thread lock (natp->mu).
     385                 :    */
     386                 :   struct NaClMutex          threads_mu;
     387                 :   struct DynArray           threads;   /* NaClAppThread pointers */
     388                 :   int                       num_threads;  /* number actually running */
     389                 : 
     390                 :   struct NaClFastMutex      desc_mu;
     391                 :   struct DynArray           desc_tbl;  /* NaClDesc pointers */
     392                 : 
     393                 :   const struct NaClDebugCallbacks *debug_stub_callbacks;
     394                 : #if NACL_WINDOWS
     395                 :   uint16_t                        debug_stub_port;
     396                 : #endif
     397                 :   struct NaClDesc                 *main_nexe_desc;
     398                 :   struct NaClDesc                 *irt_nexe_desc;
     399                 : 
     400                 :   struct NaClMutex          exception_mu;
     401                 :   uint32_t                  exception_handler;
     402                 :   int                       enable_exception_handling;
     403                 : #if NACL_WINDOWS
     404                 :   enum NaClDebugExceptionHandlerState debug_exception_handler_state;
     405                 :   NaClAttachDebugExceptionHandlerFunc attach_debug_exception_handler_func;
     406                 : #endif
     407                 :   /*
     408                 :    * enable_faulted_thread_queue is a boolean which enables handling
     409                 :    * of untrusted faults which is used by the debug stub.  When an
     410                 :    * untrusted thread faults, it is blocked until
     411                 :    * NaClAppThreadUnblockIfFaulted() is called on the thread.
     412                 :    */
     413                 :   int                       enable_faulted_thread_queue;
     414                 :   /*
     415                 :    * faulted_thread_count is the number of NaClAppThreads for which
     416                 :    * fault_signal is non-zero.
     417                 :    */
     418                 :   Atomic32                  faulted_thread_count;
     419                 : #if NACL_WINDOWS
     420                 :   /*
     421                 :    * An event that is signaled by debug exception handler process when it fills
     422                 :    * fault_signal field with non-zero value for some NaClAppThread.
     423                 :    */
     424                 :   HANDLE                    faulted_thread_event;
     425                 : #else
     426                 :   /*
     427                 :    * A file descriptor of a pipe which becomes available for reading in
     428                 :    * the event that fault_signal for some NaClAppThread becomes non-zero.
     429                 :    */
     430                 :   int                       faulted_thread_fd_read;
     431                 :   int                       faulted_thread_fd_write;
     432                 : #endif
     433                 : 
     434                 :   /*
     435                 :    * Cache of sysconf(_SC_NPROCESSORS_ONLN) (or equivalent) result.
     436                 :    */
     437                 :   int sc_nprocessors_onln;
     438                 : 
     439                 :   const struct NaClValidatorInterface *validator;
     440                 : 
     441                 :   /*
     442                 :    * Mutex for protecting futex_wait_list_head.  Lock ordering:
     443                 :    * NaClApp::mu may be claimed after futex_wait_list_mu but never
     444                 :    * before it.
     445                 :    */
     446                 :   struct NaClMutex          futex_wait_list_mu;
     447                 :   /*
     448                 :    * This is the sentinel node for a doubly linked list of
     449                 :    * NaClAppThreads.  This lists the threads that are waiting to be
     450                 :    * woken up by futex_wake().  This list must only be accessed while
     451                 :    * holding the mutex futex_wait_list_mu.
     452                 :    */
     453                 :   struct NaClListNode       futex_wait_list_head;
     454                 : };
     455                 : 
     456                 : 
     457                 : 
     458                 : void  NaClAppIncrVerbosity(void);
     459                 : 
     460                 : /*
     461                 :  * Initializes a NaCl application with the default parameters
     462                 :  * and the specified syscall table.
     463                 :  *
     464                 :  * If invoked after the outer sandbox is enabled, the caller is
     465                 :  * responsible for initializing the sc_nprocessors_onln member to a
     466                 :  * sane value.
     467                 :  *
     468                 :  * nap is a pointer to the NaCl object that is being filled in.
     469                 :  *
     470                 :  * table is the NaCl syscall table. The syscall table must contain at least
     471                 :  * NACL_MAX_SYSCALLS valid entries.
     472                 :  *
     473                 :  * Caution! Syscall handlers must be extremely careful with respect to
     474                 :  * argument validation, including time-of-check vs time-of-use defense, etc.
     475                 :  */
     476                 : int NaClAppWithSyscallTableCtor(struct NaClApp               *nap,
     477                 :                                 struct NaClSyscallTableEntry *table) NACL_WUR;
     478                 : /*
     479                 :  * Standard Ctor for NaClApp objects.  Installs default syscall
     480                 :  * handlers.
     481                 :  *
     482                 :  * If invoked after the outer sandbox is enabled, the caller is
     483                 :  * responsible for initializing the sc_nprocessors_onln member to a
     484                 :  * sane value.
     485                 :  *
     486                 :  * nap is a pointer to the NaCl object that is being filled in.
     487                 :  */
     488                 : int NaClAppCtor(struct NaClApp  *nap) NACL_WUR;
     489                 : 
     490                 : /*
     491                 :  * Loads a NaCl ELF file into memory in preparation for running it.
     492                 :  *
     493                 :  * gp is a pointer to a generic I/O object and should be a GioMem with
     494                 :  * a memory buffer containing the file read entirely into memory if
     495                 :  * the file system might be subject to race conditions (e.g., another
     496                 :  * thread / process might modify a downloaded NaCl ELF file while we
     497                 :  * are loading it here).
     498                 :  *
     499                 :  * nap is a pointer to the NaCl object that is being filled in.  it
     500                 :  * should be properly constructed via NaClAppCtor.
     501                 :  *
     502                 :  * return value: one of the LOAD_* values defined in
     503                 :  * nacl_error_code.h.  TODO: add some error detail string and hang
     504                 :  * that off the nap object, so that more details are available w/o
     505                 :  * incrementing verbosity (and polluting stdout).
     506                 :  *
     507                 :  * note: it may be necessary to flush the icache if the memory
     508                 :  * allocated for use had already made it into the icache from another
     509                 :  * NaCl application instance, and the icache does not detect
     510                 :  * self-modifying code / data writes and automatically invalidate the
     511                 :  * cache lines.
     512                 :  */
     513                 : NaClErrorCode NaClAppLoadFile(struct NaClDesc *ndp,
     514                 :                               struct NaClApp *nap) NACL_WUR;
     515                 : 
     516                 : /*
     517                 :  * Just like NaClAppLoadFile, but allow control over ASLR.
     518                 :  */
     519                 : NaClErrorCode NaClAppLoadFileAslr(struct NaClDesc *ndp,
     520                 :                                   struct NaClApp *nap,
     521                 :                                   enum NaClAslrMode aslr_mode) NACL_WUR;
     522                 : 
     523                 : 
     524                 : NaClErrorCode NaClAppLoadFileDynamically(
     525                 :     struct NaClApp *nap,
     526                 :     struct NaClDesc *ndp,
     527                 :     struct NaClValidationMetadata *metadata) NACL_WUR;
     528                 : 
     529                 : void  NaClAppPrintDetails(struct NaClApp  *nap,
     530                 :                           struct Gio      *gp);
     531                 : 
     532                 : NaClErrorCode NaClLoadImage(struct Gio            *gp,
     533                 :                             struct NaClApp        *nap) NACL_WUR;
     534                 : 
     535                 : int NaClValidateCode(struct NaClApp *nap,
     536                 :                      uintptr_t      guest_addr,
     537                 :                      uint8_t        *data,
     538                 :                      size_t         size,
     539                 :                      const struct NaClValidationMetadata *metadata) NACL_WUR;
     540                 : 
     541                 : /*
     542                 :  * Validates that the code found at data_old can safely be replaced with
     543                 :  * the code found at data_new.
     544                 :  */
     545                 : int NaClValidateCodeReplacement(struct    NaClApp *nap,
     546                 :                                 uintptr_t guest_addr,
     547                 :                                 uint8_t   *data_old,
     548                 :                                 uint8_t   *data_new,
     549                 :                                 size_t    size);
     550                 : 
     551                 : /*
     552                 :  * Copies code from data_new to data_old in a thread-safe way.
     553                 :  */
     554                 : int NaClCopyCode(struct NaClApp *nap, uintptr_t guest_addr,
     555                 :                  uint8_t *data_old, uint8_t *data_new,
     556                 :                  size_t size);
     557                 : 
     558                 : /*
     559                 :  * Copies an instruction in a thread-safe way. Used by validators.
     560                 :  */
     561                 : int NaClCopyInstruction(uint8_t *dst, uint8_t *src, uint8_t sz);
     562                 : 
     563                 : NaClErrorCode NaClValidateImage(struct NaClApp  *nap) NACL_WUR;
     564                 : 
     565                 : 
     566                 : int NaClAddrIsValidEntryPt(struct NaClApp *nap,
     567                 :                            uintptr_t      addr);
     568                 : 
     569                 : /*
     570                 :  * Takes ownership of descriptor, i.e., when NaCl app closes, it's gone.
     571                 :  */
     572                 : void NaClAddHostDescriptor(struct NaClApp *nap,
     573                 :                            int            host_os_desc,
     574                 :                            int            mode,
     575                 :                            int            nacl_desc);
     576                 : 
     577                 : /*
     578                 :  * Takes ownership of handle.
     579                 :  */
     580                 : void NaClAddImcHandle(struct NaClApp  *nap,
     581                 :                       NaClHandle      h,
     582                 :                       int             nacl_desc);
     583                 : 
     584                 : /*
     585                 :  * Launch system-level service threads.  After this, access to the
     586                 :  * NaClApp object must be done in a thread-safe manner, using nap->mu
     587                 :  * etc, or access only read-only data.
     588                 :  *
     589                 :  * NB: the "secure command channel" thread should have already started
     590                 :  * (if enabled); that thread must take care to not race with the main
     591                 :  * thread that is continuing to set up the NaCl module as well.
     592                 :  */
     593                 : int NaClAppLaunchServiceThreads(struct NaClApp *nap);
     594                 : 
     595                 : /*
     596                 :  * Report the low eight bits of |exit_status| via the reverse channel
     597                 :  * in |nap|, if one exists, to whomever is interested.  This usually
     598                 :  * involves an RPC.  Returns true if successfully reported.
     599                 :  *
     600                 :  * Also mark nap's exit_status and running member variables, announce
     601                 :  * via condvar that the nexe should be considered no longer running.
     602                 :  *
     603                 :  * Returns true (non-zero) if exit status was reported via the reverse
     604                 :  * channel, and false (0) otherwise.
     605                 :  */
     606                 : int NaClReportExitStatus(struct NaClApp *nap, int exit_status);
     607                 : 
     608                 : /*
     609                 :  * Get the top of the initial thread's stack.  Returns a user address.
     610                 :  */
     611                 : uintptr_t NaClGetInitialStackTop(struct NaClApp *nap);
     612                 : 
     613                 : /*
     614                 :  * Used to launch the main thread.  NB: calling thread may in the
     615                 :  * future become the main NaCl app thread, and this function will
     616                 :  * return only after the NaCl app main thread exits.  In such an
     617                 :  * alternative design, NaClWaitForMainThreadToExit will become a
     618                 :  * no-op.
     619                 :  */
     620                 : int NaClCreateMainThread(struct NaClApp     *nap,
     621                 :                          int                argc,
     622                 :                          char               **argv,
     623                 :                          char const *const  *envp) NACL_WUR;
     624                 : 
     625                 : int NaClWaitForMainThreadToExit(struct NaClApp  *nap);
     626                 : 
     627                 : /*
     628                 :  * Used by syscall code.
     629                 :  */
     630                 : int32_t NaClCreateAdditionalThread(struct NaClApp *nap,
     631                 :                                    uintptr_t      prog_ctr,
     632                 :                                    uintptr_t      stack_ptr,
     633                 :                                    uint32_t       user_tls1,
     634                 :                                    uint32_t       user_tls2) NACL_WUR;
     635                 : 
     636                 : void NaClLoadTrampoline(struct NaClApp *nap, enum NaClAslrMode aslr_mode);
     637                 : 
     638                 : void NaClLoadSpringboard(struct NaClApp  *nap);
     639                 : 
     640                 : static const uintptr_t kNaClBadAddress = (uintptr_t) -1;
     641                 : 
     642                 : #include "native_client/src/trusted/service_runtime/sel_ldr-inl.h"
     643                 : 
     644                 : /*
     645                 :  * Looks up a descriptor in the open-file table.  An additional
     646                 :  * reference is taken on the returned NaClDesc object (if non-NULL).
     647                 :  * The caller is responsible for invoking NaClDescUnref() on it when
     648                 :  * done.
     649                 :  */
     650                 : struct NaClDesc *NaClAppGetDesc(struct NaClApp *nap,
     651                 :                                 int            d);
     652                 : 
     653                 : /* NaClAppSetDesc() is defined in src/public/chrome_main.h. */
     654                 : 
     655                 : int32_t NaClAppSetDescAvail(struct NaClApp   *nap,
     656                 :                             struct NaClDesc  *ndp);
     657                 : 
     658                 : /*
     659                 :  * Versions that are called while already holding the desc_mu lock
     660                 :  */
     661                 : struct NaClDesc *NaClAppGetDescMu(struct NaClApp *nap,
     662                 :                                   int            d);
     663                 : 
     664                 : void NaClAppSetDescMu(struct NaClApp   *nap,
     665                 :                       int              d,
     666                 :                       struct NaClDesc  *ndp);
     667                 : 
     668                 : int32_t NaClAppSetDescAvailMu(struct NaClApp   *nap,
     669                 :                               struct NaClDesc  *ndp);
     670                 : 
     671                 : 
     672                 : int NaClAddThread(struct NaClApp        *nap,
     673                 :                   struct NaClAppThread  *natp);
     674                 : 
     675                 : int NaClAddThreadMu(struct NaClApp        *nap,
     676                 :                     struct NaClAppThread  *natp);
     677                 : 
     678                 : void NaClRemoveThread(struct NaClApp  *nap,
     679                 :                       int             thread_num);
     680                 : 
     681                 : void NaClRemoveThreadMu(struct NaClApp  *nap,
     682                 :                         int             thread_num);
     683                 : 
     684                 : struct NaClAppThread *NaClGetThreadMu(struct NaClApp  *nap,
     685                 :                                       int             thread_num);
     686                 : 
     687                 : void NaClAppInitialDescriptorHookup(struct NaClApp  *nap);
     688                 : 
     689                 : void NaClCreateServiceSocket(struct NaClApp *nap);
     690                 : 
     691                 : void NaClSetUpBootstrapChannel(struct NaClApp  *nap,
     692                 :                                NaClHandle      inherited_desc);
     693                 : 
     694                 : void NaClSecureCommandChannel(struct NaClApp  *nap);
     695                 : 
     696                 : /*
     697                 :  * Loads the |nexe| as a NaCl app module.
     698                 :  * The |load_cb| callback is invoked before the the |nexe| is loaded to allow
     699                 :  * validation being run in parallel.
     700                 :  */
     701                 : void NaClAppLoadModule(struct NaClApp      *self,
     702                 :                        struct NaClDesc     *nexe,
     703                 :                        void                (*load_cb)(void *instance_data,
     704                 :                                                       NaClErrorCode status),
     705                 :                        void                *instance_data);
     706                 : 
     707                 : int NaClAppRuntimeHostSetup(struct NaClApp                  *self,
     708                 :                             struct NaClRuntimeHostInterface *host_itf);
     709                 : 
     710                 : int NaClAppDescQuotaSetup(struct NaClApp                *self,
     711                 :                           struct NaClDescQuotaInterface *rev_quota);
     712                 : 
     713                 : /*
     714                 :  * Starts the NaCl app, the |start_cb| callback is invoked before the
     715                 :  * application is actually started.
     716                 :  */
     717                 : void NaClAppStartModule(struct NaClApp  *self,
     718                 :                         void            (*start_cb)(void *instance_data,
     719                 :                                                     NaClErrorCode status),
     720                 :                         void            *instance_data);
     721                 : 
     722                 : void NaClAppShutdown(struct NaClApp     *self,
     723                 :                      int                exit_status);
     724                 : 
     725                 : NaClErrorCode NaClWaitForLoadModuleCommand(struct NaClApp *nap) NACL_WUR;
     726                 : 
     727                 : NaClErrorCode NaClWaitForLoadModuleStatus(struct NaClApp *nap) NACL_WUR;
     728                 : 
     729                 : NaClErrorCode NaClWaitForStartModuleCommand(struct NaClApp *nap) NACL_WUR;
     730                 : 
     731                 : /*
     732                 :  * NaClBlockIfCommandChannelExists is used during error exit.  If
     733                 :  * there is a secure command channel, we sent an RPC reply with the
     734                 :  * reason that the nexe was rejected.  If we exit immediately, that
     735                 :  * reply may still be in-flight and the various channel closure (esp
     736                 :  * reverse channels, if those were set up) may be detected first by
     737                 :  * the controlling process on the other end of the command channel or
     738                 :  * reverse channel.  When channel closure wins the race against the
     739                 :  * RPC reply, it would result in a crash being reported, rather than
     740                 :  * the error code carried in the RPC reply.  We want to ensure that
     741                 :  * the RPC reply to get processed.  Instead of allowing the service
     742                 :  * runtime process to exit, we block the main thread and wait for the
     743                 :  * hard-shutdown on the command channel or command channel closure.
     744                 :  *
     745                 :  * If there is no command channel, NaClBlockIfCommandChannelExists
     746                 :  * just returns immediately.
     747                 :  */
     748                 : void NaClBlockIfCommandChannelExists(struct NaClApp *nap);
     749                 : 
     750                 : void NaClFillMemoryRegionWithHalt(void *start, size_t size);
     751                 : 
     752                 : void NaClFillTrampolineRegion(struct NaClApp *nap);
     753                 : 
     754                 : void NaClFillEndOfTextRegion(struct NaClApp *nap);
     755                 : 
     756                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
     757                 : 
     758                 : int NaClMakePcrelThunk(struct NaClApp *nap, enum NaClAslrMode aslr_mode);
     759                 : 
     760                 : #endif
     761                 : 
     762                 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
     763                 : 
     764                 : int NaClMakeDispatchAddrs(struct NaClApp *nap);
     765                 : 
     766                 : void NaClPatchOneTrampolineCall(uintptr_t call_target_addr,
     767                 :                                 uintptr_t target_addr);
     768                 : 
     769                 : #endif
     770                 : 
     771                 : void NaClPatchOneTrampoline(struct NaClApp *nap,
     772                 :                             uintptr_t target_addr);
     773                 : /*
     774                 :  * target is an absolute address in the source region.  the patch code
     775                 :  * will figure out the corresponding address in the destination region
     776                 :  * and modify as appropriate.  this makes it easier to specify, since
     777                 :  * the target is typically the address of some symbol from the source
     778                 :  * template.
     779                 :  */
     780                 : struct NaClPatch {
     781                 :   uintptr_t           target;
     782                 :   uint64_t            value;
     783                 : };
     784                 : 
     785                 : struct NaClPatchInfo {
     786                 :   uintptr_t           dst;
     787                 :   uintptr_t           src;
     788                 :   size_t              nbytes;
     789                 : 
     790                 :   struct NaClPatch    *abs16;
     791                 :   size_t              num_abs16;
     792                 : 
     793                 :   struct NaClPatch    *abs32;
     794                 :   size_t              num_abs32;
     795                 : 
     796                 :   struct NaClPatch    *abs64;
     797                 :   size_t              num_abs64;
     798                 : 
     799                 : #if NACL_TARGET_SUBARCH == 32
     800                 :   uintptr_t           *rel32;
     801                 :   size_t              num_rel32;
     802                 : #endif
     803                 : 
     804                 :   uintptr_t           *rel64;
     805                 :   size_t              num_rel64;
     806                 : };
     807                 : 
     808                 : struct NaClPatchInfo *NaClPatchInfoCtor(struct NaClPatchInfo *self);
     809                 : 
     810                 : void NaClApplyPatchToMemory(struct NaClPatchInfo *patch);
     811                 : 
     812                 : int NaClAppThreadInitArchSpecific(struct NaClAppThread *natp,
     813                 :                                   nacl_reg_t           prog_ctr,
     814                 :                                   nacl_reg_t           stack_ptr);
     815                 : 
     816                 : void NaClVmHoleWaitToStartThread(struct NaClApp *nap);
     817                 : 
     818                 : void NaClVmHoleThreadStackIsSafe(struct NaClApp *nap);
     819                 : 
     820                 : void NaClVmHoleOpeningMu(struct NaClApp *nap);
     821                 : 
     822                 : void NaClVmHoleClosingMu(struct NaClApp *nap);
     823                 : 
     824                 : /*
     825                 :  * More VM race detection.  In Windows, when we unmap or mmap over
     826                 :  * existing memory, we cannot maintain the address space reservation
     827                 :  * -- we have to unmap the original mapping with the appropriate
     828                 :  * unmapping function (VirtualFree or UnmapViewOfFile) before we can
     829                 :  * VirtualAlloc to reserve the addresss pace, leaving a timing window
     830                 :  * where another thread (possibly injected into the binary, e.g.,
     831                 :  * antivirus code) might map something else into.  We stop user-space
     832                 :  * threads when mmap/munmap occurs and detect if the temporary VM hole
     833                 :  * was filled by some other thread (and abort the process in that
     834                 :  * case), so that untrusted code cannot observe nor modify the memory
     835                 :  * that lands in the hole.  However, we still have the case where the
     836                 :  * untrusted code's threads aren't running user-space code -- a thread
     837                 :  * may have entered into a syscall handler.  We don't stop such
     838                 :  * threads, because they might be holding locks that the memory
     839                 :  * mapping functions need.  This means that, for example, a malicious
     840                 :  * application could -- assuming it could create the innocent thread
     841                 :  * race condition -- have one thread invoke the "write" NaCl syscall,
     842                 :  * enter into the host OS "write" syscall code in the NaCl syscall
     843                 :  * handler, then have another thread mmap (or munmap) the memory where
     844                 :  * the source memory region from which the content to be written
     845                 :  * resides, and as a side effect of this race, exfiltrate memory
     846                 :  * contents that NaCl modules aren't supposed to be able to access.
     847                 :  *
     848                 :  * NB: we do not try to prevent data races such as two "read" syscalls
     849                 :  * simultaneously trying to write the same memory region, or
     850                 :  * concurrent "read" and "write" syscalls racing on the same memory
     851                 :  * region..
     852                 :  */
     853                 : 
     854                 : /*
     855                 :  * Some potentially blocking I/O operation is about to start.  Syscall
     856                 :  * handlers implement DMA-style access where the host-OS syscalls
     857                 :  * directly read/write untrusted memory, so we must record the
     858                 :  * affected memory ranges as "in use" by I/O operations.
     859                 :  */
     860                 : void NaClVmIoWillStart(struct NaClApp *nap,
     861                 :                        uint32_t addr_first_usr,
     862                 :                        uint32_t addr_last_usr);
     863                 : 
     864                 : 
     865                 : /*
     866                 :  * It is a fatal error to have an invocation of NaClVmIoHasEnded whose
     867                 :  * arguments do not match those of an earlier, unmatched invocation of
     868                 :  * NaClVmIoWillStart.
     869                 :  */
     870                 : void NaClVmIoHasEnded(struct NaClApp *nap,
     871                 :                       uint32_t addr_first_usr,
     872                 :                       uint32_t addr_last_usr);
     873                 : 
     874                 : /*
     875                 :  * Used by operations (mmap, munmap) that will open a VM hole.
     876                 :  * Invoked while holding the VM lock.  Check that no I/O is pending;
     877                 :  * abort the app if the app is racing I/O operations against VM
     878                 :  * operations.
     879                 :  */
     880                 : void NaClVmIoPendingCheck_mu(struct NaClApp *nap,
     881                 :                              uint32_t addr_first_usr,
     882                 :                              uint32_t addr_last_usr);
     883                 : 
     884                 : void NaClGdbHook(struct NaClApp const *nap);
     885                 : 
     886                 : #if NACL_LINUX
     887                 : void NaClHandleBootstrapArgs(int *argc_p, char ***argv_p);
     888                 : void NaClHandleRDebug(const char *switch_value, char *argv0);
     889                 : void NaClHandleReservedAtZero(const char *switch_value);
     890                 : #else
     891               1 : static INLINE void NaClHandleBootstrapArgs(int *argc_p, char ***argv_p) {
     892               2 :   UNREFERENCED_PARAMETER(argc_p);
     893               2 :   UNREFERENCED_PARAMETER(argv_p);
     894               1 : }
     895                 : #endif
     896                 : 
     897                 : EXTERN_C_END
     898                 : 
     899                 : #endif  /* NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_ */

Generated by: LCOV version 1.7