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

Side by Side Diff: src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.c

Issue 625923004: Delete old x86 validator. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: rebase master Created 6 years, 2 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) 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 }
OLDNEW
« no previous file with comments | « src/trusted/validator/x86/ncval_reg_sfi/nc_illegal.h ('k') | src/trusted/validator/x86/ncval_reg_sfi/nc_jumps.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698