2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl service run-time.
36 #include "native_client/include/portability.h"
37 #include "native_client/include/nacl_platform.h"
42 /* TODO: IS THIS STILL NEEDED FOR WINDOWS ??? */
43 #include <sys/timeb.h>
48 #include "native_client/service_runtime/nacl_globals.h"
49 #include "native_client/service_runtime/nacl_config.h"
50 #include "native_client/service_runtime/nacl_log.h"
51 #include "native_client/service_runtime/nacl_switch_to_app.h"
52 #include "native_client/service_runtime/nacl_syscall_handlers.h"
53 #include "native_client/service_runtime/sel_ldr.h"
55 #include "native_client/service_runtime/include/sys/errno.h"
56 #include "native_client/service_runtime/include/bits/nacl_syscalls.h"
59 * Simple RPC support. The default socket file descriptor is invalid.
61 int NaClSrpcFileDescriptor
= -1;
63 int NaClArtificialDelay
= -1;
67 * The first syscall is from the NaCl module's main thread, and there
68 * are no other user threads yet, so NACLDELAY check and the NACLCLOCK
69 * usages are okay; when the NaCl module is multithreaded, the
70 * variables they initialize are read-only.
72 typedef uint64_t tick_t
;
73 static tick_t
get_ticks() {
76 uint32_t t_high
, t_low
;
79 __asm mov t_high
, edx
;
81 t
= (((tick_t
) t_high
) << 32) | t_low
;
83 asm volatile("rdtsc" : "=A" (t
));
88 void NaClMicroSleep(int microseconds
)
90 static int initialized
= 0;
91 static tick_t cpu_clock
= 0;
96 char *env
= getenv("NACLCLOCK");
98 cpu_clock
= strtoul(env
, (char **) NULL
, 0);
105 end
= now
+ (cpu_clock
* microseconds
) / 1000000;
106 NaClLog(5, "Now %"PRId64
". Waiting until %lld.\n", now
, end
);
107 while (get_ticks() < end
)
112 NORETURN
void NaClSyscallCSegHook(int32_t ldt_ix
)
114 struct NaClAppThread
*natp
= nacl_thread
[ldt_ix
];
115 struct NaClApp
*nap
= natp
->nap
;
116 struct NaClThreadContext
*user
= &natp
->user
;
117 uintptr_t tramp_addr
;
119 uint32_t aligned_tramp_ret
;
122 /* esp must be okay for control to have gotten here */
124 NaClLog(4, "Entered NaClSyscallCSegHook\n");
125 NaClLog(4, "user esp 0x%08x\n", user
->esp
);
130 * esp+0: retaddr from lcall
131 * esp+4: code seg from lcall
132 * esp+8: retaddr from syscall wrapper
135 tramp_addr
= NaClUserToSys(nap
, user
->esp
);
136 tramp_ret
= *(uint32_t *) tramp_addr
;
138 * return addr could have been tampered with by another thread, but
139 * the only result would be a bad sysnum.
141 sysnum
= (tramp_ret
- NACL_SYSCALL_START_ADDR
)
142 >> NACL_SYSCALL_BLOCK_SHIFT
;
145 NaClLog(4, "system call %d\n", sysnum
);
148 * keep tramp_ret in user addr; do not bother to ensure tramp_addr +
149 * 8 is valid, since even if we loaded two NaClApps next to each
150 * other this would just load the trampoline code, or hit the
151 * inaccessible page for NULL pointer detection (once we get that
152 * implemented). if it is not a valid address, we would just crash.
154 tramp_ret
= *(uint32_t *) (tramp_addr
+ 8);
155 if (0 != nap
->xlate_base
) {
157 * ensure that tramp_ret value is ok. no need to ensure that this
158 * is in the app's address space, since the syscall return will
159 * just result in a fault after we reconstitute the sandbox and
160 * attempt to pass control to this address.
162 aligned_tramp_ret
= tramp_ret
& ~(nap
->align_boundary
- 1);
163 if (tramp_ret
!= aligned_tramp_ret
) {
164 NaClLog(LOG_FATAL
, ("NaClSyscallCSegHook: tramp_ret infinite loop:"
165 " %08x != %08x\nMake sure NaCl SDK and sel_ldr"
166 " agree on alignment (ELF header of NaCl app"
167 " claims alignment is %d).\n"),
168 tramp_ret
, aligned_tramp_ret
, nap
->align_boundary
);
170 tramp_ret
= aligned_tramp_ret
;
173 user
->esp
+= 0xc; /* call, lcall */
174 if (sysnum
>= NACL_MAX_SYSCALLS
) {
175 NaClLog(2, "INVALID system call %d\n", sysnum
);
176 natp
->sysret
= -NACL_ABI_EINVAL
;
179 NaClLog(4, "making system call %d, handler 0x%08"PRIxPTR
"\n",
180 sysnum
, (uintptr_t) nacl_syscall
[sysnum
].handler
);
183 natp
->x_esp
= (uint32_t *) (tramp_addr
+ 0xc);
184 natp
->sysret
= (*nacl_syscall
[sysnum
].handler
)(natp
);
188 ("returning from system call %d, return value %"PRId32
190 sysnum
, natp
->sysret
, natp
->sysret
);
192 NaClLog(4, "return target 0x%08"PRIx32
"\n", tramp_ret
);
193 NaClLog(4, "user esp 0x%08"PRIx32
"\n", user
->esp
);
195 if (-1 == NaClArtificialDelay
) {
196 char *delay
= getenv("NACLDELAY");
198 NaClArtificialDelay
= strtol(delay
, (char **) NULL
, 0);
199 NaClLog(0, "ARTIFICIAL DELAY %d us\n", NaClArtificialDelay
);
201 NaClArtificialDelay
= 0;
204 if (0 != NaClArtificialDelay
) {
205 NaClMicroSleep(NaClArtificialDelay
);
207 NaClSwitchToApp(natp
, tramp_ret
);
210 fprintf(stderr
, "NORETURN NaClSwitchToApp returned!?!\n");