LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - nacl_syscall_hook.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 43 39 90.7 %
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 service run-time.
       9                 :  */
      10                 : 
      11                 : #include "native_client/src/include/portability.h"
      12                 : 
      13                 : #include <errno.h>
      14                 : #include <stdio.h>
      15                 : #include <stdlib.h>
      16                 : #include <time.h>
      17                 : 
      18                 : #include "native_client/src/include/nacl_compiler_annotations.h"
      19                 : #include "native_client/src/shared/platform/nacl_exit.h"
      20                 : #include "native_client/src/shared/platform/nacl_log.h"
      21                 : #include "native_client/src/trusted/service_runtime/nacl_globals.h"
      22                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      23                 : #include "native_client/src/trusted/service_runtime/nacl_copy.h"
      24                 : #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h"
      25                 : #include "native_client/src/trusted/service_runtime/nacl_syscall_handlers.h"
      26                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      27                 : #include "native_client/src/trusted/service_runtime/sel_rt.h"
      28                 : 
      29                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      30                 : #include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h"
      31                 : #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
      32                 : #include "native_client/src/trusted/service_runtime/nacl_stack_safety.h"
      33                 : 
      34                 : 
      35                 : /*
      36                 :  * HandleStackContext() fetches some of the inputs to the NaCl syscall
      37                 :  * from the untrusted stack.  It updates NaClThreadContext so that the
      38                 :  * saved state will be complete in case this state is read via the
      39                 :  * thread suspension API.
      40                 :  *
      41                 :  * This is called while natp->suspend_state is set to
      42                 :  * NACL_APP_THREAD_UNTRUSTED, which has two consequences:
      43                 :  *
      44                 :  *  1) We may read untrusted address space without calling
      45                 :  *     NaClCopyTakeLock() first, because this function's execution
      46                 :  *     will be suspended while any mmap hole is opened up on Windows.
      47                 :  *
      48                 :  *  2) We may not claim any locks.  This means we may not call
      49                 :  *     NaClLog().  (An exception is that LOG_FATAL calls to NaClLog()
      50                 :  *     should be okay for internal errors.)
      51                 :  */
      52         3538668 : static void HandleStackContext(struct NaClAppThread *natp,
      53         3538668 :                                uint32_t             *tramp_ret_out,
      54         3538668 :                                uintptr_t            *sp_user_out) {
      55         3538668 :   struct NaClApp *nap = natp->nap;
      56         3538668 :   uintptr_t      sp_user;
      57         3538668 :   uintptr_t      sp_sys;
      58         3538668 :   uint32_t       tramp_ret;
      59         3538668 :   nacl_reg_t     user_ret;
      60                 : 
      61                 :   /*
      62                 :    * sp_sys points to the top of the user stack where return addresses
      63                 :    * and syscall arguments are stored.
      64                 :    *
      65                 :    * Note that on x86-64, NaClUserToSysStackAddr() and
      66                 :    * NaClSysToUserStackAddr() do no range check.  sp_user must be okay
      67                 :    * for control to have reached here, because nacl_syscall*.S writes
      68                 :    * to the stack.
      69                 :    */
      70         3538668 :   sp_user = NaClGetThreadCtxSp(&natp->user);
      71         3538668 :   sp_sys = NaClUserToSysStackAddr(nap, sp_user);
      72                 :   /*
      73                 :    * Get the trampoline return address.  This just tells us which
      74                 :    * trampoline was called (and hence the syscall number); we never
      75                 :    * return to the trampoline.
      76                 :    */
      77         3538668 :   tramp_ret = *(volatile uint32_t *) (sp_sys + NACL_TRAMPRET_FIX);
      78                 :   /*
      79                 :    * Get the user return address (where we return to after the system
      80                 :    * call).  We must ensure the address is properly sandboxed before
      81                 :    * switching back to untrusted code.
      82                 :    */
      83         3538668 :   user_ret = *(volatile uintptr_t *) (sp_sys + NACL_USERRET_FIX);
      84         3538668 :   user_ret = (nacl_reg_t) NaClSandboxCodeAddr(nap, (uintptr_t) user_ret);
      85         3538668 :   natp->user.new_prog_ctr = user_ret;
      86                 : 
      87         3538668 :   *tramp_ret_out = tramp_ret;
      88         3538668 :   *sp_user_out = sp_user;
      89         3538668 : }
      90                 : 
      91         3538669 : struct NaClThreadContext *NaClSyscallCSegHook(struct NaClThreadContext *ntcp) {
      92         3538669 :   struct NaClAppThread      *natp = NaClAppThreadFromThreadContext(ntcp);
      93         3538669 :   struct NaClApp            *nap;
      94         3538669 :   uint32_t                  tramp_ret;
      95         3538669 :   size_t                    sysnum;
      96         3538669 :   uintptr_t                 sp_user;
      97         3538669 :   uint32_t                  sysret;
      98                 : 
      99                 :   /*
     100                 :    * Mark the thread as running on a trusted stack as soon as possible
     101                 :    * so that we can report any crashes that occur after this point.
     102                 :    */
     103         3538669 :   NaClStackSafetyNowOnTrustedStack();
     104                 : 
     105         3538669 :   HandleStackContext(natp, &tramp_ret, &sp_user);
     106                 : 
     107                 :   /*
     108                 :    * Before this call, the thread could be suspended, so we should not
     109                 :    * lock any mutexes before this, otherwise it could cause a
     110                 :    * deadlock.
     111                 :    */
     112         3538669 :   NaClAppThreadSetSuspendState(natp, NACL_APP_THREAD_UNTRUSTED,
     113                 :                                NACL_APP_THREAD_TRUSTED);
     114                 : 
     115         3538669 :   nap = natp->nap;
     116                 : 
     117         3538669 :   NaClCopyTakeLock(nap);
     118                 :   /*
     119                 :    * held until syscall args are copied, which occurs in the generated
     120                 :    * code.
     121                 :    */
     122                 : 
     123         3538669 :   sysnum = (tramp_ret - NACL_SYSCALL_START_ADDR) >> NACL_SYSCALL_BLOCK_SHIFT;
     124                 : 
     125         3538669 :   NaClLog(4, "Entering syscall %"NACL_PRIuS
     126                 :           ": return address 0x%08"NACL_PRIxNACL_REG"\n",
     127                 :           sysnum, natp->user.new_prog_ctr);
     128                 : 
     129                 :   /*
     130                 :    * usr_syscall_args is used by Decoder functions in
     131                 :    * nacl_syscall_handlers.c which is automatically generated file and
     132                 :    * placed in the
     133                 :    * scons-out/.../gen/native_client/src/trusted/service_runtime/
     134                 :    * directory.  usr_syscall_args must point to the first argument of
     135                 :    * a system call. System call arguments are placed on the untrusted
     136                 :    * user stack.
     137                 :    *
     138                 :    * We save the user address for user syscall arguments fetching and
     139                 :    * for VM range locking.
     140                 :    */
     141         3538669 :   natp->usr_syscall_args = NaClRawUserStackAddrNormalize(sp_user +
     142                 :                                                          NACL_SYSARGS_FIX);
     143                 : 
     144         3538669 :   if (NACL_UNLIKELY(sysnum >= NACL_MAX_SYSCALLS)) {
     145               0 :     NaClLog(2, "INVALID system call %"NACL_PRIuS"\n", sysnum);
     146               0 :     sysret = -NACL_ABI_EINVAL;
     147               0 :     NaClCopyDropLock(nap);
     148               0 :   } else {
     149         3538669 :     sysret = (*(nap->syscall_table[sysnum].handler))(natp);
     150                 :     /* Implicitly drops lock */
     151                 :   }
     152         3517806 :   NaClLog(4,
     153                 :           ("Returning from syscall %"NACL_PRIuS": return value %"NACL_PRId32
     154                 :            " (0x%"NACL_PRIx32")\n"),
     155                 :           sysnum, sysret, sysret);
     156         3517806 :   natp->user.sysret = sysret;
     157                 : 
     158                 :   /*
     159                 :    * After this NaClAppThreadSetSuspendState() call, we should not
     160                 :    * claim any mutexes, otherwise we risk deadlock.
     161                 :    */
     162         3517806 :   NaClAppThreadSetSuspendState(natp, NACL_APP_THREAD_TRUSTED,
     163                 :                                NACL_APP_THREAD_UNTRUSTED);
     164         3517806 :   NaClStackSafetyNowOnUntrustedStack();
     165                 : 
     166                 :   /*
     167                 :    * The caller switches back to untrusted code after this return.
     168                 :    */
     169         3517806 :   return ntcp;
     170                 : }

Generated by: LCOV version 1.7