OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 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 | 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 <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "native_client/src/include/concurrency_ops.h" | 9 #include "native_client/src/include/concurrency_ops.h" |
10 #include "native_client/src/include/nacl_platform.h" | 10 #include "native_client/src/include/nacl_platform.h" |
(...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 | 719 |
720 retval = 0; | 720 retval = 0; |
721 | 721 |
722 NaClTextMapClearCacheIfNeeded(nap, dest, size); | 722 NaClTextMapClearCacheIfNeeded(nap, dest, size); |
723 | 723 |
724 cleanup_unlock: | 724 cleanup_unlock: |
725 NaClXMutexUnlock(&nap->dynamic_load_mutex); | 725 NaClXMutexUnlock(&nap->dynamic_load_mutex); |
726 return retval; | 726 return retval; |
727 } | 727 } |
728 | 728 |
729 int32_t NaClTextSysDyncodeCreate(struct NaClAppThread *natp, | 729 int32_t NaClSysDyncodeCreate(struct NaClAppThread *natp, |
730 uint32_t dest, | 730 uint32_t dest, |
731 uint32_t src, | 731 uint32_t src, |
732 uint32_t size) { | 732 uint32_t size) { |
733 struct NaClApp *nap = natp->nap; | 733 struct NaClApp *nap = natp->nap; |
734 uintptr_t src_addr; | 734 uintptr_t src_addr; |
735 uint8_t *code_copy; | 735 uint8_t *code_copy; |
736 int32_t retval = -NACL_ABI_EINVAL; | 736 int32_t retval = -NACL_ABI_EINVAL; |
737 | 737 |
738 src_addr = NaClUserToSysAddrRange(nap, src, size); | 738 src_addr = NaClUserToSysAddrRange(nap, src, size); |
739 if (kNaClBadAddress == src_addr) { | 739 if (kNaClBadAddress == src_addr) { |
740 NaClLog(1, "NaClTextSysDyncodeCreate: Source address out of range\n"); | 740 NaClLog(1, "NaClSysDyncodeCreate: Source address out of range\n"); |
741 return -NACL_ABI_EFAULT; | 741 return -NACL_ABI_EFAULT; |
742 } | 742 } |
743 | 743 |
744 /* | 744 /* |
745 * Make a private copy of the code, so that we can validate it | 745 * Make a private copy of the code, so that we can validate it |
746 * without a TOCTTOU race condition. | 746 * without a TOCTTOU race condition. |
747 */ | 747 */ |
748 code_copy = malloc(size); | 748 code_copy = malloc(size); |
749 if (NULL == code_copy) { | 749 if (NULL == code_copy) { |
750 return -NACL_ABI_ENOMEM; | 750 return -NACL_ABI_ENOMEM; |
751 } | 751 } |
752 memcpy(code_copy, (uint8_t*) src_addr, size); | 752 memcpy(code_copy, (uint8_t*) src_addr, size); |
753 | 753 |
754 retval = NaClTextDyncodeCreate(nap, dest, code_copy, size); | 754 retval = NaClTextDyncodeCreate(nap, dest, code_copy, size); |
755 | 755 |
756 free(code_copy); | 756 free(code_copy); |
757 return retval; | 757 return retval; |
758 } | 758 } |
759 | 759 |
760 int32_t NaClTextSysDyncodeModify(struct NaClAppThread *natp, | 760 int32_t NaClSysDyncodeModify(struct NaClAppThread *natp, |
761 uint32_t dest, | 761 uint32_t dest, |
762 uint32_t src, | 762 uint32_t src, |
763 uint32_t size) { | 763 uint32_t size) { |
764 struct NaClApp *nap = natp->nap; | 764 struct NaClApp *nap = natp->nap; |
765 uintptr_t dest_addr; | 765 uintptr_t dest_addr; |
766 uintptr_t src_addr; | 766 uintptr_t src_addr; |
767 uintptr_t beginbundle; | 767 uintptr_t beginbundle; |
768 uintptr_t endbundle; | 768 uintptr_t endbundle; |
769 uintptr_t offset; | 769 uintptr_t offset; |
770 uint8_t *mapped_addr; | 770 uint8_t *mapped_addr; |
771 uint8_t *code_copy = NULL; | 771 uint8_t *code_copy = NULL; |
772 uint8_t code_copy_buf[NACL_INSTR_BLOCK_SIZE]; | 772 uint8_t code_copy_buf[NACL_INSTR_BLOCK_SIZE]; |
773 int validator_result; | 773 int validator_result; |
774 int32_t retval = -NACL_ABI_EINVAL; | 774 int32_t retval = -NACL_ABI_EINVAL; |
775 struct NaClDynamicRegion *region; | 775 struct NaClDynamicRegion *region; |
776 | 776 |
777 if (NULL == nap->text_shm) { | 777 if (NULL == nap->text_shm) { |
778 NaClLog(1, "NaClTextSysDyncodeModify: Dynamic loading not enabled\n"); | 778 NaClLog(1, "NaClSysDyncodeModify: Dynamic loading not enabled\n"); |
779 return -NACL_ABI_EINVAL; | 779 return -NACL_ABI_EINVAL; |
780 } | 780 } |
781 | 781 |
782 if (0 == size) { | 782 if (0 == size) { |
783 /* Nothing to modify. Succeed trivially. */ | 783 /* Nothing to modify. Succeed trivially. */ |
784 return 0; | 784 return 0; |
785 } | 785 } |
786 | 786 |
787 dest_addr = NaClUserToSysAddrRange(nap, dest, size); | 787 dest_addr = NaClUserToSysAddrRange(nap, dest, size); |
788 src_addr = NaClUserToSysAddrRange(nap, src, size); | 788 src_addr = NaClUserToSysAddrRange(nap, src, size); |
789 if (kNaClBadAddress == src_addr || kNaClBadAddress == dest_addr) { | 789 if (kNaClBadAddress == src_addr || kNaClBadAddress == dest_addr) { |
790 NaClLog(1, "NaClTextSysDyncodeModify: Address out of range\n"); | 790 NaClLog(1, "NaClSysDyncodeModify: Address out of range\n"); |
791 return -NACL_ABI_EFAULT; | 791 return -NACL_ABI_EFAULT; |
792 } | 792 } |
793 | 793 |
794 NaClXMutexLock(&nap->dynamic_load_mutex); | 794 NaClXMutexLock(&nap->dynamic_load_mutex); |
795 | 795 |
796 region = NaClDynamicRegionFind(nap, dest_addr, size); | 796 region = NaClDynamicRegionFind(nap, dest_addr, size); |
797 if (NULL == region || region->start > dest_addr | 797 if (NULL == region || region->start > dest_addr |
798 || region->start + region->size < dest_addr + size) { | 798 || region->start + region->size < dest_addr + size) { |
799 /* target not a subregion of region or region is null */ | 799 /* target not a subregion of region or region is null */ |
800 NaClLog(1, "NaClTextSysDyncodeModify: Can't find region to modify\n"); | 800 NaClLog(1, "NaClSysDyncodeModify: Can't find region to modify\n"); |
801 retval = -NACL_ABI_EFAULT; | 801 retval = -NACL_ABI_EFAULT; |
802 goto cleanup_unlock; | 802 goto cleanup_unlock; |
803 } | 803 } |
804 | 804 |
805 beginbundle = dest_addr & ~(nap->bundle_size - 1); | 805 beginbundle = dest_addr & ~(nap->bundle_size - 1); |
806 endbundle = (dest_addr + size - 1 + nap->bundle_size) | 806 endbundle = (dest_addr + size - 1 + nap->bundle_size) |
807 & ~(nap->bundle_size - 1); | 807 & ~(nap->bundle_size - 1); |
808 offset = dest_addr & (nap->bundle_size - 1); | 808 offset = dest_addr & (nap->bundle_size - 1); |
809 if (endbundle-beginbundle <= sizeof code_copy_buf) { | 809 if (endbundle-beginbundle <= sizeof code_copy_buf) { |
810 /* usually patches are a single bundle, so stack allocate */ | 810 /* usually patches are a single bundle, so stack allocate */ |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 size); | 842 size); |
843 | 843 |
844 if (validator_result != LOAD_OK | 844 if (validator_result != LOAD_OK |
845 && nap->ignore_validator_result) { | 845 && nap->ignore_validator_result) { |
846 NaClLog(LOG_ERROR, "VALIDATION FAILED for dynamically-loaded code: " | 846 NaClLog(LOG_ERROR, "VALIDATION FAILED for dynamically-loaded code: " |
847 "continuing anyway...\n"); | 847 "continuing anyway...\n"); |
848 validator_result = LOAD_OK; | 848 validator_result = LOAD_OK; |
849 } | 849 } |
850 | 850 |
851 if (validator_result != LOAD_OK) { | 851 if (validator_result != LOAD_OK) { |
852 NaClLog(1, "NaClTextSysDyncodeModify: " | 852 NaClLog(1, "NaClSysDyncodeModify: Validation of dynamic code failed\n"); |
853 "Validation of dynamic code failed\n"); | |
854 retval = -NACL_ABI_EINVAL; | 853 retval = -NACL_ABI_EINVAL; |
855 goto cleanup_unlock; | 854 goto cleanup_unlock; |
856 } | 855 } |
857 | 856 |
858 if (!NaClTextMapWrapper(nap, dest, size, &mapped_addr)) { | 857 if (!NaClTextMapWrapper(nap, dest, size, &mapped_addr)) { |
859 retval = -NACL_ABI_ENOMEM; | 858 retval = -NACL_ABI_ENOMEM; |
860 goto cleanup_unlock; | 859 goto cleanup_unlock; |
861 } | 860 } |
862 | 861 |
863 if (LOAD_OK != NaClCopyCode(nap, dest, mapped_addr, code_copy, size)) { | 862 if (LOAD_OK != NaClCopyCode(nap, dest, mapped_addr, code_copy, size)) { |
864 NaClLog(1, "NaClTextSysDyncodeModify " | 863 NaClLog(1, "NaClSysDyncodeModify: Copying of replacement code failed\n"); |
865 "Copying of replacement code failed\n"); | |
866 retval = -NACL_ABI_EINVAL; | 864 retval = -NACL_ABI_EINVAL; |
867 goto cleanup_unlock; | 865 goto cleanup_unlock; |
868 } | 866 } |
869 retval = 0; | 867 retval = 0; |
870 | 868 |
871 NaClTextMapClearCacheIfNeeded(nap, dest, size); | 869 NaClTextMapClearCacheIfNeeded(nap, dest, size); |
872 | 870 |
873 cleanup_unlock: | 871 cleanup_unlock: |
874 NaClXMutexUnlock(&nap->dynamic_load_mutex); | 872 NaClXMutexUnlock(&nap->dynamic_load_mutex); |
875 | 873 |
876 if (code_copy != code_copy_buf) { | 874 if (code_copy != code_copy_buf) { |
877 free(code_copy); | 875 free(code_copy); |
878 } | 876 } |
879 | 877 |
880 return retval; | 878 return retval; |
881 } | 879 } |
882 | 880 |
883 int32_t NaClTextSysDyncodeDelete(struct NaClAppThread *natp, | 881 int32_t NaClSysDyncodeDelete(struct NaClAppThread *natp, |
884 uint32_t dest, | 882 uint32_t dest, |
885 uint32_t size) { | 883 uint32_t size) { |
886 struct NaClApp *nap = natp->nap; | 884 struct NaClApp *nap = natp->nap; |
887 uintptr_t dest_addr; | 885 uintptr_t dest_addr; |
888 uint8_t *mapped_addr; | 886 uint8_t *mapped_addr; |
889 int32_t retval = -NACL_ABI_EINVAL; | 887 int32_t retval = -NACL_ABI_EINVAL; |
890 struct NaClDynamicRegion *region; | 888 struct NaClDynamicRegion *region; |
891 | 889 |
892 if (NULL == nap->text_shm) { | 890 if (NULL == nap->text_shm) { |
893 NaClLog(1, "NaClTextSysDyncodeDelete: Dynamic loading not enabled\n"); | 891 NaClLog(1, "NaClSysDyncodeDelete: Dynamic loading not enabled\n"); |
894 return -NACL_ABI_EINVAL; | 892 return -NACL_ABI_EINVAL; |
895 } | 893 } |
896 | 894 |
897 if (0 == size) { | 895 if (0 == size) { |
898 /* Nothing to delete. Just update our generation. */ | 896 /* Nothing to delete. Just update our generation. */ |
899 int gen; | 897 int gen; |
900 /* fetch current generation */ | 898 /* fetch current generation */ |
901 NaClXMutexLock(&nap->dynamic_load_mutex); | 899 NaClXMutexLock(&nap->dynamic_load_mutex); |
902 gen = nap->dynamic_delete_generation; | 900 gen = nap->dynamic_delete_generation; |
903 NaClXMutexUnlock(&nap->dynamic_load_mutex); | 901 NaClXMutexUnlock(&nap->dynamic_load_mutex); |
904 /* set our generation */ | 902 /* set our generation */ |
905 NaClSetThreadGeneration(natp, gen); | 903 NaClSetThreadGeneration(natp, gen); |
906 return 0; | 904 return 0; |
907 } | 905 } |
908 | 906 |
909 dest_addr = NaClUserToSysAddrRange(nap, dest, size); | 907 dest_addr = NaClUserToSysAddrRange(nap, dest, size); |
910 if (kNaClBadAddress == dest_addr) { | 908 if (kNaClBadAddress == dest_addr) { |
911 NaClLog(1, "NaClTextSysDyncodeDelete: Address out of range\n"); | 909 NaClLog(1, "NaClSysDyncodeDelete: Address out of range\n"); |
912 return -NACL_ABI_EFAULT; | 910 return -NACL_ABI_EFAULT; |
913 } | 911 } |
914 | 912 |
915 NaClXMutexLock(&nap->dynamic_load_mutex); | 913 NaClXMutexLock(&nap->dynamic_load_mutex); |
916 | 914 |
917 /* | 915 /* |
918 * this check ensures the to-be-deleted region is identical to a | 916 * this check ensures the to-be-deleted region is identical to a |
919 * previously inserted region, so no need to check for alignment/bounds/etc | 917 * previously inserted region, so no need to check for alignment/bounds/etc |
920 */ | 918 */ |
921 region = NaClDynamicRegionFind(nap, dest_addr, size); | 919 region = NaClDynamicRegionFind(nap, dest_addr, size); |
922 if (NULL == region || region->start != dest_addr || region->size != size) { | 920 if (NULL == region || region->start != dest_addr || region->size != size) { |
923 NaClLog(1, "NaClTextSysDyncodeDelete: Can't find region to delete\n"); | 921 NaClLog(1, "NaClSysDyncodeDelete: Can't find region to delete\n"); |
924 retval = -NACL_ABI_EFAULT; | 922 retval = -NACL_ABI_EFAULT; |
925 goto cleanup_unlock; | 923 goto cleanup_unlock; |
926 } | 924 } |
927 | 925 |
928 | 926 |
929 if (region->delete_generation < 0) { | 927 if (region->delete_generation < 0) { |
930 /* first deletion request */ | 928 /* first deletion request */ |
931 | 929 |
932 if (nap->dynamic_delete_generation == INT32_MAX) { | 930 if (nap->dynamic_delete_generation == INT32_MAX) { |
933 NaClLog(1, "NaClTextSysDyncodeDelete:" | 931 NaClLog(1, "NaClSysDyncodeDelete:" |
934 "Overflow, can only delete INT32_MAX regions\n"); | 932 "Overflow, can only delete INT32_MAX regions\n"); |
935 retval = -NACL_ABI_EFAULT; | 933 retval = -NACL_ABI_EFAULT; |
936 goto cleanup_unlock; | 934 goto cleanup_unlock; |
937 } | 935 } |
938 | 936 |
939 if (!NaClTextMapWrapper(nap, dest, size, &mapped_addr)) { | 937 if (!NaClTextMapWrapper(nap, dest, size, &mapped_addr)) { |
940 retval = -NACL_ABI_ENOMEM; | 938 retval = -NACL_ABI_ENOMEM; |
941 goto cleanup_unlock; | 939 goto cleanup_unlock; |
942 } | 940 } |
943 | 941 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 /* | 973 /* |
976 * Still waiting for some threads to report in... | 974 * Still waiting for some threads to report in... |
977 */ | 975 */ |
978 retval = -NACL_ABI_EAGAIN; | 976 retval = -NACL_ABI_EAGAIN; |
979 } | 977 } |
980 | 978 |
981 cleanup_unlock: | 979 cleanup_unlock: |
982 NaClXMutexUnlock(&nap->dynamic_load_mutex); | 980 NaClXMutexUnlock(&nap->dynamic_load_mutex); |
983 return retval; | 981 return retval; |
984 } | 982 } |
OLD | NEW |