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

Side by Side Diff: src/trusted/validator_ragel/validator-x86_64.rl

Issue 9348082: Move unreviewed files to unreviewed subdirectory (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 8 years, 10 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
(Empty)
1 /*
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #include <assert.h>
8 #include <elf.h>
9 #include <inttypes.h>
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "validator.h"
15
16 #undef TRUE
17 #define TRUE 1
18
19 #undef FALSE
20 #define FALSE 0
21
22 #include "validator-x86_64-instruction-consts.c"
23
24 #define check_jump_dest \
25 if ((jump_dest & bundle_mask) != bundle_mask) { \
26 if (jump_dest >= size) { \
27 printf("direct jump out of range: %zx\n", jump_dest); \
28 result = 1; \
29 goto error_detected; \
30 } else { \
31 BitmapSetBit(jump_dests, jump_dest + 1); \
32 } \
33 } \
34 operand0 = JMP_TO; \
35 base = REG_RIP; \
36 index = REG_NONE;
37
38 %%{
39 machine x86_64_decoder;
40 alphtype unsigned char;
41
42 action check_access {
43 if ((base == REG_RIP) || (base == REG_R15) ||
44 ((base == REG_RSP) && (restricted_register != REG_RSP)) ||
45 ((base == REG_RBP) && (restricted_register != REG_RBP))) {
46 if ((index == restricted_register) ||
47 ((index == REG_RDI) &&
48 (restricted_register == kSandboxedRsiRestrictedRdi))) {
49 BitmapClearBit(valid_targets, begin - data);
50 } else if ((index != REG_NONE) && (index != REG_RIZ)) {
51 fprintf(stderr,"Improper sandboxing in instruction %zx", begin - data);
52 exit(1);
53 }
54 } else if ((index == REG_RIP) || (index == REG_R15) ||
55 ((index == REG_RSP) && (restricted_register != REG_RSP)) ||
56 ((index == REG_RBP) && (restricted_register != REG_RBP))) {
57 if ((base == restricted_register) ||
58 ((base == REG_RDI) &&
59 (restricted_register == kSandboxedRsiRestrictedRdi))) {
60 BitmapClearBit(valid_targets, begin - data);
61 } else if ((base != REG_NONE) && (base != REG_RIZ)) {
62 fprintf(stderr,"Improper sandboxing in instruction @%zx", begin - data);
63 exit(1);
64 }
65 } else {
66 fprintf(stderr,"Improper sandboxing in instruction @%zx", begin - data);
67 }
68 }
69
70 action rel8_operand {
71 int8_t offset = (uint8_t) (p[0]);
72 size_t jump_dest = offset + (p - data);
73 check_jump_dest;
74 }
75 action rel16_operand {
76 assert(FALSE);
77 }
78 action rel32_operand {
79 int32_t offset =
80 (uint32_t) (p[-3] + 256U * (p[-2] + 256U * (p[-1] + 256U * (p[0]))));
81 size_t jump_dest = offset + (p - data);
82 check_jump_dest;
83 }
84
85 include decode_x86_64 "validator-x86_64-instruction.rl";
86
87 action process_normal_instruction {
88 /* Restricted %rsp or %rbp must be processed by appropriate nacl-special
89 instruction, not with regular instruction. */
90 if (restricted_register == REG_RSP) {
91 printf("Incorrectly modified register %%rsp at the %zx\n", p - data);
92 exit(1);
93 } else if (restricted_register == REG_RBP) {
94 printf("Incorrectly modified register %%rbp at the %zx\n", p - data);
95 exit(1);
96 }
97 /* If Sandboxed Rsi is destroyed then we must note that. */
98 if (restricted_register == kSandboxedRsi) {
99 for (i = 0; i < operands_count; ++i) {
100 if ((operands[i].write == TRUE) &&
101 (operands[i].name == REG_RSI) &&
102 ((operands[i].type == OperandSandboxRestricted) ||
103 (operands[i].type == OperandSandboxUnrestricted))) {
104 restricted_register = kNoRestrictedReg;
105 break;
106 }
107 }
108 }
109 if (restricted_register == kSandboxedRsi) {
110 for (i = 0; i < operands_count; ++i) {
111 if ((operands[i].write == TRUE) &&
112 (operands[i].name == REG_RDI) &&
113 (operands[i].type == OperandSandboxRestricted)) {
114 sandboxed_rsi_restricted_rdi = begin;
115 restricted_register = kSandboxedRsiRestrictedRdi;
116 }
117 }
118 }
119 if (restricted_register != kSandboxedRsiRestrictedRdi) {
120 restricted_register = kNoRestrictedReg;
121 for (i = 0; i < operands_count; ++i) {
122 if (operands[i].write && operands[i].name <= REG_R15) {
123 if (operands[i].type == OperandSandboxRestricted) {
124 if (operands[i].name == REG_R15) {
125 printf("Incorrectly modified register %%r15 at the %zx\n",
126 p - data);
127 exit(1);
128 } else {
129 restricted_register = operands[i].name;
130 }
131 } else if (operands[i].type == OperandSandboxUnrestricted) {
132 if (operands[i].name == REG_RBP) {
133 printf("Incorrectly modified register %%rbp at the %zx\n",
134 p - data);
135 exit(1);
136 } else if (operands[i].name == REG_RSP) {
137 printf("Incorrectly modified register %%rsp at the %zx\n",
138 p - data);
139 exit(1);
140 } else if (operands[i].name == REG_R15) {
141 printf("Incorrectly modified register %%r15 at the %zx\n",
142 p - data);
143 exit(1);
144 }
145 } else if (operands[i].type == OperandNoSandboxEffect) {
146 if (operands[i].name == REG_R15) {
147 printf("Incorrectly modified register %%r15 at the %zx\n",
148 p - data);
149 exit(1);
150 }
151 }
152 }
153 }
154 }
155 }
156
157 # Remove special instructions which are only allowed in special cases.
158 normal_instruction = (one_instruction - (
159 (0x48 0x89 0xe5) | # mov %rsp,%rbp
160 (0x48 0x89 0xec) | # mov %rbp,%rsp
161 (0x48 0x81 0xe4 any{4}) | # and $XXX,%rsp
162 (0x48 0x83 0xe4 any) | # and $XXX,%rsp
163 (0x4c 0x01 0xfd) | # add %r15,%rbp
164 (0x49 0x8d 0x2c 0x2f) | # lea (%r15,%rbp,1),%rbp
165 (0x4a 0x8d 0x6c 0x3d any) | # lea 0x0(%rbp,%r15,1),%rbp
166 (0x48 0x81 0xe5 any{4}) | # and $XXX,%rsp
167 (0x48 0x83 0xe5 any) | # and $XXX,%rsp
168 (0x4c 0x01 0xfc) | # add %r15,%rsp
169 (0x4a 0x8d 0x24 0x3c) | # lea (%rsp,%r15,1),%rsp
170 (0x49 0x8d 0x34 0x37) | # lea (%r15,%rsi,1),%rsi
171 (0x49 0x8d 0x3c 0x3f) # lea (%r15,%rdi,1),%rdi
172 )) @process_normal_instruction;
173
174 special_instruction =
175 (0x48 0x89 0xe5) | # mov %rsp,%rbp
176 (0x48 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp
177 (0x48 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp
178 @{ if (restricted_register == REG_RSP) {
179 printf("Incorrectly modified register %%rsp at the %zx\n", p - data);
180 exit(1);
181 }
182 restricted_register = kNoRestrictedReg;
183 } |
184 (0x48 0x89 0xec) | # mov %rbp,%rsp
185 (0x48 0x81 0xe5 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp
186 (0x48 0x83 0xe5 (0x80 .. 0xff)) # and $XXX,%rsp
187 @{ if (restricted_register == REG_RBP) {
188 printf("Incorrectly modified register %%rbp at the %zx\n", p - data);
189 exit(1);
190 }
191 restricted_register = kNoRestrictedReg;
192 } |
193 (0x4c 0x01 0xfd | # add %r15,%rbp
194 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp
195 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp
196 @{ if (restricted_register != REG_RBP) {
197 printf("Incorrectly sandboxed %%rbp at the %zx\n", p - data);
198 exit(1);
199 }
200 restricted_register = kNoRestrictedReg;
201 BitmapClearBit(valid_targets, (begin - data));
202 } |
203 (0x4c 0x01 0xfc | # add %r15,%rsp
204 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp
205 @{ if (restricted_register != REG_RSP) {
206 printf("Incorrectly sandboxed %%rsp at the %zx\n", p - data);
207 exit(1);
208 }
209 restricted_register = kNoRestrictedReg;
210 BitmapClearBit(valid_targets, (begin - data));
211 } |
212 (0x83 0xe0 0xe0 0x4c 0x01 0xf8 0xff (0xd0|0xe0) | # naclcall/jmp %eax, %r15
213 0x83 0xe1 0xe0 0x4c 0x01 0xf9 0xff (0xd1|0xe1) | # naclcall/jmp %ecx, %r15
214 0x83 0xe2 0xe0 0x4c 0x01 0xfa 0xff (0xd2|0xe2) | # naclcall/jmp %edx, %r15
215 0x83 0xe3 0xe0 0x4c 0x01 0xfb 0xff (0xd3|0xe3) | # naclcall/jmp %ebx, %r15
216 0x83 0xe4 0xe0 0x4c 0x01 0xfc 0xff (0xd4|0xe4) | # naclcall/jmp %esp, %r15
217 0x83 0xe5 0xe0 0x4c 0x01 0xfd 0xff (0xd5|0xe5) | # naclcall/jmp %ebp, %r15
218 0x83 0xe6 0xe0 0x4c 0x01 0xfe 0xff (0xd6|0xe6) | # naclcall/jmp %esi, %r15
219 0x83 0xe7 0xe0 0x4c 0x01 0xff 0xff (0xd7|0xe7)) # naclcall/jmp %edi, %r15
220 @{ if (restricted_register == REG_RSP) {
221 printf("Incorrectly modified register %%rsp at the %zx\n", p - data);
222 exit(1);
223 } else if (restricted_register == REG_RBP) {
224 printf("Incorrectly modified register %%rbp at the %zx\n", p - data);
225 exit(1);
226 }
227 BitmapClearBit(valid_targets, (p - data) - 4);
228 BitmapClearBit(valid_targets, (p - data) - 1);
229 restricted_register = kNoRestrictedReg;
230 } |
231 (0x41 0x83 0xe0 0xe0 0x4d 0x01 0xf8 0x41 0xff (0xd0|0xe0) | # naclcall/jmp
232 0x41 0x83 0xe1 0xe0 0x4d 0x01 0xf9 0x41 0xff (0xd1|0xe1) | # %r8d, %r15
233 0x41 0x83 0xe2 0xe0 0x4d 0x01 0xfa 0x41 0xff (0xd2|0xe2) | # ⋮
234 0x41 0x83 0xe3 0xe0 0x4d 0x01 0xfb 0x41 0xff (0xd3|0xe3) | # ⋮
235 0x41 0x83 0xe4 0xe0 0x4d 0x01 0xfc 0x41 0xff (0xd4|0xe4) | # ⋮
236 0x41 0x83 0xe5 0xe0 0x4d 0x01 0xfd 0x41 0xff (0xd5|0xe5) | # naclcall/jmp
237 0x41 0x83 0xe6 0xe0 0x4d 0x01 0xfe 0x41 0xff (0xd6|0xe6)) # %r14d, %r15
238 @{ if (restricted_register == REG_RSP) {
239 printf("Incorrectly modified register %%rsp at the %zx\n", p - data);
240 exit(1);
241 } else if (restricted_register == REG_RBP) {
242 printf("Incorrectly modified register %%rbp at the %zx\n", p - data);
243 exit(1);
244 }
245 BitmapClearBit(valid_targets, (p - data) - 5);
246 BitmapClearBit(valid_targets, (p - data) - 2);
247 restricted_register = kNoRestrictedReg;
248 } |
249 (0x49 0x8d 0x34 0x37) # lea (%r15,%rsi,1),%rsi
250 @{ if (restricted_register == REG_RSI) {
251 sandboxed_rsi = begin;
252 restricted_register = kSandboxedRsi;
253 } else {
254 restricted_register = kNoRestrictedReg;
255 }
256 } |
257 (0x49 0x8d 0x3c 0x3f) # lea (%r15,%rdi,1),%rdi
258 @{ if (restricted_register == REG_RDI) {
259 sandboxed_rdi = begin;
260 restricted_register = kSandboxedRdi;
261 } else if (restricted_register == kSandboxedRsiRestrictedRdi) {
262 sandboxed_rdi = begin;
263 restricted_register = kSandboxedRsiSandboxedRdi;
264 } else {
265 restricted_register = kNoRestrictedReg;
266 }
267 } |
268 (0xac | # lods %ds:(%rsi),%al
269 (data16|REXW_NONE)? 0xad) # lods %ds:(%rsi),%ax/%eax/%rax
270 @{ if (restricted_register != kSandboxedRsi) {
271 printf("Incorrectly sandboxed %%rdi at the %zx\n", p - data);
272 exit(1);
273 }
274 restricted_register = kNoRestrictedReg;
275 BitmapClearBit(valid_targets, (begin - data));
276 BitmapClearBit(valid_targets, (sandboxed_rdi - data));
277 } |
278 (0xae | # scas %ds:(%rsi),%al
279 (data16|REXW_NONE)? 0xaf | # scas %ds:(%rsi),%ax/%eax/%rax
280 rep? 0xaa | # stos %al,%es:(%rdi)
281 (data16 |
282 rep data16 |
283 data16 rep) 0xab | # stos %ax,%es:(%rdi)
284 rep? REXW_NONE? 0xab) # stos %eax/%rax,%es:(%rdi)
285 @{ if (restricted_register != kSandboxedRdi &&
286 restricted_register != kSandboxedRsiSandboxedRdi) {
287 printf("Incorrectly sandboxed %%rdi at the %zx\n", p - data);
288 exit(1);
289 }
290 restricted_register = kNoRestrictedReg;
291 BitmapClearBit(valid_targets, (begin - data));
292 BitmapClearBit(valid_targets, (sandboxed_rdi - data));
293 } |
294 (condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi)
295 (data16 |
296 condrep data16 |
297 data16 condrep) 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi)
298 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi)
299 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi)
300 (data16 |
301 rep data16 |
302 data16 rep) 0xa5 | # movsw %es:(%rdi),%ds:(%rsi)
303 rep? REXW_NONE? 0xa5) # movs[lq] %es:(%rdi),%ds:(%rsi)
304 @{ if (restricted_register != kSandboxedRsiSandboxedRdi) {
305 printf("Incorrectly sandboxed %%rsi or %%rdi at the %zx\n", p - data);
306 exit(1);
307 }
308 restricted_register = kNoRestrictedReg;
309 BitmapClearBit(valid_targets, (begin - data));
310 BitmapClearBit(valid_targets, (sandboxed_rsi - data));
311 BitmapClearBit(valid_targets, (sandboxed_rsi_restricted_rdi - data));
312 BitmapClearBit(valid_targets, (sandboxed_rdi - data));
313 };
314
315 main := ((normal_instruction | special_instruction) >{
316 begin = p;
317 BitmapSetBit(valid_targets, p - data);
318 rex_prefix = FALSE;
319 vex_prefix2 = 0xe0;
320 vex_prefix3 = 0x00;
321 })*
322 $!{ process_error(p, userdata);
323 result = 1;
324 goto error_detected;
325 };
326
327 }%%
328
329 %% write data;
330
331 /* Ignore this information for now. */
332 #define data16_prefix if (0) result
333 #define lock_prefix if (0) result
334 #define repz_prefix if (0) result
335 #define repnz_prefix if (0) result
336 #define branch_not_taken if (0) result
337 #define branch_taken if (0) result
338 #define imm if (0) begin
339 #define imm_operand if (0) result
340 #define imm2 if (0) begin
341 #define imm2_operand if (0) result
342 #define scale if (0) result
343 #define disp if (0) begin
344 #define disp_type if (0) result
345 #define operand0 operands[0].name
346 #define operand1 operands[1].name
347 #define operand2 operands[2].name
348 #define operand3 operands[3].name
349 #define operand4 operands[4].name
350 #define operand0_type operands[0].type
351 #define operand1_type operands[1].type
352 #define operand2_type operands[2].type
353 #define operand3_type operands[3].type
354 #define operand4_type operands[4].type
355 /* It's not important for us. */
356 #define operand0_read if (0) result
357 #define operand1_read if (0) result
358 #define operand2_read if (0) result
359 #define operand3_read if (0) result
360 #define operand4_read if (0) result
361 #define operand0_write operands[0].write
362 #define operand1_write operands[1].write
363 #define operand2_write operands[2].write
364 #define operand3_write operands[3].write
365 #define operand4_write operands[4].write
366
367 enum {
368 REX_B = 1,
369 REX_X = 2,
370 REX_R = 4,
371 REX_W = 8
372 };
373
374 enum disp_mode {
375 DISPNONE,
376 DISP8,
377 DISP16,
378 DISP32,
379 DISP64,
380 };
381
382 enum imm_mode {
383 IMMNONE,
384 IMM2,
385 IMM8,
386 IMM16,
387 IMM32,
388 IMM64
389 };
390
391 static const int kBitsPerByte = 8;
392
393 static inline uint8_t *BitmapAllocate(uint32_t indexes) {
394 uint32_t byte_count = (indexes + kBitsPerByte - 1) / kBitsPerByte;
395 uint8_t *bitmap = malloc(byte_count);
396 if (bitmap != NULL) {
397 memset(bitmap, 0, byte_count);
398 }
399 return bitmap;
400 }
401
402 static inline int BitmapIsBitSet(uint8_t *bitmap, uint32_t index) {
403 return (bitmap[index / kBitsPerByte] & (1 << (index % kBitsPerByte))) != 0;
404 }
405
406 static inline void BitmapSetBit(uint8_t *bitmap, uint32_t index) {
407 bitmap[index / kBitsPerByte] |= 1 << (index % kBitsPerByte);
408 }
409
410 static inline void BitmapClearBit(uint8_t *bitmap, uint32_t index) {
411 bitmap[index / kBitsPerByte] &= ~(1 << (index % kBitsPerByte));
412 }
413
414 static int CheckJumpTargets(uint8_t *valid_targets, uint8_t *jump_dests,
415 size_t size) {
416 size_t i;
417 for (i = 0; i < size / 32; i++) {
418 uint32_t jump_dest_mask = ((uint32_t *) jump_dests)[i];
419 uint32_t valid_target_mask = ((uint32_t *) valid_targets)[i];
420 if ((jump_dest_mask & ~valid_target_mask) != 0) {
421 printf("bad jump to around %x\n", (unsigned)(i * 32));
422 return 1;
423 }
424 }
425 return 0;
426 }
427
428 int ValidateChunkAMD64(const uint8_t *data, size_t size,
429 process_error_func process_error, void *userdata) {
430 const size_t bundle_size = 32;
431 const size_t bundle_mask = bundle_size - 1;
432
433 uint8_t *valid_targets = BitmapAllocate(size);
434 uint8_t *jump_dests = BitmapAllocate(size);
435
436 const uint8_t *p = data;
437 const uint8_t *begin;
438
439 uint8_t rex_prefix, vex_prefix2, vex_prefix3;
440 struct Operand {
441 unsigned int name :5;
442 unsigned int type :2;
443 bool write :1;
444 } operands[5];
445 enum register_name base, index;
446 uint8_t operands_count, i;
447 int result = 0;
448 /*
449 * These are borders of the appropriate instructions. Initialize them to make
450 * compiler happy: they are never used uninitialized even without explicit
451 * initialization but GCC is not sophysicated enough to prove that.
452 */
453 const uint8_t *sandboxed_rsi = 0;
454 const uint8_t *sandboxed_rsi_restricted_rdi = 0;
455 const uint8_t *sandboxed_rdi = 0;
456
457 assert(size % bundle_size == 0);
458
459 while (p < data + size) {
460 const uint8_t *pe = p + bundle_size;
461 const uint8_t *eof = pe;
462 int cs;
463 enum {
464 kNoRestrictedReg = 32,
465 kSandboxedRsi,
466 kSandboxedRdi,
467 kSandboxedRsiRestrictedRdi,
468 kSandboxedRsiSandboxedRdi
469 }; uint8_t restricted_register = kNoRestrictedReg;
470
471 %% write init;
472 %% write exec;
473
474 if (restricted_register == REG_RBP) {
475 printf("Incorrectly sandboxed %%rbp at the %d%zx\n", *data, p - data);
476 exit(1);
477 } else if (restricted_register == REG_RSP) {
478 printf("Incorrectly sandboxed %%rbp at the %zx\n", p - data);
479 exit(1);
480 }
481 }
482
483 if (CheckJumpTargets(valid_targets, jump_dests, size)) {
484 result = 1;
485 goto error_detected;
486 }
487
488 error_detected:
489 return result;
490 }
OLDNEW
« no previous file with comments | « src/trusted/validator_ragel/validator-x86_32.rl ('k') | src/trusted/validator_ragel/validator_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698