OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include "native_client/src/nonsfi/irt/irt_interfaces.h" | 7 #include "native_client/src/nonsfi/irt/irt_interfaces.h" |
8 | 8 |
9 #include <assert.h> | 9 #include <assert.h> |
10 #include <errno.h> | 10 #include <errno.h> |
(...skipping 10 matching lines...) Expand all Loading... |
21 #if defined(__linux__) | 21 #if defined(__linux__) |
22 # include <linux/futex.h> | 22 # include <linux/futex.h> |
23 # include <sys/syscall.h> | 23 # include <sys/syscall.h> |
24 #endif | 24 #endif |
25 | 25 |
26 #include "native_client/src/include/elf32.h" | 26 #include "native_client/src/include/elf32.h" |
27 #include "native_client/src/include/elf_auxv.h" | 27 #include "native_client/src/include/elf_auxv.h" |
28 #include "native_client/src/include/nacl/nacl_exception.h" | 28 #include "native_client/src/include/nacl/nacl_exception.h" |
29 #include "native_client/src/include/nacl_macros.h" | 29 #include "native_client/src/include/nacl_macros.h" |
30 #include "native_client/src/public/irt_core.h" | 30 #include "native_client/src/public/irt_core.h" |
31 #include "native_client/src/public/nonsfi/irt_exception_handling.h" | |
32 #include "native_client/src/trusted/service_runtime/include/machine/_types.h" | 31 #include "native_client/src/trusted/service_runtime/include/machine/_types.h" |
33 #include "native_client/src/trusted/service_runtime/include/sys/mman.h" | 32 #include "native_client/src/trusted/service_runtime/include/sys/mman.h" |
34 #include "native_client/src/trusted/service_runtime/include/sys/stat.h" | 33 #include "native_client/src/trusted/service_runtime/include/sys/stat.h" |
35 #include "native_client/src/trusted/service_runtime/include/sys/time.h" | 34 #include "native_client/src/trusted/service_runtime/include/sys/time.h" |
36 #include "native_client/src/trusted/service_runtime/include/sys/unistd.h" | 35 #include "native_client/src/trusted/service_runtime/include/sys/unistd.h" |
37 #include "native_client/src/untrusted/irt/irt.h" | 36 #include "native_client/src/untrusted/irt/irt.h" |
38 #include "native_client/src/untrusted/irt/irt_dev.h" | 37 #include "native_client/src/untrusted/irt/irt_dev.h" |
39 #include "native_client/src/untrusted/irt/irt_interfaces.h" | 38 #include "native_client/src/untrusted/irt/irt_interfaces.h" |
40 #include "native_client/src/untrusted/nacl/nacl_random.h" | 39 #include "native_client/src/untrusted/nacl/nacl_random.h" |
41 | 40 |
42 #if defined(__native_client__) && defined(__arm__) | 41 #if defined(__native_client__) && defined(__arm__) |
43 #include "native_client/src/nonsfi/irt/irt_icache.h" | 42 #include "native_client/src/nonsfi/irt/irt_icache.h" |
44 #endif | 43 #endif |
45 | 44 |
46 #if defined(__native_client__) | 45 #if defined(__native_client__) |
| 46 # include "native_client/src/nonsfi/linux/irt_signal_handling.h" |
47 # include "native_client/src/nonsfi/linux/linux_pthread_private.h" | 47 # include "native_client/src/nonsfi/linux/linux_pthread_private.h" |
48 #endif | 48 #endif |
49 | 49 |
50 /* | 50 /* |
51 * This is an implementation of NaCl's IRT interfaces that runs | 51 * This is an implementation of NaCl's IRT interfaces that runs |
52 * outside of the NaCl sandbox. | 52 * outside of the NaCl sandbox. |
53 * | 53 * |
54 * This allows PNaCl to be used as a portability layer without the | 54 * This allows PNaCl to be used as a portability layer without the |
55 * SFI-based sandboxing. PNaCl pexes can be translated to | 55 * SFI-based sandboxing. PNaCl pexes can be translated to |
56 * non-SFI-sandboxed native code and linked against this IRT | 56 * non-SFI-sandboxed native code and linked against this IRT |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 }; | 359 }; |
360 | 360 |
361 static void *start_thread(void *arg) { | 361 static void *start_thread(void *arg) { |
362 struct thread_args args = *(struct thread_args *) arg; | 362 struct thread_args args = *(struct thread_args *) arg; |
363 free(arg); | 363 free(arg); |
364 g_tls_value = args.thread_ptr; | 364 g_tls_value = args.thread_ptr; |
365 args.start_func(); | 365 args.start_func(); |
366 abort(); | 366 abort(); |
367 } | 367 } |
368 | 368 |
369 static int thread_create(void (*start_func)(void), void *stack, | |
370 void *thread_ptr) { | |
371 #if defined(__native_client__) | 369 #if defined(__native_client__) |
| 370 static int thread_create_nonsfi(void (*start_func)(void), void *stack, |
| 371 void *thread_ptr, nacl_irt_tid_t *child_tid) { |
372 struct thread_args *args = malloc(sizeof(struct thread_args)); | 372 struct thread_args *args = malloc(sizeof(struct thread_args)); |
373 if (args == NULL) { | 373 if (args == NULL) { |
374 return ENOMEM; | 374 return ENOMEM; |
375 } | 375 } |
376 args->start_func = start_func; | 376 args->start_func = start_func; |
377 args->thread_ptr = thread_ptr; | 377 args->thread_ptr = thread_ptr; |
378 /* In Linux, it is possible to use the provided stack directly. */ | 378 /* In Linux, it is possible to use the provided stack directly. */ |
379 int error = nacl_user_thread_create(start_thread, stack, args); | 379 int error = nacl_user_thread_create(start_thread, stack, args, child_tid); |
380 if (error != 0) | 380 if (error != 0) |
381 free(args); | 381 free(args); |
382 return error; | 382 return error; |
| 383 } |
| 384 |
| 385 static void thread_exit_nonsfi(int32_t *stack_flag) { |
| 386 nacl_user_thread_exit(stack_flag); |
| 387 } |
| 388 #endif |
| 389 |
| 390 static int thread_create(void (*start_func)(void), void *stack, |
| 391 void *thread_ptr) { |
| 392 #if defined(__native_client__) |
| 393 /* |
| 394 * When available, use the nonsfi version that does allow the |stack| to be |
| 395 * set in the new thread. |
| 396 */ |
| 397 return thread_create_nonsfi(start_func, stack, thread_ptr, NULL); |
383 #else | 398 #else |
384 /* | 399 /* |
385 * For now, we ignore the stack that user code provides and just use | 400 * For now, we ignore the stack that user code provides and just use |
386 * the stack that the host libpthread allocates. | 401 * the stack that the host libpthread allocates. |
387 */ | 402 */ |
388 pthread_attr_t attr; | 403 pthread_attr_t attr; |
389 int error = pthread_attr_init(&attr); | 404 int error = pthread_attr_init(&attr); |
390 if (error != 0) | 405 if (error != 0) |
391 return error; | 406 return error; |
392 error = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); | 407 error = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
(...skipping 11 matching lines...) Expand all Loading... |
404 if (error != 0) | 419 if (error != 0) |
405 free(args); | 420 free(args); |
406 cleanup: | 421 cleanup: |
407 pthread_attr_destroy(&attr); | 422 pthread_attr_destroy(&attr); |
408 return error; | 423 return error; |
409 #endif | 424 #endif |
410 } | 425 } |
411 | 426 |
412 static void thread_exit(int32_t *stack_flag) { | 427 static void thread_exit(int32_t *stack_flag) { |
413 #if defined(__native_client__) | 428 #if defined(__native_client__) |
414 nacl_user_thread_exit(stack_flag); | 429 /* |
| 430 * Since we used the nonsfi version of thread_create, we must also call the |
| 431 * nonsfi version of thread_exit to correctly clean it up. |
| 432 */ |
| 433 thread_exit_nonsfi(stack_flag); |
415 #else | 434 #else |
416 *stack_flag = 0; /* Indicate that the user code's stack can be freed. */ | 435 *stack_flag = 0; /* Indicate that the user code's stack can be freed. */ |
417 pthread_exit(NULL); | 436 pthread_exit(NULL); |
418 #endif | 437 #endif |
419 } | 438 } |
420 | 439 |
421 static int thread_nice(const int nice) { | 440 static int thread_nice(const int nice) { |
422 return 0; | 441 return 0; |
423 } | 442 } |
424 | 443 |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 tls_init, | 674 tls_init, |
656 tls_get, | 675 tls_get, |
657 }; | 676 }; |
658 | 677 |
659 const struct nacl_irt_thread nacl_irt_thread = { | 678 const struct nacl_irt_thread nacl_irt_thread = { |
660 thread_create, | 679 thread_create, |
661 thread_exit, | 680 thread_exit, |
662 thread_nice, | 681 thread_nice, |
663 }; | 682 }; |
664 | 683 |
| 684 #if defined(__native_client__) |
| 685 const struct nacl_irt_thread_v0_2 nacl_irt_thread_v0_2 = { |
| 686 thread_create_nonsfi, |
| 687 thread_exit_nonsfi, |
| 688 thread_nice, |
| 689 }; |
| 690 #endif |
| 691 |
665 #if defined(__linux__) | 692 #if defined(__linux__) |
666 const struct nacl_irt_futex nacl_irt_futex = { | 693 const struct nacl_irt_futex nacl_irt_futex = { |
667 futex_wait_abs, | 694 futex_wait_abs, |
668 futex_wake, | 695 futex_wake, |
669 }; | 696 }; |
670 #elif !defined(__native_client__) | 697 #elif !defined(__native_client__) |
671 DEFINE_STUB(futex_wait_abs) | 698 DEFINE_STUB(futex_wait_abs) |
672 DEFINE_STUB(futex_wake) | 699 DEFINE_STUB(futex_wake) |
673 const struct nacl_irt_futex nacl_irt_futex = { | 700 const struct nacl_irt_futex nacl_irt_futex = { |
674 USE_STUB(nacl_irt_futex, futex_wait_abs), | 701 USE_STUB(nacl_irt_futex, futex_wait_abs), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
714 * The following condition is true when building for Non-SFI Mode, | 741 * The following condition is true when building for Non-SFI Mode, |
715 * when we're calling Linux syscalls directly. (Counter-intuitively, | 742 * when we're calling Linux syscalls directly. (Counter-intuitively, |
716 * "__linux__" is not #defined in this case.) | 743 * "__linux__" is not #defined in this case.) |
717 */ | 744 */ |
718 #if defined(__native_client__) | 745 #if defined(__native_client__) |
719 const struct nacl_irt_exception_handling nacl_irt_exception_handling = { | 746 const struct nacl_irt_exception_handling nacl_irt_exception_handling = { |
720 nacl_exception_get_and_set_handler, | 747 nacl_exception_get_and_set_handler, |
721 nacl_exception_set_stack, | 748 nacl_exception_set_stack, |
722 nacl_exception_clear_flag, | 749 nacl_exception_clear_flag, |
723 }; | 750 }; |
| 751 |
| 752 const struct nacl_irt_async_signal_handling nacl_irt_async_signal_handling = { |
| 753 nacl_async_signal_set_handler, |
| 754 nacl_async_signal_send_async_signal, |
| 755 }; |
724 #endif | 756 #endif |
725 | 757 |
726 #if defined(__native_client__) && defined(__arm__) | 758 #if defined(__native_client__) && defined(__arm__) |
727 const struct nacl_irt_icache nacl_irt_icache = { | 759 const struct nacl_irt_icache nacl_irt_icache = { |
728 irt_clear_cache, | 760 irt_clear_cache, |
729 }; | 761 }; |
730 #endif | 762 #endif |
731 | 763 |
732 static int g_allow_dev_interfaces = 0; | 764 static int g_allow_dev_interfaces = 0; |
733 | 765 |
734 void nacl_irt_nonsfi_allow_dev_interfaces() { | 766 void nacl_irt_nonsfi_allow_dev_interfaces() { |
735 g_allow_dev_interfaces = 1; | 767 g_allow_dev_interfaces = 1; |
736 } | 768 } |
737 | 769 |
738 static int irt_dev_filter(void) { | 770 static int irt_dev_filter(void) { |
739 return g_allow_dev_interfaces; | 771 return g_allow_dev_interfaces; |
740 } | 772 } |
741 | 773 |
742 static const struct nacl_irt_interface irt_interfaces[] = { | 774 static const struct nacl_irt_interface irt_interfaces[] = { |
743 { NACL_IRT_BASIC_v0_1, &nacl_irt_basic, sizeof(nacl_irt_basic), NULL }, | 775 { NACL_IRT_BASIC_v0_1, &nacl_irt_basic, sizeof(nacl_irt_basic), NULL }, |
744 { NACL_IRT_DEV_FDIO_v0_2, &nacl_irt_dev_fdio_v0_2, | 776 { NACL_IRT_DEV_FDIO_v0_2, &nacl_irt_dev_fdio_v0_2, |
745 sizeof(nacl_irt_dev_fdio_v0_2), NULL }, | 777 sizeof(nacl_irt_dev_fdio_v0_2), NULL }, |
746 { NACL_IRT_FDIO_v0_1, &nacl_irt_fdio, sizeof(nacl_irt_fdio), NULL }, | 778 { NACL_IRT_FDIO_v0_1, &nacl_irt_fdio, sizeof(nacl_irt_fdio), NULL }, |
747 { NACL_IRT_MEMORY_v0_3, &nacl_irt_memory, sizeof(nacl_irt_memory), NULL }, | 779 { NACL_IRT_MEMORY_v0_3, &nacl_irt_memory, sizeof(nacl_irt_memory), NULL }, |
748 { NACL_IRT_TLS_v0_1, &nacl_irt_tls, sizeof(nacl_irt_tls), NULL }, | 780 { NACL_IRT_TLS_v0_1, &nacl_irt_tls, sizeof(nacl_irt_tls), NULL }, |
749 { NACL_IRT_THREAD_v0_1, &nacl_irt_thread, sizeof(nacl_irt_thread), NULL }, | 781 { NACL_IRT_THREAD_v0_1, &nacl_irt_thread, sizeof(nacl_irt_thread), NULL }, |
| 782 #if defined(__native_client__) |
| 783 { NACL_IRT_THREAD_v0_2, &nacl_irt_thread_v0_2, |
| 784 sizeof(nacl_irt_thread_v0_2), NULL }, |
| 785 #endif |
750 { NACL_IRT_FUTEX_v0_1, &nacl_irt_futex, sizeof(nacl_irt_futex), NULL }, | 786 { NACL_IRT_FUTEX_v0_1, &nacl_irt_futex, sizeof(nacl_irt_futex), NULL }, |
751 { NACL_IRT_RANDOM_v0_1, &nacl_irt_random, sizeof(nacl_irt_random), NULL }, | 787 { NACL_IRT_RANDOM_v0_1, &nacl_irt_random, sizeof(nacl_irt_random), NULL }, |
752 #if defined(__linux__) || defined(__native_client__) | 788 #if defined(__linux__) || defined(__native_client__) |
753 { NACL_IRT_CLOCK_v0_1, &nacl_irt_clock, sizeof(nacl_irt_clock), NULL }, | 789 { NACL_IRT_CLOCK_v0_1, &nacl_irt_clock, sizeof(nacl_irt_clock), NULL }, |
754 #endif | 790 #endif |
755 { NACL_IRT_DEV_FILENAME_v0_3, &nacl_irt_dev_filename, | 791 { NACL_IRT_DEV_FILENAME_v0_3, &nacl_irt_dev_filename, |
756 sizeof(nacl_irt_dev_filename), irt_dev_filter }, | 792 sizeof(nacl_irt_dev_filename), irt_dev_filter }, |
757 { NACL_IRT_DEV_GETPID_v0_1, &nacl_irt_dev_getpid, | 793 { NACL_IRT_DEV_GETPID_v0_1, &nacl_irt_dev_getpid, |
758 sizeof(nacl_irt_dev_getpid), irt_dev_filter }, | 794 sizeof(nacl_irt_dev_getpid), irt_dev_filter }, |
759 #if defined(__native_client__) | 795 #if defined(__native_client__) |
760 { NACL_IRT_EXCEPTION_HANDLING_v0_1, &nacl_irt_exception_handling, | 796 { NACL_IRT_EXCEPTION_HANDLING_v0_1, &nacl_irt_exception_handling, |
761 sizeof(nacl_irt_exception_handling), NULL }, | 797 sizeof(nacl_irt_exception_handling), NULL }, |
| 798 { NACL_IRT_ASYNC_SIGNAL_HANDLING_v0_1, &nacl_irt_async_signal_handling, |
| 799 sizeof(nacl_irt_async_signal_handling), NULL }, |
762 #endif | 800 #endif |
763 #if defined(__native_client__) && defined(__arm__) | 801 #if defined(__native_client__) && defined(__arm__) |
764 { NACL_IRT_ICACHE_v0_1, &nacl_irt_icache, sizeof(nacl_irt_icache), NULL }, | 802 { NACL_IRT_ICACHE_v0_1, &nacl_irt_icache, sizeof(nacl_irt_icache), NULL }, |
765 #endif | 803 #endif |
766 }; | 804 }; |
767 | 805 |
768 size_t nacl_irt_query_core(const char *interface_ident, | 806 size_t nacl_irt_query_core(const char *interface_ident, |
769 void *table, size_t tablesize) { | 807 void *table, size_t tablesize) { |
770 return nacl_irt_query_list(interface_ident, table, tablesize, | 808 return nacl_irt_query_list(interface_ident, table, tablesize, |
771 irt_interfaces, sizeof(irt_interfaces)); | 809 irt_interfaces, sizeof(irt_interfaces)); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 nacl_entry_func_t entry_func = | 864 nacl_entry_func_t entry_func = |
827 #if defined(__APPLE__) | 865 #if defined(__APPLE__) |
828 _start; | 866 _start; |
829 #else | 867 #else |
830 _user_start; | 868 _user_start; |
831 #endif | 869 #endif |
832 | 870 |
833 return nacl_irt_nonsfi_entry(argc, argv, environ, entry_func); | 871 return nacl_irt_nonsfi_entry(argc, argv, environ, entry_func); |
834 } | 872 } |
835 #endif | 873 #endif |
OLD | NEW |