LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - nacl_syscall_hook.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 50 34 68.0 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 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/shared/platform/nacl_exit.h"
      19                 : #include "native_client/src/shared/platform/nacl_log.h"
      20                 : #include "native_client/src/trusted/service_runtime/nacl_globals.h"
      21                 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
      22                 : #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h"
      23                 : #include "native_client/src/trusted/service_runtime/nacl_syscall_handlers.h"
      24                 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
      25                 : #include "native_client/src/trusted/service_runtime/sel_rt.h"
      26                 : 
      27                 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
      28                 : #include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h"
      29                 : #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
      30                 : #include "native_client/src/trusted/service_runtime/nacl_stack_safety.h"
      31                 : 
      32                 : int NaClArtificialDelay = -1;
      33                 : 
      34                 : 
      35                 : /*
      36                 :  * The first syscall is from the NaCl module's main thread, and there
      37                 :  * are no other user threads yet, so NACLDELAY check and the NACLCLOCK
      38                 :  * usages are okay; when the NaCl module is multithreaded, the
      39                 :  * variables they initialize are read-only.
      40                 :  */
      41                 : 
      42                 : 
      43               0 : void NaClMicroSleep(int microseconds) {
      44                 :   static int    initialized = 0;
      45                 :   static tick_t cpu_clock = 0;
      46                 :   tick_t        now;
      47                 :   tick_t        end;
      48                 : 
      49               0 :   if (!initialized) {
      50               0 :     char *env = getenv("NACLCLOCK");
      51               0 :     if (NULL != env) {
      52               0 :       cpu_clock = strtoul(env, (char **) NULL, 0);
      53                 :     }
      54                 : 
      55               0 :     initialized = 1;
      56                 :   }
      57                 : 
      58               0 :   now = get_ticks();
      59               0 :   end = now + (cpu_clock * microseconds) / 1000000;
      60               0 :   NaClLog(5, "Now %"NACL_PRId64".  Waiting until %"NACL_PRId64".\n", now, end);
      61               0 :   while (get_ticks() < end)
      62                 :     ;
      63               0 : }
      64                 : 
      65             562 : NORETURN void NaClSyscallCSegHook(int32_t tls_idx) {
      66                 :   struct NaClAppThread      *natp;
      67                 :   struct NaClApp            *nap;
      68                 :   struct NaClThreadContext  *user;
      69                 :   uintptr_t                 tramp_ret;
      70                 :   nacl_reg_t                user_ret;
      71                 :   size_t                    sysnum;
      72                 :   uintptr_t                 sp_user;
      73                 :   uintptr_t                 sp_sys;
      74                 : 
      75                 :   /*
      76                 :    * Mark the thread as running on a trusted stack as soon as possible
      77                 :    * so that we can report any crashes that occur after this point.
      78                 :    */
      79             562 :   NaClStackSafetyNowOnTrustedStack();
      80                 : 
      81             562 :   natp = nacl_thread[tls_idx];
      82                 : 
      83                 :   /*
      84                 :    * Before this call, the thread could be suspended, so we should not
      85                 :    * lock any mutexes before this, otherwise it could cause a
      86                 :    * deadlock.
      87                 :    */
      88             562 :   NaClAppThreadSetSuspendState(natp, NACL_APP_THREAD_UNTRUSTED,
      89                 :                                NACL_APP_THREAD_TRUSTED);
      90                 : 
      91             562 :   nap = natp->nap;
      92             562 :   user = &natp->user;
      93             562 :   sp_user = NaClGetThreadCtxSp(user);
      94                 : 
      95                 :   /* sp must be okay for control to have gotten here */
      96                 : #if !BENCHMARK
      97             562 :   NaClLog(4, "Entered NaClSyscallCSegHook\n");
      98             562 :   NaClLog(4, "user sp %"NACL_PRIxPTR"\n", sp_user);
      99                 : #endif
     100                 : 
     101                 :   /*
     102                 :    * on x86_32 user stack:
     103                 :    *  esp+0:  retaddr from lcall
     104                 :    *  esp+4:  code seg from lcall
     105                 :    *  esp+8:  retaddr to user module
     106                 :    *  esp+c:  ...
     107                 :    *
     108                 :    * on ARM user stack
     109                 :    *   sp+0:  retaddr from trampoline slot
     110                 :    *   sp+4:  retaddr to user module
     111                 :    *   sp+8:  arg0 to system call
     112                 :    *   sp+c:  arg1 to system call
     113                 :    *   sp+10: ....
     114                 :    */
     115                 : 
     116             562 :   sp_sys = NaClUserToSysStackAddr(nap, sp_user);
     117                 :   /*
     118                 :    * sp_sys points to the top of user stack where there is a retaddr to
     119                 :    * trampoline slot
     120                 :    */
     121             562 :   tramp_ret = *(uintptr_t *)sp_sys;
     122             562 :   tramp_ret = NaClUserToSysStackAddr(nap, tramp_ret);
     123                 : 
     124             562 :   sysnum = (tramp_ret - (nap->mem_start + NACL_SYSCALL_START_ADDR))
     125                 :       >> NACL_SYSCALL_BLOCK_SHIFT;
     126                 : 
     127                 : #if !BENCHMARK
     128             562 :   NaClLog(4, "system call %"NACL_PRIuS"\n", sysnum);
     129                 : #endif
     130                 : 
     131                 :   /*
     132                 :    * getting user return address (the address where we need to return after
     133                 :    * system call) from the user stack. (see stack layout above)
     134                 :    */
     135             562 :   user_ret = *(uintptr_t *) (sp_sys + NACL_USERRET_FIX);
     136                 :   /*
     137                 :    * Fix the user stack, throw away return addresses from the top of the stack.
     138                 :    * After this fix, the first argument to a system call must be on the top of
     139                 :    * the user stack (see user stack layout above)
     140                 :    */
     141             562 :   sp_sys += NACL_SYSARGS_FIX;
     142             562 :   sp_user += NACL_SYSCALLRET_FIX;
     143             562 :   NaClSetThreadCtxSp(user, sp_user);
     144                 : 
     145             562 :   if (sysnum >= NACL_MAX_SYSCALLS) {
     146               0 :     NaClLog(2, "INVALID system call %"NACL_PRIdS"\n", sysnum);
     147               0 :     natp->sysret = -NACL_ABI_EINVAL;
     148                 :   } else {
     149                 : #if !BENCHMARK
     150             562 :     NaClLog(4, "making system call %"NACL_PRIdS", "
     151                 :             "handler 0x%08"NACL_PRIxPTR"\n",
     152                 :             sysnum, (uintptr_t) nap->syscall_table[sysnum].handler);
     153                 : #endif
     154                 :     /*
     155                 :      * syscall_args is used by Decoder functions in
     156                 :      * nacl_syscall_handlers.c which is automatically generated file
     157                 :      * and placed in the
     158                 :      * scons-out/.../gen/native_client/src/trusted/service_runtime/
     159                 :      * directory.  syscall_args must point to the first argument of a
     160                 :      * system call. System call arguments are placed on the untrusted
     161                 :      * user stack.
     162                 :      */
     163             562 :     natp->syscall_args = (uintptr_t *) sp_sys;
     164             562 :     natp->sysret = (*(nap->syscall_table[sysnum].handler))(natp);
     165                 :   }
     166                 : #if !BENCHMARK
     167             559 :   NaClLog(4,
     168                 :           ("returning from system call %"NACL_PRIdS", return value %"NACL_PRId32
     169                 :            " (0x%"NACL_PRIx32")\n"),
     170                 :           sysnum, natp->sysret, natp->sysret);
     171                 : 
     172             559 :   NaClLog(4, "return target 0x%08"NACL_PRIxNACL_REG"\n", user_ret);
     173             559 :   NaClLog(4, "user sp %"NACL_PRIxPTR"\n", sp_user);
     174                 : #endif
     175             559 :   if (-1 == NaClArtificialDelay) {
     176               3 :     char *delay = getenv("NACLDELAY");
     177               3 :     if (NULL != delay) {
     178               0 :       NaClArtificialDelay = strtol(delay, (char **) NULL, 0);
     179               0 :       NaClLog(0, "ARTIFICIAL DELAY %d us\n", NaClArtificialDelay);
     180                 :     } else {
     181               3 :       NaClArtificialDelay = 0;
     182                 :     }
     183                 :   }
     184             559 :   if (0 != NaClArtificialDelay) {
     185               0 :     NaClMicroSleep(NaClArtificialDelay);
     186                 :   }
     187                 : 
     188                 :   /*
     189                 :    * before switching back to user module, we need to make sure that the
     190                 :    * user_ret is properly sandboxed.
     191                 :    */
     192             559 :   user_ret = (nacl_reg_t) NaClSandboxCodeAddr(nap, (uintptr_t)user_ret);
     193                 :   /*
     194                 :    * After this NaClAppThreadSetSuspendState() call, we should not
     195                 :    * claim any mutexes, otherwise we risk deadlock.  Note that if
     196                 :    * NACLVERBOSITY is set high enough to enable the NaClLog() calls in
     197                 :    * NaClSwitchToApp(), these calls could deadlock on Windows.
     198                 :    */
     199             559 :   NaClAppThreadSetSuspendState(natp, NACL_APP_THREAD_TRUSTED,
     200                 :                                NACL_APP_THREAD_UNTRUSTED);
     201             559 :   NaClStackSafetyNowOnUntrustedStack();
     202                 : 
     203             559 :   NaClSwitchToApp(natp, user_ret);
     204                 :   /* NOTREACHED */
     205                 : 
     206                 :   fprintf(stderr, "NORETURN NaClSwitchToApp returned!?!\n");
     207                 :   NaClAbort();
     208                 : }

Generated by: LCOV version 1.7