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 |
Brad Chen
2012/10/04 17:26:04
What is this file? Please add a comment.
khim
2012/10/05 08:22:53
Done.
| |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include <string.h> | 12 #include <string.h> |
13 | 13 |
14 #include "native_client/src/trusted/validator_ragel/unreviewed/validator_interna l.h" | 14 #include "native_client/src/trusted/validator_ragel/validator_internal.h" |
15 | 15 |
16 %%{ | 16 %%{ |
17 machine x86_64_validator; | 17 machine x86_64_validator; |
18 alphtype unsigned char; | 18 alphtype unsigned char; |
19 variable p current_position; | 19 variable p current_position; |
20 variable pe end_of_bundle; | 20 variable pe end_of_bundle; |
21 variable eof end_of_bundle; | 21 variable eof end_of_bundle; |
22 variable cs current_state; | 22 variable cs current_state; |
23 | 23 |
24 include byte_machine "byte_machines.rl"; | 24 include byte_machine "byte_machines.rl"; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 process_2_operands_zero_extends(&restricted_register, | 98 process_2_operands_zero_extends(&restricted_register, |
99 &instruction_info_collected, rex_prefix, | 99 &instruction_info_collected, rex_prefix, |
100 operand_states); | 100 operand_states); |
101 } | 101 } |
102 | 102 |
103 include decode_x86_64 "validator_x86_64_instruction.rl"; | 103 include decode_x86_64 "validator_x86_64_instruction.rl"; |
104 | 104 |
105 data16condrep = (data16 | condrep data16 | data16 condrep); | 105 data16condrep = (data16 | condrep data16 | data16 condrep); |
106 data16rep = (data16 | rep data16 | data16 rep); | 106 data16rep = (data16 | rep data16 | data16 rep); |
107 | 107 |
108 # Special %rbp modifications without required sandboxing | 108 # Special %rbp modifications without required sandboxing |
Brad Chen
2012/10/04 17:26:04
This comment is unclear. Why don't these special m
khim
2012/10/05 08:22:53
These special instructions don't require the sandb
| |
109 # | |
110 # Note that there are two different opcodes for “mov”: “mov” with opcode | |
111 # “0x89” moves from “A” to “B” while “mov” with opcode “0x8b” moves from | |
112 # “B” to “A”. | |
109 rbp_modifications = | 113 rbp_modifications = |
110 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp | 114 (b_0100_10x0 0x89 0xe5) | # mov %rsp,%rbp |
111 (b_0100_10x0 0x8b 0xec) # | mov %rsp,%rbp | 115 (b_0100_10x0 0x8b 0xec) # | mov %rsp,%rbp |
112 #(b_0100_1xx0 0x81 0xe5 any{3} (0x80 .. 0xff)) | # and $XXX,%rbp | 116 #(b_0100_1xx0 0x81 0xe5 any{3} (0x80 .. 0xff)) | # and $XXX,%rbp |
113 #(b_0100_1xx0 0x83 0xe5 (0x80 .. 0xff)) # and $XXX,%rbp | 117 #(b_0100_1xx0 0x83 0xe5 (0x80 .. 0xff)) # and $XXX,%rbp |
Brad Chen
2012/10/04 17:26:04
The strange positioning of '|' and '#' and the com
khim
2012/10/05 08:22:53
These instructions are permitted in the similar bl
| |
114 @process_0_operands; | 118 @process_0_operands; |
115 | 119 |
116 # Special instructions used for %rbp sandboxing | 120 # Special instructions used for %rbp sandboxing |
117 rbp_sandboxing = | 121 rbp_sandboxing = |
118 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp | 122 (b_0100_11x0 0x01 0xfd | # add %r15,%rbp |
119 b_0100_10x1 0x03 0xef | # add %r15,%rbp | 123 b_0100_10x1 0x03 0xef | # add %r15,%rbp |
120 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp | 124 0x49 0x8d 0x2c 0x2f | # lea (%r15,%rbp,1),%rbp |
121 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp | 125 0x4a 0x8d 0x6c 0x3d 0x00) # lea 0x0(%rbp,%r15,1),%rbp |
122 @{ if (restricted_register == REG_RBP) | 126 @{ if (restricted_register == REG_RBP) |
123 instruction_info_collected |= RESTRICTED_REGISTER_USED; | 127 instruction_info_collected |= RESTRICTED_REGISTER_USED; |
124 else | 128 else |
125 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; | 129 instruction_info_collected |= UNRESTRICTED_RBP_PROCESSED; |
126 restricted_register = NO_REG; | 130 restricted_register = NO_REG; |
127 BitmapClearBit(valid_targets, (instruction_start - data)); | 131 MakeJumpTargetInvalid((instruction_start - data), valid_targets); |
Brad Chen
2012/10/04 17:26:04
Are you going to make the instruction at the targe
khim
2012/10/05 08:22:53
I have no opinion WRT to the best name. We clear t
| |
128 }; | 132 }; |
129 | 133 |
130 # Special %rbp modifications without required sandboxing | 134 # Special %rbp modifications without required sandboxing |
Brad Chen
2012/10/04 17:26:04
This line begins a section that is extremely simil
khim
2012/10/05 08:22:53
Actually this is just bad comment. Previous one de
| |
135 # | |
136 # Note that there are two different opcodes for “mov”: “mov” with opcode | |
137 # “0x89” moves from “A” to “B” while “mov” with opcode “0x8b” moves from | |
138 # “B” to “A”. | |
131 rsp_modifications = | 139 rsp_modifications = |
132 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp | 140 (b_0100_10x0 0x89 0xec) | # mov %rbp,%rsp |
133 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp | 141 (b_0100_10x0 0x8b 0xe5) | # mov %rbp,%rsp |
134 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp | 142 #(b_0100_1xx0 0x81 0xe4 any{3} (0x80 .. 0xff)) | # and $XXX,%rsp |
135 #Superfluous bits are not supported: | 143 #Superfluous bits are not supported: |
136 # http://code.google.com/p/nativeclient/issues/detail?id=3012 | 144 # http://code.google.com/p/nativeclient/issues/detail?id=3012 |
137 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp | 145 (b_0100_1000 0x83 0xe4 (0x80 .. 0xff)) # and $XXX,%rsp |
138 @process_0_operands; | 146 @process_0_operands; |
139 | 147 |
140 # Special instructions used for %rbp sandboxing | 148 # Special instructions used for %rbp sandboxing |
141 rsp_sandboxing = | 149 rsp_sandboxing = |
142 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp | 150 (b_0100_11x0 0x01 0xfc | # add %r15,%rsp |
143 b_0100_10x1 0x03 0xe7 | # add %r15,%rbp | 151 b_0100_10x1 0x03 0xe7 | # add %r15,%rbp |
144 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp | 152 0x4a 0x8d 0x24 0x3c) # lea (%rsp,%r15,1),%rsp |
145 @{ if (restricted_register == REG_RSP) | 153 @{ if (restricted_register == REG_RSP) |
Brad Chen
2012/10/04 17:26:04
Why isn't this action commented? Please comment al
khim
2012/10/05 08:22:53
Done.
| |
146 instruction_info_collected |= RESTRICTED_REGISTER_USED; | 154 instruction_info_collected |= RESTRICTED_REGISTER_USED; |
147 else | 155 else |
148 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; | 156 instruction_info_collected |= UNRESTRICTED_RSP_PROCESSED; |
149 restricted_register = NO_REG; | 157 restricted_register = NO_REG; |
150 BitmapClearBit(valid_targets, (instruction_start - data)); | 158 MakeJumpTargetInvalid((instruction_start - data), valid_targets); |
151 }; | 159 }; |
152 | 160 |
153 # naclcall or nacljmp. Note: first "and $~0x1f, %eXX" is a normal instruction | 161 # naclcall or nacljmp. These are indirect-jump sequences. They include three |
Brad Chen
2012/10/04 17:26:04
Before getting into any specific instructions ther
khim
2012/10/05 08:22:53
This is validator_internals.html.
| |
154 # and as such will detect case where %rbp/%rsp is illegally modified. | 162 # commands: |
Brad Chen
2012/10/04 17:26:04
How about "These are three-instruction indirection
khim
2012/10/05 08:22:53
Done.
| |
163 # and “and $~0x1f, %eXX” | |
Brad Chen
2012/10/04 17:26:04
Why repeat the opcode "and" helpful in these comme
khim
2012/10/05 08:22:53
Tried to make easier to see that third command may
| |
164 # add “and RBASE, %rXX” | |
165 # jmpq “*%rXX” or callq “*%rXX” | |
166 # Note: first "and $~0x1f, %eXX" is a normal instruction and as such will | |
167 # detect case where %rbp/%rsp is illegally modified. | |
Brad Chen
2012/10/04 17:26:04
Who will detect this case? I don't understand the
khim
2012/10/05 08:22:53
When this ragel machine will be combined with norm
| |
168 # | |
169 # There are number of variants present which differ by the REX prefix usage: | |
Brad Chen
2012/10/04 17:26:04
Where are the variants?
khim
2012/10/05 08:22:53
Below. Should I write that?
| |
170 # we need to make sure “%eXX” in “and”, “%rXX” in “add”, and “%eXX” in “jmpq” | |
171 # or “callq” is the same register and it's much simpler to do if one single | |
172 # action handles only fixed number of bytes. | |
173 # | |
174 # Additional complication arises because x86-64 contains two different “add” | |
175 # instruction: with “0x01” and “0x03” opcode. Both are in use in the wild | |
Brad Chen
2012/10/04 17:26:04
Please avoid colorful language such as "in use in
khim
2012/10/05 08:22:53
The only question is: how to determine if I wrote
| |
176 # thus we can not support just one form. They differ in the direction used: | |
177 # both can add “A” and “B” but one of them stores the result in “A” and other | |
178 # stores the result in “B” (see AMD/Intel manual for clarification). | |
179 # | |
180 # REGISTER USAGE ABBREVIATIONS: | |
181 # E32: legacy ia32 registers (all eight: %eax to %edi) | |
182 # R32: 64-bit counterparts for legacy 386 registers (%rax to %rdi) | |
183 # R64: new amd64 registers (only seven: %r8 to %r14) | |
184 # R32: 32-bit counterparts for new amd64 registers (%r8d to %r14d) | |
Brad Chen
2012/10/04 17:26:04
You have defined R32 twice. I think you mean "E32"
khim
2012/10/05 08:22:53
Yes, and done.
| |
185 # RBASE: %r15 (used as “base of untrusted world” in NaCl for amd64) | |
155 naclcall_or_nacljmp = | 186 naclcall_or_nacljmp = |
156 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi | 187 # This block encodes call and jump instructions of the form: |
188 # 0: 83 e_ e0 and $~0x1f,E32 | |
189 # 3: 4_ 01 f_ add RBASE,R32 | |
190 # 6: ff e_ jmpq *R32 | |
191 #### INSTRUCTION ONE (three bytes) | |
192 # and $~0x1f, E32 | |
157 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 | 193 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 |
158 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 194 #### INSTRUCTION TWO (three bytes) |
195 # add RBASE, R32 (0x01 opcode) | |
159 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) | 196 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) |
160 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 197 #### INSTRUCTION THREE.c (three bytes plus optional REX prefix) |
Brad Chen
2012/10/04 17:26:04
three or two bytes?
khim
2012/10/05 08:22:53
Done.
| |
198 # callq R32 | |
161 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | | 199 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | |
162 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 200 #### INSTRUCTION THREE.j (three bytes plus optional REX prefix) |
Brad Chen
2012/10/04 17:26:04
Shouldn't 'three' be 'two' here too? Looks like 'j
khim
2012/10/05 08:22:53
Replaced "j" with "jmp".
Now it's "INSTRUCTION TH
| |
201 # jmpq R32 | |
163 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | 202 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) |
203 # This action first compares register numbers in three atomic instructions | |
Brad Chen
2012/10/04 17:26:04
What do you mean by 'atomic instructions'? That me
khim
2012/10/05 08:22:53
atomic -> component.
| |
204 # described above, then it redefines the range of the super-instruction to | |
205 # include the preceding sandboxing sequence and invalidates jump targets on | |
206 # the interior of the super-instructions and finally clears “the restricted | |
207 # register” variable. | |
208 # | |
209 # “Magic numbers” correspond to the structure of this particular variant of | |
210 # the superinstruction. | |
Brad Chen
2012/10/04 17:26:04
Please be consistent; use either 'super-instructio
khim
2012/10/05 08:22:53
Done.
| |
164 @{ | 211 @{ |
165 instruction_start -= 6; | 212 instruction_start -= 6; |
166 if (RMFromModRM(instruction_start[1]) != | 213 if (RMFromModRM(instruction_start[1]) != |
167 RMFromModRM(instruction_start[5]) || | 214 RMFromModRM(instruction_start[5]) || |
168 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) | 215 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) |
169 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | 216 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; |
170 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 217 MakeJumpTargetInvalid((instruction_start - data) + 3, valid_targets); |
171 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 218 MakeJumpTargetInvalid((instruction_start - data) + 6, valid_targets); |
172 restricted_register = NO_REG; | 219 restricted_register = NO_REG; |
173 } | | 220 } | |
174 | 221 |
175 # and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi | 222 # This block encodes call and jump instructions of the form: |
223 # 0: 83 e_ e0 and $~0x1f,E32 | |
224 # 3: 4_ 03 f_ add RBASE,R32 | |
225 # 6: ff e_ jmpq *R32 | |
226 #### INSTRUCTION ONE (three bytes) | |
227 # and $~0x1f, E32 | |
176 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 | 228 (0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 |
177 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 229 #### INSTRUCTION TWO (three bytes) |
230 # add RBASE, R32 (0x03 opcode) | |
178 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) | 231 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) |
179 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 232 #### INSTRUCTION THREE.c (three bytes plus optional REX prefix) |
Brad Chen
2012/10/04 17:26:04
Here again I think you mean 'two' instead of 'thre
khim
2012/10/05 08:22:53
Done.
| |
233 # callq R32 | |
180 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | | 234 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | |
181 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 235 #### INSTRUCTION THREE.j (three bytes plus optional REX prefix) |
236 # jmpq R32 | |
182 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | 237 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) |
238 # This action first compares register numbers in three atomic instructions | |
239 # described above, then it redefines the range of the super-instruction to | |
240 # include the preceding sandboxing sequence and invalidates jump targets on | |
241 # the interior of the super-instructions and finally clears “the restricted | |
242 # register” variable. | |
243 # | |
244 # “Magic numbers” correspond to the structure of this particular variant of | |
245 # the superinstruction. | |
Brad Chen
2012/10/04 17:26:04
This action is identical to the previous action. P
khim
2012/10/05 08:22:53
All actions are different: where actions are ident
| |
183 @{ | 246 @{ |
184 instruction_start -= 6; | 247 instruction_start -= 6; |
185 if (RMFromModRM(instruction_start[1]) != | 248 if (RMFromModRM(instruction_start[1]) != |
186 RegFromModRM(instruction_start[5]) || | 249 RegFromModRM(instruction_start[5]) || |
187 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) | 250 RMFromModRM(instruction_start[1]) != RMFromModRM(*current_position)) |
188 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | 251 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; |
189 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 252 MakeJumpTargetInvalid((instruction_start - data) + 3, valid_targets); |
190 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 253 MakeJumpTargetInvalid((instruction_start - data) + 6, valid_targets); |
191 restricted_register = NO_REG; | 254 restricted_register = NO_REG; |
192 } | | 255 } | |
193 | 256 |
194 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi | 257 # This block encodes call and jump instructions of the form: |
258 # 0: 4_ 83 e_ e0 and $~0x1f,E32 | |
259 # 4: 4_ 01 f_ add RBASE,R32 | |
260 # 7: ff e_ jmpq *R32 | |
261 #### INSTRUCTION ONE (four bytes) | |
262 # and $~0x1f, E32 | |
195 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 | 263 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 |
196 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 264 #### INSTRUCTION TWO (three bytes) |
265 # add RBASE, R32 (0x01 opcode) | |
197 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) | 266 b_0100_11x0 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe|0xff) |
198 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 267 #### INSTRUCTION THREE.c (three bytes plus optional REX prefix) |
268 # callq R32 | |
199 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | | 269 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | |
200 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 270 # jmpq R32 |
201 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | | 271 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | |
202 | 272 |
203 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d | 273 # This block encodes call and jump instructions of the form: |
274 # 0: 4_ 83 e_ e0 and $~0x1f,E64 | |
275 # 4: 4_ 01 f_ add RBASE,R64 | |
276 # 7: 4_ ff e_ jmpq *R64 | |
277 #### INSTRUCTION ONE (four bytes) | |
278 # and $~0x1f, E64 | |
204 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 | 279 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 |
205 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d | 280 #### INSTRUCTION TWO (three bytes) |
281 # add RBASE, R64 (0x01 opcode) | |
206 b_0100_11x1 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe) | 282 b_0100_11x1 0x01 (0xf8|0xf9|0xfa|0xfb|0xfc|0xfd|0xfe) |
207 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 | 283 #### INSTRUCTION THREE.c (four bytes) |
284 # callq R64 | |
208 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | | 285 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | |
209 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 | 286 #### INSTRUCTION THREE.j (four bytes) |
287 # jmpq R64 | |
210 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) | 288 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) |
289 # This action first compares register numbers in three atomic instructions | |
290 # described above, then it redefines the range of the super-instruction to | |
291 # include the preceding sandboxing sequence and invalidates jump targets on | |
292 # the interior of the super-instructions and finally clears “the restricted | |
293 # register” variable. | |
294 # | |
295 # “Magic numbers” correspond to the structure of this particular variant of | |
296 # the superinstruction (we group actions with identical “magic numbers”). | |
211 @{ | 297 @{ |
Brad Chen
2012/10/04 17:26:04
This is much too repetitive. You are increasing my
khim
2012/10/05 08:22:53
You can not make the description of the instructio
| |
212 instruction_start -= 7; | 298 instruction_start -= 7; |
213 if (RMFromModRM(instruction_start[2]) != | 299 if (RMFromModRM(instruction_start[2]) != |
214 RMFromModRM(instruction_start[6]) || | 300 RMFromModRM(instruction_start[6]) || |
215 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) | 301 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) |
216 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | 302 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; |
217 BitmapClearBit(valid_targets, (instruction_start - data) + 4); | 303 MakeJumpTargetInvalid((instruction_start - data) + 4, valid_targets); |
218 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 304 MakeJumpTargetInvalid((instruction_start - data) + 7, valid_targets); |
219 restricted_register = NO_REG; | 305 restricted_register = NO_REG; |
220 } | | 306 } | |
221 | 307 |
222 # rex.R?X? and $~0x1f, %eax/%ecx/%edx/%ebx/%esp/%ebp/%esi/%edi | 308 # This block encodes call and jump instructions of the form: |
Brad Chen
2012/10/04 17:26:04
Here I think you mean "super-instruction" not "ins
khim
2012/10/05 08:22:53
Done.
| |
309 # 0: 4_ 83 e_ e0 and $~0x1f,E32 | |
310 # 4: 4_ 03 f_ add RBASE,R32 | |
311 # 7: ff e_ jmpq *R32 | |
312 #### INSTRUCTION ONE (four bytes) | |
313 # and $~0x1f, E32 | |
223 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 | 314 ((REX_RX 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7) 0xe0 |
224 # add %r15,%rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 315 #### INSTRUCTION TWO (three bytes) |
316 # add RBASE, R32 (0x03 opcode) | |
225 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) | 317 b_0100_10x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7|0xff) |
226 # callq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 318 #### INSTRUCTION THREE.c (three bytes plus optional REX prefix) |
Brad Chen
2012/10/04 17:26:04
'two'?
khim
2012/10/05 08:22:53
Done.
| |
319 # callq R32 | |
227 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | | 320 ((REX_WRX? 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6|0xd7)) | |
228 # jmpq %rax/%rcx/%rdx/%rbx/%rsp/%rbp/%rsi/%rdi | 321 # jmpq R32 |
229 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | | 322 (REX_WRX? 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6|0xe7)))) | |
Brad Chen
2012/10/04 17:26:04
It's really hard to figure out what parenthetical
khim
2012/10/05 08:22:53
Indeed: indentation was mixed up, sorry.
Fixed.
| |
230 | 323 |
231 # and $~0x1f, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d | 324 # This block encodes call and jump instructions of the form: |
325 # 0: 4_ 83 e_ e0 and $~0x1f,E64 | |
326 # 4: 4_ 03 f_ add RBASE,R64 | |
327 # 7: 4_ ff e_ jmpq *R64 | |
328 #### INSTRUCTION ONE (four bytes) | |
329 # and $~0x1f, E64 | |
232 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 | 330 (b_0100_0xx1 0x83 (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6) 0xe0 |
233 # add %r15, %r8d/%r9d/%r10d/%r11d/%r12d/%r13d/%r14d | 331 #### INSTRUCTION TWO (three bytes) |
332 # add RBASE, R64 (0x03 opcode) | |
234 b_0100_11x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7) | 333 b_0100_11x1 0x03 (0xc7|0xcf|0xd7|0xdf|0xe7|0xef|0xf7) |
235 # callq %r8/%r9/%r10/%r11/%r12/%r13/%r14 | 334 #### INSTRUCTION THREE.c (four bytes) |
335 # callq R64 | |
236 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | | 336 ((b_0100_xxx1 0xff (0xd0|0xd1|0xd2|0xd3|0xd4|0xd5|0xd6)) | |
237 # jmpq %r8/%r9/%r10/%r11/%r12/%r13/%r14 | 337 #### INSTRUCTION THREE.j (four bytes) |
338 # jmpq R64 | |
238 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) | 339 (b_0100_xxx1 0xff (0xe0|0xe1|0xe2|0xe3|0xe4|0xe5|0xe6))))) |
340 # This action first compares register numbers in three atomic instructions | |
Brad Chen
2012/10/04 17:26:04
Every place you find yourself repeating a comment
khim
2012/10/05 08:22:53
Done.
| |
341 # described above, then it redefines the range of the super-instruction to | |
342 # include the preceding sandboxing sequence and invalidates jump targets on | |
343 # the interior of the super-instructions and finally clears “the restricted | |
344 # register” variable. | |
345 # | |
346 # “Magic numbers” correspond to the structure of this particular variant of | |
347 # the superinstruction (we group actions with identical “magic numbers”). | |
239 @{ | 348 @{ |
240 instruction_start -= 7; | 349 instruction_start -= 7; |
241 if (RMFromModRM(instruction_start[2]) != | 350 if (RMFromModRM(instruction_start[2]) != |
242 RegFromModRM(instruction_start[6]) || | 351 RegFromModRM(instruction_start[6]) || |
243 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) | 352 RMFromModRM(instruction_start[2]) != RMFromModRM(*current_position)) |
244 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; | 353 instruction_info_collected |= UNRECOGNIZED_INSTRUCTION; |
245 BitmapClearBit(valid_targets, (instruction_start - data) + 4); | 354 MakeJumpTargetInvalid((instruction_start - data) + 4, valid_targets); |
246 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 355 MakeJumpTargetInvalid((instruction_start - data) + 7, valid_targets); |
247 restricted_register = NO_REG; | 356 restricted_register = NO_REG; |
248 }; | 357 }; |
249 | 358 |
250 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand | 359 # EMMS/SSE2/AVX instructions which have implicit %ds:(%rsi) operand |
251 # maskmovq %mmX,%mmY | 360 # maskmovq %mmX,%mmY |
252 maskmovq = | 361 maskmovq = |
253 REX_WRXB? (0x0f 0xf7) | 362 REX_WRXB? (0x0f 0xf7) |
254 @CPUFeature_EMMX modrm_registers; | 363 @CPUFeature_EMMX modrm_registers; |
255 # maskmovdqu %xmmX, %xmmY | 364 # maskmovdqu %xmmX, %xmmY |
256 maskmovdqu = | 365 maskmovdqu = |
(...skipping 25 matching lines...) Expand all Loading... | |
282 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) | 391 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) |
283 string_instruction_rsi_rdi = | 392 string_instruction_rsi_rdi = |
284 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi) | 393 condrep? 0xa6 | # cmpsb %es:(%rdi),%ds:(%rsi) |
285 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi) | 394 data16condrep 0xa7 | # cmpsw %es:(%rdi),%ds:(%rsi) |
286 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi) | 395 condrep? REXW_NONE? 0xa7 | # cmps[lq] %es:(%rdi),%ds:(%rsi) |
287 | 396 |
288 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi) | 397 rep? 0xa4 | # movsb %es:(%rdi),%ds:(%rsi) |
289 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi) | 398 data16rep 0xa5 | # movsw %es:(%rdi),%ds:(%rsi) |
290 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi) | 399 rep? REXW_NONE? 0xa5 ; # movs[lq] %es:(%rdi),%ds:(%rsi) |
291 | 400 |
401 # Superinstruction which handle instructions which require sandboxed %rsi. | |
402 # | |
403 # There are two variants which handle spurious REX prefixes. | |
Brad Chen
2012/10/04 17:26:04
In what sense are the REX prefixes spurious? This
khim
2012/10/05 08:22:53
They don't change the meaning of the instruction b
| |
404 # | |
405 # Note that both “0x89 0xf6” and “0x8b 0xf6” encode “mov %esi,%esi”: | |
406 # “mov” with opcode “0x89” moves from “A” to “B” while “mov” with opcode | |
407 # “0x8b” moves from “B” to “A” but when “A” and “B” happen to denote the | |
408 # same register there are no functional difference between these opcodes. | |
292 sandbox_instruction_rsi_no_rdi = | 409 sandbox_instruction_rsi_no_rdi = |
293 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 410 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
Brad Chen
2012/10/04 17:26:04
What does '.' mean here? How is it different from
khim
2012/10/05 08:22:53
"." means concatenation which is default action, t
| |
294 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 411 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
295 string_instruction_rsi_no_rdi | 412 string_instruction_rsi_no_rdi |
413 # This action redefines the range of the super-instruction to include the | |
Brad Chen
2012/10/04 17:26:04
This same identical comment is repeated at least f
khim
2012/10/05 08:22:53
Done.
| |
414 # preceding sandboxing sequence then invalidates jump targets on the | |
415 # interior of the super-instructions and finally clears “the restricted | |
416 # register” variable. | |
417 # | |
418 # “Magic numbers” correspond to the structure of this particular variant of | |
419 # the superinstruction. | |
296 @{ | 420 @{ |
297 instruction_start -= 6; | 421 instruction_start -= 6; |
298 BitmapClearBit(valid_targets, (instruction_start - data) + 2); | 422 MakeJumpTargetInvalid((instruction_start - data) + 2, valid_targets); |
299 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 423 MakeJumpTargetInvalid((instruction_start - data) + 6, valid_targets); |
300 restricted_register = NO_REG; | 424 restricted_register = NO_REG; |
301 } | | 425 } | |
302 | 426 |
303 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 427 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
304 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 428 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
305 string_instruction_rsi_no_rdi | 429 string_instruction_rsi_no_rdi |
430 # This action redefines the range of the super-instruction to include the | |
431 # preceding sandboxing sequence then invalidates jump targets on the | |
432 # interior of the super-instructions and finally clears “the restricted | |
433 # register” variable. | |
434 # | |
435 # “Magic numbers” correspond to the structure of this particular variant of | |
436 # the superinstruction. | |
306 @{ | 437 @{ |
307 instruction_start -= 7; | 438 instruction_start -= 7; |
308 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 439 MakeJumpTargetInvalid((instruction_start - data) + 3, valid_targets); |
309 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 440 MakeJumpTargetInvalid((instruction_start - data) + 7, valid_targets); |
310 restricted_register = NO_REG; | 441 restricted_register = NO_REG; |
311 }; | 442 }; |
312 | 443 |
444 # Superinstruction which handle instructions which require sandboxed %rdi. | |
445 # | |
446 # There are two variants which handle spurious REX prefixes. | |
447 # | |
448 # Note that both “0x89 0xff” and “0x8b 0xff” encode “mov %edi,%edi”: | |
449 # “mov” with opcode “0x89” moves from “A” to “B” while “mov” with opcode | |
450 # “0x8b” moves from “B” to “A” but when “A” and “B” happen to denote the | |
451 # same register there are no functional difference between these opcodes. | |
313 sandbox_instruction_rdi_no_rsi = | 452 sandbox_instruction_rdi_no_rsi = |
314 (0x89 | 0x8b) 0xff . # mov %edi,%edi | 453 (0x89 | 0x8b) 0xff . # mov %edi,%edi |
315 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 454 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
316 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) | 455 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) |
456 # This action redefines the range of the super-instruction to include the | |
457 # preceding sandboxing sequence then invalidates jump targets on the | |
458 # interior of the super-instructions and finally clears “the restricted | |
459 # register” variable. | |
460 # | |
461 # “Magic numbers” correspond to the structure of this particular variant of | |
462 # the superinstruction. | |
317 @{ | 463 @{ |
318 instruction_start -= 6; | 464 instruction_start -= 6; |
319 BitmapClearBit(valid_targets, (instruction_start - data) + 2); | 465 MakeJumpTargetInvalid((instruction_start - data) + 2, valid_targets); |
320 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 466 MakeJumpTargetInvalid((instruction_start - data) + 6, valid_targets); |
321 restricted_register = NO_REG; | 467 restricted_register = NO_REG; |
322 } | | 468 } | |
323 | 469 |
324 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi | 470 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi |
325 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 471 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
326 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) | 472 (string_instruction_rdi_no_rsi | mmx_sse_rdi_instruction) |
473 # This action redefines the range of the super-instruction to include the | |
474 # preceding sandboxing sequence then invalidates jump targets on the | |
475 # interior of the super-instructions and finally clears “the restricted | |
476 # register” variable. | |
477 # | |
478 # “Magic numbers” correspond to the structure of this particular variant of | |
479 # the superinstruction. | |
327 @{ | 480 @{ |
328 instruction_start -= 7; | 481 instruction_start -= 7; |
329 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 482 MakeJumpTargetInvalid((instruction_start - data) + 3, valid_targets); |
330 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 483 MakeJumpTargetInvalid((instruction_start - data) + 7, valid_targets); |
331 restricted_register = NO_REG; | 484 restricted_register = NO_REG; |
332 }; | 485 }; |
333 | 486 |
334 | 487 |
335 # String instructions which use both %ds:(%rsi) and %ds:(%rdi) | 488 # Superinstruction which handle instructions which require both sandboxed %rsi |
489 # and sandboxed %rdi. | |
490 # | |
491 # There are four variants which handle spurious REX prefixes. | |
492 # | |
493 # Note that both “0x89 0xf6” and “0x8b 0xf6” encode “mov %esi,%esi” while both | |
494 # “0x89 0xff” and “0x8b 0xff” encode “mov %edi,%edi”: “mov” with opcode “0x89” | |
495 # moves from “A” to “B” while “mov” with opcode “0x8b” moves from “B” to “A” | |
496 # but when “A” and “B” happen to denote the same register there are no | |
497 # functional difference between these opcodes. | |
336 sandbox_instruction_rsi_rdi = | 498 sandbox_instruction_rsi_rdi = |
337 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 499 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
338 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 500 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
339 (0x89 | 0x8b) 0xff . # mov %edi,%edi | 501 (0x89 | 0x8b) 0xff . # mov %edi,%edi |
340 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 502 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
341 string_instruction_rsi_rdi | 503 string_instruction_rsi_rdi |
504 # This action redefines the range of the super-instruction to include the | |
505 # preceding sandboxing sequence then invalidates jump targets on the | |
506 # interior of the super-instructions and finally clears “the restricted | |
507 # register” variable. | |
508 # | |
509 # “Magic numbers” correspond to the structure of this particular variant of | |
510 # the superinstruction. | |
342 @{ | 511 @{ |
343 instruction_start -= 12; | 512 instruction_start -= 12; |
344 BitmapClearBit(valid_targets, (instruction_start - data) + 2); | 513 MakeJumpTargetInvalid((instruction_start - data) + 2, valid_targets); |
345 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 514 MakeJumpTargetInvalid((instruction_start - data) + 6, valid_targets); |
346 BitmapClearBit(valid_targets, (instruction_start - data) + 8); | 515 MakeJumpTargetInvalid((instruction_start - data) + 8, valid_targets); |
347 BitmapClearBit(valid_targets, (instruction_start - data) + 12); | 516 MakeJumpTargetInvalid((instruction_start - data) + 12, valid_targets); |
348 restricted_register = NO_REG; | 517 restricted_register = NO_REG; |
349 } | | 518 } | |
350 | 519 |
351 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 520 (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
352 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 521 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
353 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi | 522 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi |
354 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 523 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
355 string_instruction_rsi_rdi | 524 string_instruction_rsi_rdi |
525 # This action redefines the range of the super-instruction to include the | |
526 # preceding sandboxing sequence then invalidates jump targets on the | |
527 # interior of the super-instructions and finally clears “the restricted | |
528 # register” variable. | |
529 # | |
530 # “Magic numbers” correspond to the structure of this particular variant of | |
531 # the superinstruction. | |
356 @{ | 532 @{ |
357 instruction_start -= 13; | 533 instruction_start -= 13; |
358 BitmapClearBit(valid_targets, (instruction_start - data) + 2); | 534 MakeJumpTargetInvalid((instruction_start - data) + 2, valid_targets); |
359 BitmapClearBit(valid_targets, (instruction_start - data) + 6); | 535 MakeJumpTargetInvalid((instruction_start - data) + 6, valid_targets); |
360 BitmapClearBit(valid_targets, (instruction_start - data) + 9); | 536 MakeJumpTargetInvalid((instruction_start - data) + 9, valid_targets); |
361 BitmapClearBit(valid_targets, (instruction_start - data) + 13); | 537 MakeJumpTargetInvalid((instruction_start - data) + 13, valid_targets); |
362 restricted_register = NO_REG; | 538 restricted_register = NO_REG; |
363 } | | 539 } | |
364 | 540 |
365 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 541 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
366 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 542 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
367 (0x89 | 0x8b) 0xff . # mov %edi,%edi | 543 (0x89 | 0x8b) 0xff . # mov %edi,%edi |
368 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 544 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
369 string_instruction_rsi_rdi | 545 string_instruction_rsi_rdi |
546 # This action redefines the range of the super-instruction to include the | |
547 # preceding sandboxing sequence then invalidates jump targets on the | |
548 # interior of the super-instructions and finally clears “the restricted | |
549 # register” variable. | |
550 # | |
551 # “Magic numbers” correspond to the structure of this particular variant of | |
552 # the superinstruction. | |
370 @{ | 553 @{ |
371 instruction_start -= 13; | 554 instruction_start -= 13; |
372 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 555 MakeJumpTargetInvalid((instruction_start - data) + 3, valid_targets); |
373 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 556 MakeJumpTargetInvalid((instruction_start - data) + 7, valid_targets); |
374 BitmapClearBit(valid_targets, (instruction_start - data) + 9); | 557 MakeJumpTargetInvalid((instruction_start - data) + 9, valid_targets); |
375 BitmapClearBit(valid_targets, (instruction_start - data) + 13); | 558 MakeJumpTargetInvalid((instruction_start - data) + 13, valid_targets); |
376 restricted_register = NO_REG; | 559 restricted_register = NO_REG; |
377 } | | 560 } | |
378 | 561 |
379 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi | 562 REX_X (0x89 | 0x8b) 0xf6 . # mov %esi,%esi |
380 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi | 563 0x49 0x8d 0x34 0x37 . # lea (%r15,%rsi,1),%rsi |
381 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi | 564 REX_X (0x89 | 0x8b) 0xff . # mov %edi,%edi |
382 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi | 565 0x49 0x8d 0x3c 0x3f . # lea (%r15,%rdi,1),%rdi |
383 string_instruction_rsi_rdi | 566 string_instruction_rsi_rdi |
567 # This action redefines the range of the super-instruction to include the | |
568 # preceding sandboxing sequence then invalidates jump targets on the | |
569 # interior of the super-instructions and finally clears “the restricted | |
570 # register” variable. | |
571 # | |
572 # “Magic numbers” correspond to the structure of this particular variant of | |
573 # the superinstruction. | |
384 @{ | 574 @{ |
385 instruction_start -= 14; | 575 instruction_start -= 14; |
386 BitmapClearBit(valid_targets, (instruction_start - data) + 3); | 576 MakeJumpTargetInvalid((instruction_start - data) + 3, valid_targets); |
387 BitmapClearBit(valid_targets, (instruction_start - data) + 7); | 577 MakeJumpTargetInvalid((instruction_start - data) + 7, valid_targets); |
388 BitmapClearBit(valid_targets, (instruction_start - data) + 10); | 578 MakeJumpTargetInvalid((instruction_start - data) + 10, valid_targets); |
389 BitmapClearBit(valid_targets, (instruction_start - data) + 14); | 579 MakeJumpTargetInvalid((instruction_start - data) + 14, valid_targets); |
390 restricted_register = NO_REG; | 580 restricted_register = NO_REG; |
391 }; | 581 }; |
392 | 582 |
393 special_instruction = | 583 special_instruction = |
394 (rbp_modifications | | 584 (rbp_modifications | |
395 rsp_modifications | | 585 rsp_modifications | |
396 rbp_sandboxing | | 586 rbp_sandboxing | |
397 rsp_sandboxing | | 587 rsp_sandboxing | |
398 naclcall_or_nacljmp | | 588 naclcall_or_nacljmp | |
399 sandbox_instruction_rsi_no_rdi | | 589 sandbox_instruction_rsi_no_rdi | |
400 sandbox_instruction_rdi_no_rsi | | 590 sandbox_instruction_rdi_no_rsi | |
401 sandbox_instruction_rsi_rdi) | 591 sandbox_instruction_rsi_rdi) |
402 @{ | 592 @{ |
403 instruction_info_collected |= SPECIAL_INSTRUCTION; | 593 instruction_info_collected |= SPECIAL_INSTRUCTION; |
404 }; | 594 }; |
405 | 595 |
406 # Remove special instructions which are only allowed in special cases. | 596 # Remove special instructions which are only allowed in special cases. |
407 normal_instruction = one_instruction - special_instruction; | 597 normal_instruction = one_instruction - special_instruction; |
408 | 598 |
409 # Check if call is properly aligned | 599 # Check if call is properly aligned. |
600 # | |
601 # For direct call we explicitly encode all variations. For indirect call | |
602 # we accept all the special instructions which ends with indirect call. | |
410 call_alignment = | 603 call_alignment = |
411 ((normal_instruction & | 604 ((normal_instruction & |
412 # Direct call | 605 # Direct call |
413 ((data16 REX_RXB? 0xe8 rel16) | | 606 ((data16 REX_RXB? 0xe8 rel16) | |
414 (REX_WRXB? 0xe8 rel32) | | 607 (REX_WRXB? 0xe8 rel32) | |
415 (data16 REXW_RXB 0xe8 rel32))) | | 608 (data16 REXW_RXB 0xe8 rel32))) | |
416 (special_instruction & | 609 (special_instruction & |
417 # Indirect call | 610 # Indirect call |
418 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* & | 611 (any* data16? REX_WRXB? 0xff ((opcode_2 | opcode_3) any* & |
419 (modrm_memory | modrm_registers))))) | 612 (modrm_memory | modrm_registers))))) |
420 @{ | 613 @{ |
421 if (((current_position - data) & kBundleMask) != kBundleMask) | 614 if (((current_position - data) & kBundleMask) != kBundleMask) |
422 instruction_info_collected |= BAD_CALL_ALIGNMENT; | 615 instruction_info_collected |= BAD_CALL_ALIGNMENT; |
423 }; | 616 }; |
424 | 617 |
425 | 618 |
426 main := ((call_alignment | normal_instruction | special_instruction) | 619 main := ((call_alignment | normal_instruction | special_instruction) |
427 >{ | 620 >{ |
428 BitmapSetBit(valid_targets, current_position - data); | 621 MakeJumpTargetValid(current_position - data, valid_targets); |
429 } | 622 } |
430 @{ | 623 @{ |
431 if ((instruction_info_collected & | 624 if ((instruction_info_collected & |
432 (VALIDATION_ERRORS_MASK | BAD_CALL_ALIGNMENT)) || | 625 (VALIDATION_ERRORS_MASK | BAD_CALL_ALIGNMENT)) || |
433 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) { | 626 (options & CALL_USER_CALLBACK_ON_EACH_INSTRUCTION)) { |
434 result &= user_callback( | 627 result &= user_callback( |
435 instruction_start, current_position, | 628 instruction_start, current_position, |
436 instruction_info_collected | | 629 instruction_info_collected | |
437 ((restricted_register << RESTRICTED_REGISTER_SHIFT) & | 630 ((restricted_register << RESTRICTED_REGISTER_SHIFT) & |
438 RESTRICTED_REGISTER_MASK), callback_data); | 631 RESTRICTED_REGISTER_MASK), callback_data); |
439 } | 632 } |
440 /* On successful match the instruction start must point to the next byte | 633 /* On successful match the instruction start must point to the next byte |
441 * to be able to report the new offset as the start of instruction | 634 * to be able to report the new offset as the start of instruction |
442 * causing error. */ | 635 * causing error. */ |
443 instruction_start = current_position + 1; | 636 instruction_start = current_position + 1; |
444 instruction_info_collected = 0; | 637 instruction_info_collected = 0; |
445 SET_REX_PREFIX(FALSE); | 638 SET_REX_PREFIX(FALSE); |
639 /* Top three bis of VEX2 are inverted: see AMD/Intel manual. */ | |
446 SET_VEX_PREFIX2(0xe0); | 640 SET_VEX_PREFIX2(0xe0); |
447 SET_VEX_PREFIX3(0x00); | 641 SET_VEX_PREFIX3(0x00); |
448 operand_states = 0; | 642 operand_states = 0; |
449 })* | 643 })* |
450 $err{ | 644 $err{ |
451 result &= user_callback(instruction_start, current_position, | 645 result &= user_callback(instruction_start, current_position, |
452 UNRECOGNIZED_INSTRUCTION, callback_data); | 646 UNRECOGNIZED_INSTRUCTION, callback_data); |
453 continue; | 647 continue; |
454 }; | 648 }; |
455 | 649 |
456 }%% | 650 }%% |
457 | 651 |
458 %% write data; | 652 %% write data; |
459 | 653 |
460 Bool ValidateChunkAMD64(const uint8_t *data, size_t size, | 654 Bool ValidateChunkAMD64(const uint8_t *data, size_t size, |
461 enum validation_options options, | 655 enum validation_options options, |
462 const NaClCPUFeaturesX86 *cpu_features, | 656 const NaClCPUFeaturesX86 *cpu_features, |
463 validation_callback_func user_callback, | 657 ValidationCallbackFunc user_callback, |
464 void *callback_data) { | 658 void *callback_data) { |
465 bitmap_word valid_targets_small; | 659 bitmap_word valid_targets_small; |
466 bitmap_word jump_dests_small; | 660 bitmap_word jump_dests_small; |
467 bitmap_word *valid_targets; | 661 bitmap_word *valid_targets; |
468 bitmap_word *jump_dests; | 662 bitmap_word *jump_dests; |
469 const uint8_t *current_position; | 663 const uint8_t *current_position; |
470 const uint8_t *end_of_bundle; | 664 const uint8_t *end_of_bundle; |
471 int result = TRUE; | 665 int result = TRUE; |
472 | 666 |
473 CHECK(sizeof valid_targets_small == sizeof jump_dests_small); | 667 CHECK(sizeof valid_targets_small == sizeof jump_dests_small); |
(...skipping 26 matching lines...) Expand all Loading... | |
500 current_position = end_of_bundle, | 694 current_position = end_of_bundle, |
501 end_of_bundle = current_position + kBundleSize) { | 695 end_of_bundle = current_position + kBundleSize) { |
502 /* Start of the instruction being processed. */ | 696 /* Start of the instruction being processed. */ |
503 const uint8_t *instruction_start = current_position; | 697 const uint8_t *instruction_start = current_position; |
504 int current_state; | 698 int current_state; |
505 uint32_t instruction_info_collected = 0; | 699 uint32_t instruction_info_collected = 0; |
506 /* Keeps one byte of information per operand in the current instruction: | 700 /* Keeps one byte of information per operand in the current instruction: |
507 * 2 bits for register kinds, | 701 * 2 bits for register kinds, |
508 * 5 bits for register numbers (16 regs plus RIZ). */ | 702 * 5 bits for register numbers (16 regs plus RIZ). */ |
509 uint32_t operand_states = 0; | 703 uint32_t operand_states = 0; |
510 enum register_name base = NO_REG; | 704 enum OperandName base = NO_REG; |
511 enum register_name index = NO_REG; | 705 enum OperandName index = NO_REG; |
512 enum register_name restricted_register = NO_REG; | 706 enum OperandName restricted_register = NO_REG; |
513 uint8_t rex_prefix = FALSE; | 707 uint8_t rex_prefix = FALSE; |
514 uint8_t vex_prefix2 = 0xe0; | 708 uint8_t vex_prefix2 = 0xe0; |
515 uint8_t vex_prefix3 = 0x00; | 709 uint8_t vex_prefix3 = 0x00; |
516 | 710 |
517 %% write init; | 711 %% write init; |
518 %% write exec; | 712 %% write exec; |
519 | 713 |
520 if (restricted_register == REG_RBP) | 714 if (restricted_register == REG_RBP) |
521 result &= user_callback(end_of_bundle, end_of_bundle, | 715 result &= user_callback(end_of_bundle, end_of_bundle, |
522 RESTRICTED_RBP_UNPROCESSED | | 716 RESTRICTED_RBP_UNPROCESSED | |
(...skipping 10 matching lines...) Expand all Loading... | |
533 user_callback, callback_data); | 727 user_callback, callback_data); |
534 | 728 |
535 /* We only use malloc for a large code sequences */ | 729 /* We only use malloc for a large code sequences */ |
536 if (size > sizeof valid_targets_small) { | 730 if (size > sizeof valid_targets_small) { |
537 free(jump_dests); | 731 free(jump_dests); |
538 free(valid_targets); | 732 free(valid_targets); |
539 } | 733 } |
540 if (!result) errno = EINVAL; | 734 if (!result) errno = EINVAL; |
541 return result; | 735 return result; |
542 } | 736 } |
OLD | NEW |