Chromium Code Reviews| 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 "native_client/src/shared/platform/nacl_log.h" | 7 #include "native_client/src/shared/platform/nacl_log.h" |
| 8 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | 8 #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
| 9 #include "native_client/src/trusted/validator/ncvalidate.h" | 9 #include "native_client/src/trusted/validator/ncvalidate.h" |
| 10 | 10 |
| 11 const size_t kMinimumCachedCodeSize = 40000; | 11 const size_t kMinimumCachedCodeSize = 40000; |
| 12 | 12 |
| 13 /* Translate validation status to values wanted by sel_ldr. */ | 13 /* Translate validation status to values wanted by sel_ldr. */ |
| 14 static int NaClValidateStatus(NaClValidationStatus status) { | 14 static int NaClValidateStatus(NaClValidationStatus status) { |
| 15 switch (status) { | 15 switch (status) { |
| 16 case NaClValidationSucceeded: | 16 case NaClValidationSucceeded: |
| 17 return LOAD_OK; | 17 return LOAD_OK; |
| 18 case NaClValidationFailedOutOfMemory: | 18 case NaClValidationFailedOutOfMemory: |
| 19 /* Note: this is confusing, but is what sel_ldr is expecting. */ | 19 /* Note: this is confusing, but is what sel_ldr is expecting. */ |
| 20 return LOAD_BAD_FILE; | 20 return LOAD_BAD_FILE; |
| 21 case NaClValidationFailed: | 21 case NaClValidationFailed: |
| 22 case NaClValidationFailedNotImplemented: | 22 case NaClValidationFailedNotImplemented: |
| 23 case NaClValidationFailedCpuNotSupported: | 23 case NaClValidationFailedCpuNotSupported: |
| 24 case NaClValidationFailedSegmentationIssue: | 24 case NaClValidationFailedSegmentationIssue: |
| 25 default: | 25 default: |
| 26 return LOAD_VALIDATION_FAILED; | 26 return LOAD_VALIDATION_FAILED; |
| 27 } | 27 } |
| 28 } | 28 } |
| 29 | 29 |
| 30 typedef NaClValidationStatus (*ValidateFunc) ( | 30 static NaClValidationStatus ValidatorCopyNotImplemented( |
|
Nick Bray
2012/04/25 20:57:42
I think that each validator that doesn't implement
pasko-google - do not use
2012/04/26 15:17:01
hm, we seem to agreed that validator selection is
Nick Bray
2012/04/27 00:41:30
As I see it, each "validator" will always behave t
pasko-google - do not use
2012/04/27 17:32:11
Purely hypothetical: if we want to choose validato
Nick Bray
2012/04/27 22:21:36
That would affect the choice of validator and woul
| |
| 31 uintptr_t, uint8_t*, size_t, int, int, | 31 uintptr_t guest_addr, |
| 32 const NaClCPUFeatures*, struct NaClValidationCache*); | 32 uint8_t *data_old, |
| 33 uint8_t *data_new, | |
| 34 size_t size, | |
| 35 const NaClCPUFeatures *cpu_features) { | |
| 36 UNREFERENCED_PARAMETER(guest_addr); | |
| 37 UNREFERENCED_PARAMETER(data_old); | |
| 38 UNREFERENCED_PARAMETER(data_new); | |
| 39 UNREFERENCED_PARAMETER(size); | |
| 40 UNREFERENCED_PARAMETER(cpu_features); | |
| 41 return NaClValidationFailedNotImplemented; | |
| 42 } | |
| 33 | 43 |
| 34 static ValidateFunc NaClSelectValidator(struct NaClApp *nap) { | 44 static NaClValidationStatus ValidatorCodeReplacementNotImplemented( |
| 35 ValidateFunc ret = NACL_SUBARCH_NAME(ApplyValidator, | 45 uintptr_t guest_addr, |
| 36 NACL_TARGET_ARCH, NACL_TARGET_SUBARCH); | 46 uint8_t *data_old, |
| 37 #ifdef __arm__ | 47 uint8_t *data_new, |
| 38 UNREFERENCED_PARAMETER(nap); | 48 size_t size, |
| 39 #else | 49 const NaClCPUFeatures *cpu_features) { |
| 40 if (nap->enable_dfa_validator) { | 50 UNREFERENCED_PARAMETER(guest_addr); |
| 41 ret = NACL_SUBARCH_NAME(ApplyDfaValidator, | 51 UNREFERENCED_PARAMETER(data_old); |
| 42 NACL_TARGET_ARCH, NACL_TARGET_SUBARCH); | 52 UNREFERENCED_PARAMETER(data_new); |
| 53 UNREFERENCED_PARAMETER(size); | |
| 54 UNREFERENCED_PARAMETER(cpu_features); | |
| 55 return NaClValidationFailedNotImplemented; | |
| 56 } | |
| 57 | |
| 58 void NaClSelectValidator(struct NaClApp *nap) { | |
| 59 nap->validate_func = NACL_SUBARCH_NAME(ApplyValidator, | |
|
Nick Bray
2012/04/25 20:57:42
I'd reorganize this into mutually exclusive ifdefs
pasko-google - do not use
2012/04/26 15:17:01
That was my first thought as well. Mutually exclus
Nick Bray
2012/04/27 00:41:30
But if you require each validator declare its own
| |
| 60 NACL_TARGET_ARCH, NACL_TARGET_SUBARCH); | |
| 61 #if !defined(__arm__) && defined(NACL_STANDALONE) | |
| 62 if (getenv("NACL_DANGEROUS_USE_DFA_VALIDATOR") != NULL) { | |
| 63 fprintf(stderr, "DANGER! USING THE UNSTABLE DFA VALIDATOR!\n"); | |
| 64 nap->validate_func = NACL_SUBARCH_NAME(ApplyDfaValidator, | |
| 65 NACL_TARGET_ARCH, NACL_TARGET_SUBARCH); | |
| 43 } | 66 } |
| 44 #endif | 67 #endif |
| 45 return ret; | 68 nap->validate_copy_func = ValidatorCopyNotImplemented; |
| 69 nap->validate_code_replacement_func = ValidatorCodeReplacementNotImplemented; | |
| 70 #ifndef __arm__ | |
| 71 nap->validate_copy_func = NACL_SUBARCH_NAME(ApplyValidatorCopy, | |
| 72 NACL_TARGET_ARCH, NACL_TARGET_SUBARCH); | |
| 73 nap->validate_code_replacement_func = NACL_SUBARCH_NAME( | |
| 74 ApplyValidatorCodeReplacement, NACL_TARGET_ARCH, NACL_TARGET_SUBARCH); | |
| 75 #endif | |
| 46 } | 76 } |
| 47 | 77 |
| 48 int NaClValidateCode(struct NaClApp *nap, uintptr_t guest_addr, | 78 int NaClValidateCode(struct NaClApp *nap, uintptr_t guest_addr, |
| 49 uint8_t *data, size_t size) { | 79 uint8_t *data, size_t size) { |
| 50 NaClValidationStatus status = NaClValidationSucceeded; | 80 NaClValidationStatus status = NaClValidationSucceeded; |
| 51 struct NaClValidationCache *cache = nap->validation_cache; | 81 struct NaClValidationCache *cache = nap->validation_cache; |
| 52 ValidateFunc validate_func = NaClSelectValidator(nap); | |
| 53 | 82 |
| 54 if (size < kMinimumCachedCodeSize) { | 83 if (size < kMinimumCachedCodeSize) { |
| 55 /* | 84 /* |
| 56 * Don't cache the validation of small code chunks for three reasons: | 85 * Don't cache the validation of small code chunks for three reasons: |
| 57 * 1) The size of the validation cache will be bounded. Cache entries are | 86 * 1) The size of the validation cache will be bounded. Cache entries are |
| 58 * better used for bigger code. | 87 * better used for bigger code. |
| 59 * 2) The per-transaction overhead of validation caching is more noticeable | 88 * 2) The per-transaction overhead of validation caching is more noticeable |
| 60 * for small code. | 89 * for small code. |
| 61 * 3) JITs tend to generate a lot of small code chunks, and JITed code may | 90 * 3) JITs tend to generate a lot of small code chunks, and JITed code may |
| 62 * never be seen again. Currently code size is the best mechanism we | 91 * never be seen again. Currently code size is the best mechanism we |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 77 NaClLog(LOG_FATAL, | 106 NaClLog(LOG_FATAL, |
| 78 "stub_out_mode and fixed_feature_cpu_mode are incompatible\n"); | 107 "stub_out_mode and fixed_feature_cpu_mode are incompatible\n"); |
| 79 return LOAD_VALIDATION_FAILED; | 108 return LOAD_VALIDATION_FAILED; |
| 80 } | 109 } |
| 81 if (nap->validator_stub_out_mode) { | 110 if (nap->validator_stub_out_mode) { |
| 82 /* Validation caching is currently incompatible with stubout. */ | 111 /* Validation caching is currently incompatible with stubout. */ |
| 83 cache = NULL; | 112 cache = NULL; |
| 84 /* In stub out mode, we do two passes. The second pass acts as a | 113 /* In stub out mode, we do two passes. The second pass acts as a |
| 85 sanity check that bad instructions were indeed overwritten with | 114 sanity check that bad instructions were indeed overwritten with |
| 86 allowable HLTs. */ | 115 allowable HLTs. */ |
| 87 status = validate_func(guest_addr, data, size, | 116 status = nap->validate_func(guest_addr, data, size, |
| 88 TRUE, /* stub out */ | 117 TRUE, /* stub out */ |
| 89 FALSE, /* text is not read-only */ | 118 FALSE, /* text is not read-only */ |
| 90 &nap->cpu_features, | 119 &nap->cpu_features, |
| 91 cache); | 120 cache); |
| 92 } | 121 } |
| 93 if (status == NaClValidationSucceeded) { | 122 if (status == NaClValidationSucceeded) { |
| 94 /* Fixed feature CPU mode implies read-only. */ | 123 /* Fixed feature CPU mode implies read-only. */ |
| 95 int readonly_text = nap->fixed_feature_cpu_mode; | 124 int readonly_text = nap->fixed_feature_cpu_mode; |
| 96 status = validate_func(guest_addr, data, size, | 125 status = nap->validate_func(guest_addr, data, size, |
| 97 FALSE, /* do not stub out */ | 126 FALSE, /* do not stub out */ |
| 98 readonly_text, | 127 readonly_text, |
| 99 &nap->cpu_features, | 128 &nap->cpu_features, |
| 100 cache); | 129 cache); |
| 101 } | 130 } |
| 102 return NaClValidateStatus(status); | 131 return NaClValidateStatus(status); |
| 103 } | 132 } |
| 104 | 133 |
| 105 int NaClValidateCodeReplacement(struct NaClApp *nap, uintptr_t guest_addr, | 134 int NaClValidateCodeReplacement(struct NaClApp *nap, uintptr_t guest_addr, |
| 106 uint8_t *data_old, uint8_t *data_new, | 135 uint8_t *data_old, uint8_t *data_new, |
| 107 size_t size) { | 136 size_t size) { |
| 108 if (nap->validator_stub_out_mode) return LOAD_BAD_FILE; | 137 if (nap->validator_stub_out_mode) return LOAD_BAD_FILE; |
| 109 if (nap->fixed_feature_cpu_mode) return LOAD_BAD_FILE; | 138 if (nap->fixed_feature_cpu_mode) return LOAD_BAD_FILE; |
| 110 | 139 |
| 111 if ((guest_addr % nap->bundle_size) != 0 || | 140 if ((guest_addr % nap->bundle_size) != 0 || |
| 112 (size % nap->bundle_size) != 0) { | 141 (size % nap->bundle_size) != 0) { |
| 113 return LOAD_BAD_FILE; | 142 return LOAD_BAD_FILE; |
| 114 } | 143 } |
| 115 | 144 |
| 116 return NaClValidateStatus( | 145 return NaClValidateStatus(nap->validate_code_replacement_func( |
| 117 NACL_SUBARCH_NAME(ApplyValidatorCodeReplacement, | 146 guest_addr, data_old, data_new, size, &nap->cpu_features)); |
| 118 NACL_TARGET_ARCH, | |
| 119 NACL_TARGET_SUBARCH) | |
| 120 (guest_addr, data_old, data_new, size, &nap->cpu_features)); | |
| 121 } | 147 } |
| 122 | 148 |
| 123 int NaClCopyCode(struct NaClApp *nap, uintptr_t guest_addr, | 149 int NaClCopyCode(struct NaClApp *nap, uintptr_t guest_addr, |
| 124 uint8_t *data_old, uint8_t *data_new, | 150 uint8_t *data_old, uint8_t *data_new, |
| 125 size_t size) { | 151 size_t size) { |
| 126 /* Fixed-feature mode disables any code copying for now. Currently | 152 /* Fixed-feature mode disables any code copying for now. Currently |
| 127 * the only use of NaClCodeCopy() seems to be for dynamic code | 153 * the only use of NaClCodeCopy() seems to be for dynamic code |
| 128 * modification, which should fail in NaClValidateCodeReplacement() | 154 * modification, which should fail in NaClValidateCodeReplacement() |
| 129 * before reaching this. | 155 * before reaching this. |
| 130 */ | 156 */ |
| 131 if (nap->fixed_feature_cpu_mode) return LOAD_BAD_FILE; | 157 if (nap->fixed_feature_cpu_mode) return LOAD_BAD_FILE; |
| 132 return NaClValidateStatus( | 158 return NaClValidateStatus(nap->validate_copy_func( |
| 133 NACL_SUBARCH_NAME(ApplyValidatorCopy, | 159 guest_addr, data_old, data_new, size, &nap->cpu_features)); |
| 134 NACL_TARGET_ARCH, | |
| 135 NACL_TARGET_SUBARCH) | |
| 136 (guest_addr, data_old, data_new, size, &nap->cpu_features)); | |
| 137 } | 160 } |
| 138 | 161 |
| 139 NaClErrorCode NaClValidateImage(struct NaClApp *nap) { | 162 NaClErrorCode NaClValidateImage(struct NaClApp *nap) { |
| 140 uintptr_t memp; | 163 uintptr_t memp; |
| 141 uintptr_t endp; | 164 uintptr_t endp; |
| 142 size_t regionsize; | 165 size_t regionsize; |
| 143 NaClErrorCode rcode; | 166 NaClErrorCode rcode; |
| 144 | 167 |
| 145 memp = nap->mem_start + NACL_TRAMPOLINE_END; | 168 memp = nap->mem_start + NACL_TRAMPOLINE_END; |
| 146 endp = nap->mem_start + nap->static_text_end; | 169 endp = nap->mem_start + nap->static_text_end; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 164 NaClLog(LOG_ERROR, | 187 NaClLog(LOG_ERROR, |
| 165 "Run sel_ldr in debug mode to ignore validation failure.\n"); | 188 "Run sel_ldr in debug mode to ignore validation failure.\n"); |
| 166 NaClLog(LOG_ERROR, | 189 NaClLog(LOG_ERROR, |
| 167 "Run ncval <module-name> for validation error details.\n"); | 190 "Run ncval <module-name> for validation error details.\n"); |
| 168 rcode = LOAD_VALIDATION_FAILED; | 191 rcode = LOAD_VALIDATION_FAILED; |
| 169 } | 192 } |
| 170 } | 193 } |
| 171 } | 194 } |
| 172 return rcode; | 195 return rcode; |
| 173 } | 196 } |
| OLD | NEW |