OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "syscall_entrypoint.h" | 5 #include "syscall_entrypoint.h" |
6 | 6 |
7 #include "debug.h" | 7 #include "debug.h" |
8 #include "sandbox_impl.h" | 8 #include "sandbox_impl.h" |
9 #include "system_call_table.h" | 9 #include "system_call_table.h" |
10 | 10 |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 "jmp 2b\n" | 169 "jmp 2b\n" |
170 #elif defined(__i386__) | 170 #elif defined(__i386__) |
171 "cmp $119, %eax\n" // NR_sigreturn | 171 "cmp $119, %eax\n" // NR_sigreturn |
172 "jnz 1f\n" | 172 "jnz 1f\n" |
173 "add $0x8, %esp\n" // pop return address | 173 "add $0x8, %esp\n" // pop return address |
174 "0:int $0x80\n" // sigreturn() is unrestricted | 174 "0:int $0x80\n" // sigreturn() is unrestricted |
175 "mov $66, %ebx\n" // sigreturn() should never return | 175 "mov $66, %ebx\n" // sigreturn() should never return |
176 "mov %ebx, %eax\n" // NR_exit | 176 "mov %ebx, %eax\n" // NR_exit |
177 "jmp 0b\n" | 177 "jmp 0b\n" |
178 "1:cmp $173, %eax\n" // NR_rt_sigreturn | 178 "1:cmp $173, %eax\n" // NR_rt_sigreturn |
179 "jnz 3f\n" | 179 "jnz 4f\n" |
180 | 180 |
181 // Convert rt_sigframe into sigframe, allowing us to call sigreturn(). | 181 // Convert rt_sigframe into sigframe, allowing us to call sigreturn(). |
182 // This is possible since the first part of signal stack frames have | 182 // This is possible since the first part of signal stack frames have |
183 // stayed very stable since the earliest kernel versions. While never | 183 // stayed very stable since the earliest kernel versions. While never |
184 // officially documented, lots of user space applications rely on this | 184 // officially documented, lots of user space applications rely on this |
185 // part of the ABI, and kernel developers have been careful to maintain | 185 // part of the ABI, and kernel developers have been careful to maintain |
186 // backwards compatibility. | 186 // backwards compatibility. |
187 // In general, the rt_sigframe includes a lot of extra information that | 187 // In general, the rt_sigframe includes a lot of extra information that |
188 // the signal handler can look at. Most notably, this means a complete | 188 // the signal handler can look at. Most notably, this means a complete |
189 // siginfo record. | 189 // siginfo record. |
190 // Fortunately though, the kernel doesn't look at any of this extra data | 190 // Fortunately though, the kernel doesn't look at any of this extra data |
191 // when returning from a signal handler. So, we can safely convert an | 191 // when returning from a signal handler. So, we can safely convert an |
192 // rt_sigframe to a legacy sigframe, discarding the extra data in the | 192 // rt_sigframe to a legacy sigframe, discarding the extra data in the |
193 // process. Interestingly, the legacy signal frame is actually larger than | 193 // process. Interestingly, the legacy signal frame is actually larger than |
194 // the rt signal frame, as it includes a lot more padding. | 194 // the rt signal frame, as it includes a lot more padding. |
195 "sub $0x1C4, %esp\n" // a legacy signal stack is much larger | 195 "sub $0x1C4, %esp\n" // a legacy signal stack is much larger |
196 "mov 0x1CC(%esp), %eax\n" // push signal number | 196 "mov 0x1CC(%esp), %eax\n" // push signal number |
197 "push %eax\n" | 197 "push %eax\n" |
198 "lea 0x270(%esp), %esi\n" // copy siginfo register values | 198 "lea 0x270(%esp), %esi\n" // copy siginfo register values |
199 "lea 0x4(%esp), %edi\n" // into new location | 199 "lea 0x4(%esp), %edi\n" // into new location |
200 "mov $0x16, %ecx\n" | 200 "mov $0x16, %ecx\n" |
201 "cld\n" | 201 "cld\n" |
202 "rep movsl\n" | 202 "rep movsl\n" |
203 "mov 0x2C8(%esp), %ebx\n" // copy first half of signal mask | 203 "mov 0x2C8(%esp), %ebx\n" // copy first half of signal mask |
204 "mov %ebx, 0x54(%esp)\n" | 204 "mov %ebx, 0x54(%esp)\n" |
205 "lea 2f, %esi\n" | 205 "call 2f\n" |
| 206 "2:pop %esi\n" |
| 207 "add $(3f-2b), %esi\n" |
206 "push %esi\n" // push restorer function | 208 "push %esi\n" // push restorer function |
207 "lea 0x2D4(%esp), %edi\n" // patch up retcode magic numbers | 209 "lea 0x2D4(%esp), %edi\n" // patch up retcode magic numbers |
208 "movb $2, %cl\n" | 210 "movb $2, %cl\n" |
209 "rep movsl\n" | 211 "rep movsl\n" |
210 "ret\n" // return to restorer function | 212 "ret\n" // return to restorer function |
211 "2:pop %eax\n" // remove dummy argument (signo) | 213 "3:pop %eax\n" // remove dummy argument (signo) |
212 "mov $119, %eax\n" // NR_sigaction | 214 "mov $119, %eax\n" // NR_sigaction |
213 "int $0x80\n" | 215 "int $0x80\n" |
214 | 216 |
215 | 217 |
216 // Preserve all registers | 218 // Preserve all registers |
217 "3:push %ebp\n" | 219 "4:push %ebp\n" |
218 "push $0xDEADBEEF\n" // marker used by breakpad | 220 "push $0xDEADBEEF\n" // marker used by breakpad |
219 "push %ebx\n" | 221 "push %ebx\n" |
220 "push %ecx\n" | 222 "push %ecx\n" |
221 "push %edx\n" | 223 "push %edx\n" |
222 "push %esi\n" | 224 "push %esi\n" |
223 "push %edi\n" | 225 "push %edi\n" |
224 | 226 |
225 // Align stack pointer, so that called functions can push SSE registers | 227 // Align stack pointer, so that called functions can push SSE registers |
226 // onto stack. This apparently is a requirement of the x86-32 ABI. | 228 // onto stack. This apparently is a requirement of the x86-32 ABI. |
227 "mov %esp, %ebp\n" | 229 "mov %esp, %ebp\n" |
228 "and $-16, %esp\n" | 230 "and $-16, %esp\n" |
229 "sub $4, %esp\n" | 231 "sub $4, %esp\n" |
230 "push %ebp\n" // push old un-aligned stack pointer | 232 "push %ebp\n" // push old un-aligned stack pointer |
231 "lea 0x14(%ebp), %ebp\n" // frame pointer points to 0xDEADBEEF | 233 "lea 0x14(%ebp), %ebp\n" // frame pointer points to 0xDEADBEEF |
232 "push %eax\n" | 234 "push %eax\n" |
233 "mov 4(%ebp), %eax\n" // push original value of %ebp | 235 "mov 4(%ebp), %eax\n" // push original value of %ebp |
234 "xchg %eax, 0(%esp)\n" | 236 "xchg %eax, 0(%esp)\n" |
235 | 237 |
236 // Convert from syscall calling conventions to C calling conventions | 238 // Convert from syscall calling conventions to C calling conventions |
237 "push %edi\n" | 239 "push %edi\n" |
238 "push %esi\n" | 240 "push %esi\n" |
239 "push %edx\n" | 241 "push %edx\n" |
240 "push %ecx\n" | 242 "push %ecx\n" |
241 "push %ebx\n" | 243 "push %ebx\n" |
242 "push %eax\n" | 244 "push %eax\n" |
243 | 245 |
244 // Check range of system call | 246 // Check range of system call |
245 "cmp playground$maxSyscall, %eax\n" | 247 "call 5f\n" |
246 "ja 9f\n" | 248 "5:pop %edx\n" |
| 249 "add $(_GLOBAL_OFFSET_TABLE_+(.-5b)), %edx\n" |
| 250 "mov playground$maxSyscall@GOT(%edx), %edx\n" |
| 251 "cmp 0(%edx), %eax\n" |
| 252 "ja 14f\n" |
247 | 253 |
248 // We often have long sequences of calls to gettimeofday(). This is | 254 // We often have long sequences of calls to gettimeofday(). This is |
249 // needlessly expensive. Coalesce them into a single call. | 255 // needlessly expensive. Coalesce them into a single call. |
250 // | 256 // |
251 // We keep track of state in TLS storage that we can access through | 257 // We keep track of state in TLS storage that we can access through |
252 // the %fs segment register. See trusted_thread.cc for the exact | 258 // the %fs segment register. See trusted_thread.cc for the exact |
253 // memory layout. | 259 // memory layout. |
254 // | 260 // |
255 // TODO(markus): maybe, we should proactively call gettimeofday() and | 261 // TODO(markus): maybe, we should proactively call gettimeofday() and |
256 // clock_gettime(), whenever we talk to the trusted thread? | 262 // clock_gettime(), whenever we talk to the trusted thread? |
257 // or maybe, if we have recently seen requests to compute | 263 // or maybe, if we have recently seen requests to compute |
258 // the time. There might be a repeated pattern of those. | 264 // the time. There might be a repeated pattern of those. |
259 "cmp $78, %eax\n" // __NR_gettimeofday | 265 "cmp $78, %eax\n" // __NR_gettimeofday |
260 "jnz 6f\n" | 266 "jnz 10f\n" |
261 "cmp %eax, %fs:0x102C-0x58\n" // last system call | 267 "cmp %eax, %fs:0x102C-0x58\n" // last system call |
262 "jnz 4f\n" | 268 "jnz 7f\n" |
263 | 269 |
264 // This system call and the last system call prior to this one both are | 270 // This system call and the last system call prior to this one both are |
265 // calls to gettimeofday(). Try to avoid making the new call and just | 271 // calls to gettimeofday(). Try to avoid making the new call and just |
266 // return the same result as in the previous call. | 272 // return the same result as in the previous call. |
267 // Just in case the caller is spinning on the result from gettimeofday(), | 273 // Just in case the caller is spinning on the result from gettimeofday(), |
268 // every so often, call the actual system call. | 274 // every so often, call the actual system call. |
269 "decl %fs:0x1030-0x58\n" // countdown calls to gettimofday() | 275 "decl %fs:0x1030-0x58\n" // countdown calls to gettimofday() |
270 "jz 4f\n" | 276 "jz 7f\n" |
271 | 277 |
272 // Atomically read the 64bit word representing last-known timestamp and | 278 // Atomically read the 64bit word representing last-known timestamp and |
273 // return it to the caller. On x86-32 this is a little more complicated and | 279 // return it to the caller. On x86-32 this is a little more complicated and |
274 // requires the use of the cmpxchg8b instruction. | 280 // requires the use of the cmpxchg8b instruction. |
275 "mov %ebx, %eax\n" | 281 "mov %ebx, %eax\n" |
276 "mov %ecx, %edx\n" | 282 "mov %ecx, %edx\n" |
277 "lock; cmpxchg8b 100f\n" | 283 "call 6f\n" |
| 284 "6:pop %ebp\n" |
| 285 "add $(100f-6b), %ebp\n" |
| 286 "lock; cmpxchg8b 0(%ebp)\n" |
278 "mov %eax, 0(%ebx)\n" | 287 "mov %eax, 0(%ebx)\n" |
279 "mov %edx, 4(%ebx)\n" | 288 "mov %edx, 4(%ebx)\n" |
280 "xor %eax, %eax\n" | 289 "xor %eax, %eax\n" |
281 "add $28, %esp\n" | 290 "add $28, %esp\n" |
282 "jmp 8f\n" | 291 "jmp 13f\n" |
283 | 292 |
284 // This is a call to gettimeofday(), but we don't have a valid cached | 293 // This is a call to gettimeofday(), but we don't have a valid cached |
285 // result, yet. | 294 // result, yet. |
286 "4:mov %eax, %fs:0x102C-0x58\n" // remember syscall number | 295 "7:mov %eax, %fs:0x102C-0x58\n" // remember syscall number |
287 "movl $500, %fs:0x1030-0x58\n" // make system call, each 500 invocations | 296 "movl $500, %fs:0x1030-0x58\n" // make system call, each 500 invocations |
288 "call playground$defaultSystemCallHandler\n" | 297 "call playground$defaultSystemCallHandler@PLT\n" |
289 | 298 |
290 // Returned from gettimeofday(). Remember return value, in case the | 299 // Returned from gettimeofday(). Remember return value, in case the |
291 // application calls us again right away. | 300 // application calls us again right away. |
292 // Again, this has to happen atomically and requires cmpxchg8b. | 301 // Again, this has to happen atomically and requires cmpxchg8b. |
293 "mov 4(%ebx), %ecx\n" | 302 "mov 4(%ebx), %ecx\n" |
294 "mov 0(%ebx), %ebx\n" | 303 "mov 0(%ebx), %ebx\n" |
295 "mov 100f, %eax\n" | 304 "call 8f\n" |
296 "mov 101f, %edx\n" | 305 "8:pop %ebp\n" |
297 "5:lock; cmpxchg8b 100f\n" | 306 "add $(100f-8b), %ebp\n" |
298 "jnz 5b\n" | 307 "mov 0(%ebp), %eax\n" |
| 308 "mov 4(%ebp), %edx\n" |
| 309 "9:lock; cmpxchg8b 0(%ebp)\n" |
| 310 "jnz 9b\n" |
299 "xor %eax, %eax\n" | 311 "xor %eax, %eax\n" |
300 "jmp 10f\n" | 312 "jmp 15f\n" |
301 | 313 |
302 // Remember the number of the last system call made. We deliberately do | 314 // Remember the number of the last system call made. We deliberately do |
303 // not remember calls to gettid(), as we have often seen long sequences | 315 // not remember calls to gettid(), as we have often seen long sequences |
304 // of calls to just gettimeofday() and gettid(). In that situation, we | 316 // of calls to just gettimeofday() and gettid(). In that situation, we |
305 // would still like to coalesce the gettimeofday() calls. | 317 // would still like to coalesce the gettimeofday() calls. |
306 "6:cmp $224, %eax\n" // __NR_gettid | 318 "10:cmp $224, %eax\n" // __NR_gettid |
307 "jz 7f\n" | 319 "jz 11f\n" |
308 "mov %eax, %fs:0x102C-0x58\n" // remember syscall number | 320 "mov %eax, %fs:0x102C-0x58\n" // remember syscall number |
309 | 321 |
310 // Retrieve function call from system call table (c.f.system_call_table.cc) | 322 // Retrieve function call from system call table (c.f.system_call_table.cc) |
311 // We have three different types of entries; zero for denied system calls, | 323 // We have three different types of entries; zero for denied system calls, |
312 // that should be handled by the defaultSystemCallHandler(); minus one | 324 // that should be handled by the defaultSystemCallHandler(); minus one |
313 // for unrestricted system calls that need to be forwarded to the trusted | 325 // for unrestricted system calls that need to be forwarded to the trusted |
314 // thread; and function pointers to specific handler functions. | 326 // thread; and function pointers to specific handler functions. |
315 "7:shl $3, %eax\n" | 327 "11:shl $3, %eax\n" |
316 "mov playground$syscallTable, %ebx\n" | 328 "call 12f\n" |
317 "add %ebx, %eax\n" | 329 "12:pop %ebx\n" |
| 330 "add $(_GLOBAL_OFFSET_TABLE_+(.-12b)), %ebx\n" |
| 331 "mov playground$syscallTable@GOT(%ebx), %ebx\n" |
| 332 "add 0(%ebx), %eax\n" |
318 "mov 0(%eax), %eax\n" | 333 "mov 0(%eax), %eax\n" |
319 | 334 |
320 // Jump to function if non-null and not UNRESTRICTED_SYSCALL, otherwise | 335 // Jump to function if non-null and not UNRESTRICTED_SYSCALL, otherwise |
321 // jump to fallback handler. | 336 // jump to fallback handler. |
322 "cmp $1, %eax\n" | 337 "cmp $1, %eax\n" |
323 "jbe 9f\n" | 338 "jbe 14f\n" |
324 "add $4, %esp\n" | 339 "add $4, %esp\n" |
325 "call *%eax\n" | 340 "call *%eax\n" |
326 "add $24, %esp\n" | 341 "add $24, %esp\n" |
327 | 342 |
328 // Restore CPU registers, except for %eax which was set by the system call. | 343 // Restore CPU registers, except for %eax which was set by the system call. |
329 "8:pop %esp\n" | 344 "13:pop %esp\n" |
330 "pop %edi\n" | 345 "pop %edi\n" |
331 "pop %esi\n" | 346 "pop %esi\n" |
332 "pop %edx\n" | 347 "pop %edx\n" |
333 "pop %ecx\n" | 348 "pop %ecx\n" |
334 "pop %ebx\n" | 349 "pop %ebx\n" |
335 "pop %ebp\n" // 0xDEADBEEF marker | 350 "pop %ebp\n" // 0xDEADBEEF marker |
336 "pop %ebp\n" | 351 "pop %ebp\n" |
337 | 352 |
338 // Remove fake return address. This is added in the patching code in | 353 // Remove fake return address. This is added in the patching code in |
339 // library.cc and it makes stack traces a little cleaner. | 354 // library.cc and it makes stack traces a little cleaner. |
340 "add $4, %esp\n" | 355 "add $4, %esp\n" |
341 | 356 |
342 // Return to caller | 357 // Return to caller |
343 "ret\n" | 358 "ret\n" |
344 | 359 |
345 // Call default handler. | 360 // Call default handler. |
346 "9:call playground$defaultSystemCallHandler\n" | 361 "14:call playground$defaultSystemCallHandler@PLT\n" |
347 "10:add $28, %esp\n" | 362 "15:add $28, %esp\n" |
348 "jmp 8b\n" | 363 "jmp 13b\n" |
349 | 364 |
350 ".pushsection \".bss\"\n" | 365 ".pushsection \".bss\"\n" |
351 ".balign 8\n" | 366 ".balign 8\n" |
352 "100:.byte 0, 0, 0, 0\n" | 367 "100:.byte 0, 0, 0, 0, 0, 0, 0, 0\n" |
353 "101:.byte 0, 0, 0, 0\n" | |
354 ".popsection\n" | 368 ".popsection\n" |
355 | 369 |
356 #else | 370 #else |
357 #error Unsupported target platform | 371 #error Unsupported target platform |
358 #endif | 372 #endif |
359 ".size playground$syscallEntryPointWithFrame," | 373 ".size playground$syscallEntryPointWithFrame," |
360 ".-playground$syscallEntryPointWithFrame\n" | 374 ".-playground$syscallEntryPointWithFrame\n" |
361 ".popsection\n" | 375 ".popsection\n" |
362 ); | 376 ); |
363 | 377 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 } | 431 } |
418 } | 432 } |
419 if (rc < 0) { | 433 if (rc < 0) { |
420 rc = -sys.my_errno; | 434 rc = -sys.my_errno; |
421 } | 435 } |
422 Debug::elapsed(tm, syscallNum); | 436 Debug::elapsed(tm, syscallNum); |
423 return (void *)rc; | 437 return (void *)rc; |
424 } | 438 } |
425 | 439 |
426 } // namespace | 440 } // namespace |
OLD | NEW |