OLD | NEW |
| (Empty) |
1 /* | |
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 | |
4 * found in the LICENSE file. | |
5 */ | |
6 | |
7 /* Validator to check that instructions are in the legal subset. */ | |
8 | |
9 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.h" | |
10 | |
11 #include "native_client/src/shared/platform/nacl_log.h" | |
12 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h" | |
13 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" | |
14 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state.h" | |
15 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" | |
16 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter.
h" | |
17 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncvalidate_iter_
internal.h" | |
18 #include "native_client/src/trusted/validator/x86/decoder/generator/gen/nacl_dis
allows.h" | |
19 | |
20 /* To turn on debugging of instruction decoding, change value of | |
21 * DEBUGGING to 1. | |
22 */ | |
23 #define DEBUGGING 0 | |
24 | |
25 #include "native_client/src/shared/utils/debugging.h" | |
26 | |
27 /* Message to use if we don't have a more precise reason why the instruction | |
28 * is illegal. | |
29 */ | |
30 static const char* kNaClGenericReasonDisallowed = | |
31 "Illegal native client instruction"; | |
32 | |
33 /* This function returns a printable description of the reason an instruction | |
34 * is disallowed, or NULL if the reason is not understood. | |
35 */ | |
36 static const char* NaClReasonWhyDisallowed(NaClDisallowsFlag flag) { | |
37 switch (flag) { | |
38 case NaClTooManyPrefixBytes: | |
39 return "More than one (non-REX) prefix byte specified"; | |
40 case NaClMarkedIllegal: | |
41 return "This instruction has been marked illegal by Native Client"; | |
42 case NaClMarkedInvalid: | |
43 return "Opcode sequence doesn't define a valid x86 instruction"; | |
44 case NaClMarkedSystem: | |
45 return "System instructions are not allowed by Native Client"; | |
46 case NaClHasBadSegmentPrefix: | |
47 return "Uses a segment prefix byte not allowed by Native Client"; | |
48 case NaClCantUsePrefix67: | |
49 return "Use of 67 (ADDR16) prefix not allowed by Native Client"; | |
50 case NaClMultipleRexPrefix: | |
51 return "Multiple use of REX prefix not allowed"; | |
52 case NaClRepDisallowed: | |
53 return | |
54 "Use of REP (F3) prefix for instruction not allowed by " | |
55 "Native Client"; | |
56 case NaClRepneDisallowed: | |
57 return | |
58 "Use of REPNE (F2) prefix for instruction not allowed by " | |
59 "Native Client"; | |
60 case NaClData16Disallowed: | |
61 return | |
62 "Use of DATA16 (66) prefix for instruction not allowed by " | |
63 "Native Client"; | |
64 case NaClHasDuplicatePrefix: | |
65 return | |
66 "Duplicating a prefix byte is not allowed by Native Client"; | |
67 case NaClHasAmbigSegmentPrefixes: | |
68 return | |
69 "Specifying different segment registers using prefix bytes " | |
70 "is not allowed by Native Client"; | |
71 case NaClRexPrefixNotLast: | |
72 return "REX prefix byte must appear last"; | |
73 default: | |
74 return NULL; | |
75 } | |
76 } | |
77 | |
78 /* Same as NaClReasonWhyDisallowed, except that the unknown value (NULL) | |
79 * is replaced by a useful print error message. | |
80 */ | |
81 static const char* NaClGetReasonWhyDisallowed(NaClDisallowsFlag flag) { | |
82 const char* why = NaClReasonWhyDisallowed(flag); | |
83 if (NULL == why) { | |
84 /* If reached, we don't understand the flag. Non the less, we should | |
85 * return a message explaining that the instruction is illegal, so | |
86 * that an appropriate error message can be printed. | |
87 */ | |
88 why = kNaClGenericReasonDisallowed; | |
89 } | |
90 return why; | |
91 } | |
92 | |
93 /* A mask of possible segment prefixes. */ | |
94 static const uint32_t kNaClSegmentPrefixMask = | |
95 kPrefixSEGES | kPrefixSEGFS | kPrefixSEGGS | kPrefixSEGSS | | |
96 kPrefixSEGCS | kPrefixSEGDS; | |
97 | |
98 /* | |
99 * A mask for prefixes that can't appear with any jump instruction. | |
100 * Note: We rule these out because of Intel's Software Developer's | |
101 * Manual (volume 2a) documents in section 2.1.1 that such uses may | |
102 * cause unpredictable behaviour. | |
103 */ | |
104 static const uint32_t kNaClUnsafeJumpPrefixes = | |
105 kPrefixSEGES | kPrefixSEGFS | kPrefixSEGGS | kPrefixSEGSS; | |
106 | |
107 /* | |
108 * A mask for prefixes that can only appear with conditional jump | |
109 * instructions with branch hints. | |
110 */ | |
111 static const uint32_t kNaClBranchHintJumpPrefixes = | |
112 kPrefixSEGCS | kPrefixSEGDS; | |
113 | |
114 /* This function checks properties about segment registers on an | |
115 * instruction, reporting issues not allowed by native client. | |
116 */ | |
117 static void NaClCheckSegmentPrefixes(NaClValidatorState* state, | |
118 Bool* is_legal, | |
119 NaClDisallowsFlags* disallows_flags) { | |
120 NaClInstState* inst_state = state->cur_inst_state; | |
121 Bool segment_prefixes_ok = TRUE; | |
122 | |
123 if (0 == (inst_state->prefix_mask & kNaClSegmentPrefixMask)) return; | |
124 | |
125 if (state->cur_inst->flags & | |
126 (NACL_IFLAG(JumpInstruction) | NACL_IFLAG(ConditionalJump))) { | |
127 if (inst_state->prefix_mask & kNaClUnsafeJumpPrefixes) { | |
128 segment_prefixes_ok = FALSE; | |
129 } | |
130 if (NaClExcludesBit(state->cur_inst->flags, NACL_IFLAG(BranchHints)) && | |
131 NaClHasBit(inst_state->prefix_mask, kNaClBranchHintJumpPrefixes)) { | |
132 segment_prefixes_ok = FALSE; | |
133 } | |
134 } else { | |
135 /* We don't allow any prefix masks on data accesses. */ | |
136 segment_prefixes_ok = FALSE; | |
137 } | |
138 | |
139 if (!segment_prefixes_ok) { | |
140 *is_legal = FALSE; | |
141 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasBadSegmentPrefix); | |
142 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
143 NaClGetReasonWhyDisallowed(NaClHasBadSegmentPrefix))); | |
144 } | |
145 | |
146 /* Don't allow ambiguous prefix forms. */ | |
147 if (inst_state->has_ambig_segment_prefixes) { | |
148 *is_legal = FALSE; | |
149 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasAmbigSegmentPrefixes); | |
150 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
151 NaClGetReasonWhyDisallowed(NaClHasAmbigSegmentPrefixes))); | |
152 } | |
153 | |
154 } | |
155 | |
156 /* This function checks properties of prefix bytes on an instruction, | |
157 * reporting issues not allowed by native client. | |
158 * | |
159 * Parameters are: | |
160 * state : The current validator state to check. | |
161 * is_legal: Flag set to FALSE if any prefix problems are found. | |
162 * disallows_flags : Set of flags, describing the reason(s) the | |
163 * current instruction in the validator state is not | |
164 * legal in native client. Updated as appropriate. | |
165 */ | |
166 static void NaClCheckForPrefixIssues(NaClValidatorState* state, | |
167 Bool* is_legal, | |
168 NaClDisallowsFlags* disallows_flags) { | |
169 NaClInstState* inst_state = state->cur_inst_state; | |
170 const NaClInst* inst = state->cur_inst; | |
171 /* Don't allow more than one (non-REX) prefix. */ | |
172 int num_prefix_bytes = inst_state->num_prefix_bytes; | |
173 if (inst_state->rexprefix) --num_prefix_bytes; | |
174 | |
175 /* Don't allow an invalid instruction. */ | |
176 if (!NaClInstStateIsValid(inst_state)) { | |
177 *is_legal = FALSE; | |
178 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedInvalid); | |
179 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
180 NaClGetReasonWhyDisallowed(NaClMarkedInvalid))); | |
181 } | |
182 | |
183 /* If there aren't prefix bytes, there isn't anything to check. */ | |
184 if (num_prefix_bytes == 0) return; | |
185 | |
186 /* Don't allow multiple prefix bytes, except for the special | |
187 * case of the pair DATA16 and LOCK (allowed so that one can | |
188 * lock short integers). | |
189 * | |
190 * Note: Explicit NOP sequences that use multiple 66 values are | |
191 * recognized as special cases, and need not be processed here. | |
192 */ | |
193 if (num_prefix_bytes > 1) { | |
194 if ((num_prefix_bytes == 2) && | |
195 (inst_state->prefix_mask & kPrefixDATA16) && | |
196 (inst_state->prefix_mask & kPrefixLOCK)) { | |
197 /* Allow data prefix if lock prefix also given. */ | |
198 } else { | |
199 *is_legal = FALSE; | |
200 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClTooManyPrefixBytes); | |
201 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
202 NaClGetReasonWhyDisallowed(NaClTooManyPrefixBytes))); | |
203 } | |
204 } | |
205 | |
206 /* Only allow REP/REPE/REPZ (F3) prefix if flag specifies it is allowed. */ | |
207 if ((inst_state->prefix_mask & kPrefixREP) && | |
208 (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsRep)))) { | |
209 *is_legal = FALSE; | |
210 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRepDisallowed); | |
211 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
212 NaClGetReasonWhyDisallowed(NaClRepDisallowed))); | |
213 } | |
214 | |
215 /* Only allow REPNE/REPNZ (F2) prefix if flag specifies it is allowed. */ | |
216 if ((inst_state->prefix_mask & kPrefixREPNE) && | |
217 (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsRepne)))) { | |
218 *is_legal = FALSE; | |
219 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRepneDisallowed); | |
220 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
221 NaClGetReasonWhyDisallowed(NaClRepneDisallowed))); | |
222 } | |
223 | |
224 /* Only allow Data16 (66) prefix if flag specifies it is allowed. */ | |
225 if ((inst_state->prefix_mask & kPrefixDATA16) && | |
226 (NACL_EMPTY_IFLAGS == (inst->flags & NACL_IFLAG(OpcodeAllowsData16)))) { | |
227 *is_legal = FALSE; | |
228 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClData16Disallowed); | |
229 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
230 NaClGetReasonWhyDisallowed(NaClData16Disallowed))); | |
231 } | |
232 | |
233 /* Don't allow more than one REX prefix. */ | |
234 if (inst_state->num_rex_prefixes > 1) { | |
235 /* NOTE: does not apply to NOP, since they are parsed using | |
236 * special handling (i.e. explicit byte sequence matches) that | |
237 * doesn't explicitly define prefix bytes. | |
238 * | |
239 * NOTE: We don't disallow this while decoding, since xed doesn't | |
240 * disallow this, and we want to be able to compare our tool | |
241 * to xed. | |
242 */ | |
243 *is_legal = FALSE; | |
244 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMultipleRexPrefix); | |
245 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
246 NaClGetReasonWhyDisallowed(NaClMultipleRexPrefix))); | |
247 } | |
248 | |
249 /* Don't allow shortened address sizes. That is prefix ADDR16. */ | |
250 if (inst_state->prefix_mask & kPrefixADDR16) { | |
251 *is_legal = FALSE; | |
252 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClCantUsePrefix67); | |
253 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
254 NaClGetReasonWhyDisallowed(NaClCantUsePrefix67))); | |
255 } | |
256 | |
257 NaClCheckSegmentPrefixes(state, is_legal, disallows_flags); | |
258 | |
259 /* Don't allow duplicated prefixes. Note: Don't report if multiple | |
260 * REX prefixes has been reported, since we don't know what duplicates | |
261 * caused the problem, and an error has already been reported. | |
262 */ | |
263 if (inst_state->has_prefix_duplicates && | |
264 (NACL_EMPTY_DISALLOWS_FLAGS == | |
265 (*disallows_flags & NACL_DISALLOWS_FLAG(NaClMultipleRexPrefix)))) { | |
266 /* NOTE: does not apply to NOP, since they are parsed using | |
267 * special handling (i.e. explicit byte sequence matches) that | |
268 * doesn't explicitly define prefix bytes. | |
269 * | |
270 * NOTE: We don't disallow this while decoding, since xed doesn't | |
271 * disallow this, and we want to be able to compare our tool | |
272 * to xed. | |
273 */ | |
274 *is_legal = FALSE; | |
275 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClHasDuplicatePrefix); | |
276 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
277 NaClGetReasonWhyDisallowed(NaClHasDuplicatePrefix))); | |
278 } | |
279 | |
280 /* Check the location of the REX prefix, if one is specified.. */ | |
281 if (inst_state->prefix_mask & kPrefixREX) { | |
282 /* First find the locations of the REX prefix. */ | |
283 int i; | |
284 int rex_index = -1; | |
285 for (i = 0; i < inst_state->num_prefix_bytes; ++i) { | |
286 char prefix = inst_state->bytes.byte[i]; | |
287 switch (prefix) { | |
288 case 0x40: | |
289 case 0x41: | |
290 case 0x42: | |
291 case 0x43: | |
292 case 0x44: | |
293 case 0x45: | |
294 case 0x46: | |
295 case 0x47: | |
296 case 0x48: | |
297 case 0x49: | |
298 case 0x4a: | |
299 case 0x4b: | |
300 case 0x4c: | |
301 case 0x4d: | |
302 case 0x4e: | |
303 case 0x4f: | |
304 rex_index = i; | |
305 break; | |
306 default: | |
307 break; | |
308 } | |
309 } | |
310 /* NOTE: REX prefix must be last, unless FO exists. If FO | |
311 * exists, it must be after REX (Intel Manual). | |
312 * | |
313 * NOTE: (karl) It appears that this constraint is violated | |
314 * with compiled code of /bin/ld_static. According to AMD, | |
315 * the rex prefix must be last. | |
316 * | |
317 * For now, we will follow the convention of gcc, which places | |
318 * the LOCK byte in front of the REX byte. | |
319 */ | |
320 if (rex_index >= 0) { | |
321 if ((rex_index + 1) != inst_state->num_prefix_bytes) { | |
322 *is_legal = FALSE; | |
323 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClRexPrefixNotLast); | |
324 } | |
325 } | |
326 } | |
327 } | |
328 | |
329 /* Checks instruction details of the current instruction to see if there | |
330 * are any red flags that make the instruction illegal. | |
331 * | |
332 * Parameters are: | |
333 * state : The current validator state to check. | |
334 * is_legal: Flag set to FALSE if any prefix problems are found. | |
335 * disallows_flags : Set of flags, describing the reason(s) the | |
336 * current instruction in the validator state is not | |
337 * legal in native client. Updated as appropriate. | |
338 */ | |
339 static void NaClCheckIfMarkedIllegal(NaClValidatorState* state, | |
340 Bool* is_legal, | |
341 NaClDisallowsFlags* disallows_flags) { | |
342 if (NACL_IFLAG(NaClIllegal) & state->cur_inst->flags) { | |
343 *is_legal = FALSE; | |
344 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedIllegal); | |
345 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
346 NaClGetReasonWhyDisallowed(NaClMarkedIllegal))); | |
347 } | |
348 | |
349 /* Check other forms to disallow. | |
350 * TODO(karl): Move these checks into the model generator, setting the | |
351 * NaClIllegal flag. Once that is completed, this switch statement can | |
352 * can be removed. | |
353 */ | |
354 switch (state->cur_inst->insttype) { | |
355 case NACLi_RETURN: | |
356 case NACLi_EMMX: | |
357 /* EMMX needs to be supported someday but isn't ready yet. */ | |
358 case NACLi_ILLEGAL: | |
359 case NACLi_SYSTEM: | |
360 case NACLi_RDMSR: | |
361 case NACLi_RDTSCP: | |
362 case NACLi_LONGMODE: | |
363 case NACLi_SVM: | |
364 case NACLi_3BYTE: | |
365 case NACLi_UNDEFINED: | |
366 *is_legal = FALSE; | |
367 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedIllegal); | |
368 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
369 NaClGetReasonWhyDisallowed(NaClMarkedIllegal))); | |
370 break; | |
371 case NACLi_INVALID: | |
372 *is_legal = FALSE; | |
373 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedInvalid); | |
374 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
375 NaClGetReasonWhyDisallowed(NaClMarkedInvalid))); | |
376 break; | |
377 case NACLi_SYSCALL: | |
378 case NACLi_SYSENTER: | |
379 *is_legal = FALSE; | |
380 *disallows_flags |= NACL_DISALLOWS_FLAG(NaClMarkedSystem); | |
381 DEBUG(NaClLog(LOG_INFO, "%s\n", | |
382 NaClGetReasonWhyDisallowed(NaClMarkedSystem))); | |
383 break; | |
384 default: | |
385 break; | |
386 } | |
387 } | |
388 | |
389 /* Prints out error messages describing why the current instruction | |
390 * in the given validator state is not legal in native client. | |
391 * | |
392 * Parameters are: | |
393 * state : The current validator state to check. | |
394 * disallows_flags : Set of flags, describing the reason(s) the | |
395 * current instruction in the validator state is not | |
396 * legal in native client. Updated as appropriate. | |
397 */ | |
398 static void NaClReportWhyNaClIllegal(NaClValidatorState* state, | |
399 NaClDisallowsFlags disallows_flags) { | |
400 if (NACL_EMPTY_DISALLOWS_FLAGS != disallows_flags) { | |
401 int i; | |
402 Bool printed_reason = FALSE; | |
403 NaClInstState* inst_state = state->cur_inst_state; | |
404 /* Print out error message for each reason the instruction is disallowed. */ | |
405 for (i = 0; i < NaClDisallowsFlagEnumSize; ++i) { | |
406 if (disallows_flags & NACL_DISALLOWS_FLAG(i)) { | |
407 const char* why_disallowed = NaClReasonWhyDisallowed(i); | |
408 if (NULL != why_disallowed) { | |
409 printed_reason = TRUE; | |
410 NaClValidatorInstMessage( | |
411 LOG_ERROR, state, inst_state, "%s\n", why_disallowed); | |
412 } | |
413 } | |
414 /* Stop looking if we should quit reporting errors. */ | |
415 if (state->quit) break; | |
416 } | |
417 /* Be sure we print a reason (in case the switch isn't complete). */ | |
418 if (!printed_reason) { | |
419 disallows_flags = NACL_EMPTY_DISALLOWS_FLAGS; | |
420 } | |
421 } | |
422 if (NACL_EMPTY_DISALLOWS_FLAGS == disallows_flags) { | |
423 /* No known reason was recorded, but the instruction was recorded as illegal
. | |
424 * Report that the instruction is not acceptable. | |
425 */ | |
426 NaClValidatorInstMessage(LOG_ERROR, state, state->cur_inst_state, | |
427 "%s\n", kNaClGenericReasonDisallowed); | |
428 } | |
429 } | |
430 | |
431 void NaClValidateInstructionLegal(NaClValidatorState* state) { | |
432 Bool is_legal = TRUE; | |
433 NaClDisallowsFlags disallows_flags = NACL_EMPTY_DISALLOWS_FLAGS; | |
434 DEBUG_OR_ERASE({ | |
435 struct Gio* g = NaClLogGetGio(); | |
436 NaClLog(LOG_INFO, "->NaClValidateInstructionLegal\n"); | |
437 NaClInstPrint(g, state->decoder_tables, | |
438 NaClInstStateInst(state->cur_inst_state)); | |
439 NaClExpVectorPrint(g, state); | |
440 }); | |
441 NaClCheckForPrefixIssues(state, &is_legal, &disallows_flags); | |
442 NaClCheckIfMarkedIllegal(state, &is_legal, &disallows_flags); | |
443 if (!is_legal) { | |
444 NaClReportWhyNaClIllegal(state, disallows_flags); | |
445 } | |
446 DEBUG(NaClLog(LOG_INFO, | |
447 "<-NaClValidateInstructionLegal: is_legal = %"NACL_PRIdBool"\n", | |
448 is_legal)); | |
449 } | |
OLD | NEW |