Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/trusted/validator_x86/nccopycode.c

Issue 10134056: Refactor the process of choosing validators. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: gyp, extern, formatting Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 /* 7 /*
8 * nccopycode.c 8 * nccopycode.c
9 * Copies two code streams in a thread-safe way 9 * Copies two code streams in a thread-safe way
10 * 10 *
(...skipping 11 matching lines...) Expand all
22 #include <stdlib.h> 22 #include <stdlib.h>
23 #include <errno.h> 23 #include <errno.h>
24 #include <string.h> 24 #include <string.h>
25 #include <assert.h> 25 #include <assert.h>
26 #include "native_client/src/include/nacl_platform.h" 26 #include "native_client/src/include/nacl_platform.h"
27 #include "native_client/src/shared/platform/nacl_check.h" 27 #include "native_client/src/shared/platform/nacl_check.h"
28 #include "native_client/src/trusted/service_runtime/sel_ldr.h" 28 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
29 #include "native_client/src/trusted/service_runtime/sel_memory.h" 29 #include "native_client/src/trusted/service_runtime/sel_memory.h"
30 #include "native_client/src/trusted/validator/ncvalidate.h" 30 #include "native_client/src/trusted/validator/ncvalidate.h"
31 31
32 #if NACL_ARCH(NACL_TARGET_ARCH) == NACL_x86 32 #if NACL_ARCH(NACL_TARGET_ARCH) == NACL_x86
Nick Bray 2012/05/25 06:41:21 Remove dead includes?
33 # if NACL_TARGET_SUBARCH == 32 33 # if NACL_TARGET_SUBARCH == 32
34 # include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode.h" 34 # include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode.h"
35 # include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncvalidate.h" 35 # include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncvalidate.h"
36 # elif NACL_TARGET_SUBARCH == 64 36 # elif NACL_TARGET_SUBARCH == 64
37 # include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" 37 # include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h"
38 # include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_intern al.h" 38 # include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_intern al.h"
39 # include "native_client/src/trusted/validator/x86/nacl_cpuid.h" 39 # include "native_client/src/trusted/validator/x86/nacl_cpuid.h"
40 # include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncval_decode_t ables.h" 40 # include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncval_decode_t ables.h"
41 # include "native_client/src/trusted/validator/x86/nc_segment.h" 41 # include "native_client/src/trusted/validator/x86/nc_segment.h"
42 # else 42 # else
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 */ 175 */
176 if (0 != NaCl_mprotect(g_squashybuffer, size, PROT_READ)) { 176 if (0 != NaCl_mprotect(g_squashybuffer, size, PROT_READ)) {
177 NaClLog(0, 177 NaClLog(0,
178 ("SerializeAllProcessors: interprocessor interrupt" 178 ("SerializeAllProcessors: interprocessor interrupt"
179 " generation failed: could not reverse shield polarity (3)\n")); 179 " generation failed: could not reverse shield polarity (3)\n"));
180 return FALSE; 180 return FALSE;
181 } 181 }
182 return TRUE; 182 return TRUE;
183 } 183 }
184 184
185 /* 185 int NaClCopyInstruction_x86(uint8_t *dst, uint8_t *src, uint8_t sz) {
186 * Copy a single instruction, avoiding the possibility of other threads
187 * executing a partially changed instruction.
188 */
189 static Bool CopyInstructionInternal(uint8_t *dst,
190 uint8_t *src,
191 uint8_t sz) {
192 intptr_t offset = 0; 186 intptr_t offset = 0;
193 uint8_t *firstbyte_p = dst; 187 uint8_t *firstbyte_p = dst;
194 188
195 while (sz > 0 && dst[0] == src[0]) { 189 while (sz > 0 && dst[0] == src[0]) {
196 /* scroll to first changed byte */ 190 /* scroll to first changed byte */
197 dst++, src++, sz--; 191 dst++, src++, sz--;
198 } 192 }
199 193
200 if (sz == 0) { 194 if (sz == 0) {
201 /* instructions are identical, we are done */ 195 /* instructions are identical, we are done */
202 return TRUE; 196 return 1;
203 } 197 }
204 198
205 while (sz > 0 && dst[sz-1] == src[sz-1]) { 199 while (sz > 0 && dst[sz-1] == src[sz-1]) {
206 /* trim identical bytes at end */ 200 /* trim identical bytes at end */
207 sz--; 201 sz--;
208 } 202 }
209 203
210 if (sz == 1) { 204 if (sz == 1) {
211 /* we assume a 1-byte change is atomic */ 205 /* we assume a 1-byte change is atomic */
212 *dst = *src; 206 *dst = *src;
213 } else if (IsTrustedWrite(dst, sz, 4, &offset)) { 207 } else if (IsTrustedWrite(dst, sz, 4, &offset)) {
214 uint8_t tmp[4]; 208 uint8_t tmp[4];
215 memcpy(tmp, dst-offset, sizeof tmp); 209 memcpy(tmp, dst-offset, sizeof tmp);
216 memcpy(tmp+offset, src, sz); 210 memcpy(tmp+offset, src, sz);
217 onestore_memmove4(dst-offset, tmp); 211 onestore_memmove4(dst-offset, tmp);
218 } else if (IsTrustedWrite(dst, sz, 8, &offset)) { 212 } else if (IsTrustedWrite(dst, sz, 8, &offset)) {
219 uint8_t tmp[8]; 213 uint8_t tmp[8];
220 memcpy(tmp, dst-offset, sizeof tmp); 214 memcpy(tmp, dst-offset, sizeof tmp);
221 memcpy(tmp+offset, src, sz); 215 memcpy(tmp+offset, src, sz);
222 onestore_memmove8(dst-offset, tmp); 216 onestore_memmove8(dst-offset, tmp);
223 } else { 217 } else {
224 /* the slow path, first flip first byte to halt*/ 218 /* the slow path, first flip first byte to halt*/
225 uint8_t firstbyte = firstbyte_p[0]; 219 uint8_t firstbyte = firstbyte_p[0];
226 firstbyte_p[0] = kNaClFullStop; 220 firstbyte_p[0] = kNaClFullStop;
227 221
228 if (!SerializeAllProcessors()) return FALSE; 222 if (!SerializeAllProcessors()) return 0;
229 223
230 /* copy the rest of instruction */ 224 /* copy the rest of instruction */
231 if (dst == firstbyte_p) { 225 if (dst == firstbyte_p) {
232 /* but not the first byte! */ 226 /* but not the first byte! */
233 firstbyte = *src; 227 firstbyte = *src;
234 dst++, src++, sz--; 228 dst++, src++, sz--;
235 } 229 }
236 memcpy(dst, src, sz); 230 memcpy(dst, src, sz);
237 231
238 if (!SerializeAllProcessors()) return FALSE; 232 if (!SerializeAllProcessors()) return 0;
239 233
240 /* flip first byte back */ 234 /* flip first byte back */
241 firstbyte_p[0] = firstbyte; 235 firstbyte_p[0] = firstbyte;
242 } 236 }
243 return TRUE; 237 return 1;
244 } 238 }
245
246 #if NACL_TARGET_SUBARCH == 32
247
248 /*
249 * Copy a single instruction, avoiding the possibility of other threads
250 * executing a partially changed instruction.
251 */
252 static Bool CopyInstruction(NCDecoderStatePair* tthis,
253 NCDecoderInst *dinst_old,
254 NCDecoderInst *dinst_new) {
255 NCRemainingMemory* mem_old = &dinst_old->dstate->memory;
256 NCRemainingMemory* mem_new = &dinst_new->dstate->memory;
257
258 return CopyInstructionInternal(mem_old->mpc,
259 mem_new->mpc,
260 mem_old->read_length);
261 }
262
263 int NCCopyCode(uint8_t *dst, uint8_t *src, NaClPcAddress vbase,
264 size_t sz) {
265 NCDecoderState dst_dstate;
266 NCDecoderInst dst_inst;
267 NCDecoderState src_dstate;
268 NCDecoderInst src_inst;
269 NCDecoderStatePair pair;
270 int result = 0;
271
272 NCDecoderStateConstruct(&dst_dstate, dst, vbase, sz, &dst_inst, 1);
273 NCDecoderStateConstruct(&src_dstate, src, vbase, sz, &src_inst, 1);
274 NCDecoderStatePairConstruct(&pair, &dst_dstate, &src_dstate);
275 pair.action_fn = CopyInstruction;
276 if (NCDecoderStatePairDecode(&pair)) result = 1;
277 NCDecoderStatePairDestruct(&pair);
278 NCDecoderStateDestruct(&src_dstate);
279 NCDecoderStateDestruct(&dst_dstate);
280
281 return result;
282 }
283
284 NaClValidationStatus NACL_SUBARCH_NAME(ApplyValidatorCopy,
285 NACL_TARGET_ARCH,
286 NACL_TARGET_SUBARCH)
287 (uintptr_t guest_addr,
288 uint8_t *data_old,
289 uint8_t *data_new,
290 size_t size,
291 const NaClCPUFeaturesX86 *cpu_features) {
292 if (!NaClArchSupported(cpu_features))
293 return NaClValidationFailedCpuNotSupported;
294
295 return ((0 == NCCopyCode(data_old, data_new, guest_addr,
296 size))
297 ? NaClValidationFailed : NaClValidationSucceeded);
298 }
299
300 #elif NACL_TARGET_SUBARCH == 64
301
302 int NaClCopyCodeIter(uint8_t *dst, uint8_t *src,
303 NaClPcAddress vbase, size_t size) {
304 NaClSegment segment_old, segment_new;
305 NaClInstIter *iter_old, *iter_new;
306 NaClInstState *istate_old, *istate_new;
307 int still_good = 1;
308
309 NaClSegmentInitialize(dst, vbase, size, &segment_old);
310 NaClSegmentInitialize(src, vbase, size, &segment_new);
311
312 iter_old = NaClInstIterCreate(kNaClValDecoderTables, &segment_old);
313 if (NULL == iter_old) return 0;
314 iter_new = NaClInstIterCreate(kNaClValDecoderTables, &segment_new);
315 if (NULL == iter_new) {
316 NaClInstIterDestroy(iter_old);
317 return 0;
318 }
319 while (1) {
320 /* March over every instruction, which means NaCl pseudo-instructions are
321 * treated as multiple instructions. Checks in NaClValidateCodeReplacement
322 * guarantee that only valid replacements will happen, and no pseudo-
323 * instructions should be touched.
324 */
325 if (!(NaClInstIterHasNext(iter_old) && NaClInstIterHasNext(iter_new))) {
326 if (NaClInstIterHasNext(iter_old) || NaClInstIterHasNext(iter_new)) {
327 NaClLog(LOG_ERROR,
328 "Segment replacement: copy failed: iterators "
329 "length mismatch\n");
330 still_good = 0;
331 }
332 break;
333 }
334 istate_old = NaClInstIterGetState(iter_old);
335 istate_new = NaClInstIterGetState(iter_new);
336 if (istate_old->bytes.length != istate_new->bytes.length ||
337 iter_old->memory.read_length != iter_new->memory.read_length ||
338 istate_new->inst_addr != istate_old->inst_addr) {
339 /* Sanity check: this should never happen based on checks in
340 * NaClValidateInstReplacement.
341 */
342 NaClLog(LOG_ERROR,
343 "Segment replacement: copied instructions misaligned\n");
344 still_good = 0;
345 break;
346 }
347 /* Replacing all modified instructions at once could yield a speedup here
348 * as every time we modify instructions we must serialize all processors
349 * twice. Re-evaluate if code modification performance is an issue.
350 */
351 if (!CopyInstructionInternal(iter_old->memory.mpc,
352 iter_new->memory.mpc,
353 iter_old->memory.read_length)) {
354 NaClLog(LOG_ERROR,
355 "Segment replacement: copy failed: unable to copy instruction\n");
356 still_good = 0;
357 break;
358 }
359 NaClInstIterAdvance(iter_old);
360 NaClInstIterAdvance(iter_new);
361 }
362
363 NaClInstIterDestroy(iter_old);
364 NaClInstIterDestroy(iter_new);
365 return still_good;
366 }
367
368 NaClValidationStatus NACL_SUBARCH_NAME(ApplyValidatorCopy,
369 NACL_TARGET_ARCH,
370 NACL_TARGET_SUBARCH)
371 (uintptr_t guest_addr,
372 uint8_t *data_old,
373 uint8_t *data_new,
374 size_t size,
375 const NaClCPUFeaturesX86 *cpu_features) {
376 if (!NaClArchSupported(cpu_features))
377 return NaClValidationFailedCpuNotSupported;
378
379 return (0 == NaClCopyCodeIter(data_old, data_new, guest_addr, size))
380 ? NaClValidationFailed : NaClValidationSucceeded;
381 }
382
383 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698