Chromium Code Reviews| 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 |
| 7 /* | 7 /* |
| 8 * This file contains common parts of x86-32 and x86-64 insternals (inline | 8 * This file contains common parts of x86-32 and x86-64 insternals (inline |
| 9 * functions and defines). | 9 * functions and defines). |
| 10 */ | 10 */ |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 #define SET_BRANCH_TAKEN(S) | 130 #define SET_BRANCH_TAKEN(S) |
| 131 #define SET_BRANCH_NOT_TAKEN(S) | 131 #define SET_BRANCH_NOT_TAKEN(S) |
| 132 #define SET_MODRM_SCALE(S) | 132 #define SET_MODRM_SCALE(S) |
| 133 #define SET_DISP_TYPE(T) | 133 #define SET_DISP_TYPE(T) |
| 134 #define SET_DISP_PTR(P) | 134 #define SET_DISP_PTR(P) |
| 135 #define SET_IMM_TYPE(T) | 135 #define SET_IMM_TYPE(T) |
| 136 #define SET_IMM_PTR(P) | 136 #define SET_IMM_PTR(P) |
| 137 #define SET_IMM2_TYPE(T) | 137 #define SET_IMM2_TYPE(T) |
| 138 #define SET_IMM2_PTR(P) | 138 #define SET_IMM2_PTR(P) |
| 139 | 139 |
| 140 static const int kBitsPerByte = 8; | 140 #define BITMAP_WORD_NAME BITMAP_WORD_NAME1(NACL_HOST_WORDSIZE) |
| 141 #define BITMAP_WORD_NAME1(size) BITMAP_WORD_NAME2(size) | |
| 142 #define BITMAP_WORD_NAME2(size) uint##size##_t | |
| 141 | 143 |
| 142 static INLINE uint8_t *BitmapAllocate(size_t indexes) { | 144 typedef BITMAP_WORD_NAME bitmap_word; |
| 143 size_t byte_count = (indexes + kBitsPerByte - 1) / kBitsPerByte; | 145 |
| 144 uint8_t *bitmap = malloc(byte_count); | 146 static INLINE bitmap_word *BitmapAllocate(size_t indexes) { |
| 147 size_t byte_count = (indexes + NACL_HOST_WORDSIZE - 1) / NACL_HOST_WORDSIZE; | |
|
halyavin
2012/08/17 15:22:37
byte_count->word_count
| |
| 148 bitmap_word *bitmap = malloc(byte_count/(NACL_HOST_WORDSIZE/8)); | |
|
halyavin
2012/08/17 15:22:37
*sizeof(bitmap_word)
| |
| 145 if (bitmap != NULL) { | 149 if (bitmap != NULL) { |
| 146 memset(bitmap, 0, byte_count); | 150 memset(bitmap, 0, byte_count); |
| 147 } | 151 } |
| 148 return bitmap; | 152 return bitmap; |
| 149 } | 153 } |
| 150 | 154 |
| 151 static FORCEINLINE int BitmapIsBitSet(uint8_t *bitmap, size_t index) { | 155 static FORCEINLINE int BitmapIsBitSet(bitmap_word *bitmap, size_t index) { |
| 152 return (bitmap[index / kBitsPerByte] & (1 << (index % kBitsPerByte))) != 0; | 156 return (bitmap[index / NACL_HOST_WORDSIZE] & |
| 157 (1 << (index % NACL_HOST_WORDSIZE))) != 0; | |
|
halyavin
2012/08/17 15:22:37
((bitmap_word)1)
| |
| 153 } | 158 } |
| 154 | 159 |
| 155 static FORCEINLINE void BitmapSetBit(uint8_t *bitmap, size_t index) { | 160 static FORCEINLINE void BitmapSetBit(bitmap_word *bitmap, size_t index) { |
| 156 bitmap[index / kBitsPerByte] |= 1 << (index % kBitsPerByte); | 161 bitmap[index / NACL_HOST_WORDSIZE] |= 1 << (index % NACL_HOST_WORDSIZE); |
|
halyavin
2012/08/17 15:22:37
same
| |
| 157 } | 162 } |
| 158 | 163 |
| 159 static FORCEINLINE void BitmapClearBit(uint8_t *bitmap, size_t index) { | 164 static FORCEINLINE void BitmapClearBit(bitmap_word *bitmap, size_t index) { |
| 160 bitmap[index / kBitsPerByte] &= ~(1 << (index % kBitsPerByte)); | 165 bitmap[index / NACL_HOST_WORDSIZE] &= ~(1 << (index % NACL_HOST_WORDSIZE)); |
|
halyavin
2012/08/17 15:22:37
same
| |
| 161 } | 166 } |
| 162 | 167 |
| 163 /* Mark the destination of a jump instruction and make an early validity check: | 168 /* Mark the destination of a jump instruction and make an early validity check: |
| 164 * to jump outside given code region, the target address must be aligned. | 169 * to jump outside given code region, the target address must be aligned. |
| 165 * | 170 * |
| 166 * Returns TRUE iff the jump passes the early validity check. | 171 * Returns TRUE iff the jump passes the early validity check. |
| 167 */ | 172 */ |
| 168 static FORCEINLINE int MarkJumpTarget(size_t jump_dest, | 173 static FORCEINLINE int MarkJumpTarget(size_t jump_dest, |
| 169 uint8_t *jump_dests, | 174 bitmap_word *jump_dests, |
| 170 size_t size) { | 175 size_t size) { |
| 171 if ((jump_dest & kBundleMask) == 0) { | 176 if ((jump_dest & kBundleMask) == 0) { |
| 172 return TRUE; | 177 return TRUE; |
| 173 } | 178 } |
| 174 if (jump_dest >= size) { | 179 if (jump_dest >= size) { |
| 175 return FALSE; | 180 return FALSE; |
| 176 } | 181 } |
| 177 BitmapSetBit(jump_dests, jump_dest); | 182 BitmapSetBit(jump_dests, jump_dest); |
| 178 return TRUE; | 183 return TRUE; |
| 179 } | 184 } |
| 180 | 185 |
| 181 | 186 |
| 182 static INLINE Bool ProcessInvalidJumpTargets( | 187 static INLINE Bool ProcessInvalidJumpTargets( |
| 183 const uint8_t *data, | 188 const uint8_t *data, |
| 184 size_t size, | 189 size_t size, |
| 185 uint8_t *valid_targets, | 190 bitmap_word *valid_targets, |
| 186 uint8_t *jump_dests, | 191 bitmap_word *jump_dests, |
| 187 validation_callback_func user_callback, | 192 validation_callback_func user_callback, |
| 188 void *callback_data) { | 193 void *callback_data) { |
| 194 size_t elements = (size + NACL_HOST_WORDSIZE / 8 - 1) & | |
| 195 ~(NACL_HOST_WORDSIZE / 8 - 1); | |
| 189 size_t i; | 196 size_t i; |
| 190 | 197 |
| 191 assert(size % 32 == 0); | 198 for (i = 0; i < elements ; i++) { |
| 192 | 199 bitmap_word jump_dest_mask = jump_dests[i]; |
| 193 for (i = 0; i < size / 32; i++) { | 200 bitmap_word valid_target_mask = valid_targets[i]; |
| 194 uint32_t jump_dest_mask = ((uint32_t *) jump_dests)[i]; | |
| 195 uint32_t valid_target_mask = ((uint32_t *) valid_targets)[i]; | |
| 196 if ((jump_dest_mask & ~valid_target_mask) != 0) { | 201 if ((jump_dest_mask & ~valid_target_mask) != 0) { |
| 197 // TODO(shcherbina): report address precisely, not just 32-byte block | 202 // TODO(shcherbina): report address precisely, not just 32-byte block |
| 198 // TODO(khim): report all errors found, not just the first one | 203 // TODO(khim): report all errors found, not just the first one |
| 199 return user_callback(data + i * 32, data + i * 32, BAD_JUMP_TARGET, | 204 return user_callback(data + i * NACL_HOST_WORDSIZE, |
| 205 data + i * NACL_HOST_WORDSIZE, BAD_JUMP_TARGET, | |
| 200 callback_data); | 206 callback_data); |
| 201 } | 207 } |
| 202 } | 208 } |
| 203 | 209 |
| 204 return TRUE; | 210 return TRUE; |
| 205 } | 211 } |
| 206 | 212 |
| 207 | 213 |
| 208 /* | 214 /* |
| 209 * Process rel8_operand. Note: rip points to the beginning of the next | 215 * Process rel8_operand. Note: rip points to the beginning of the next |
| 210 * instruction here and x86 encoding guarantees rel8 field is the last one | 216 * instruction here and x86 encoding guarantees rel8 field is the last one |
| 211 * in a current instruction. | 217 * in a current instruction. |
| 212 */ | 218 */ |
| 213 static FORCEINLINE void rel8_operand(const uint8_t *rip, | 219 static FORCEINLINE void rel8_operand(const uint8_t *rip, |
| 214 const uint8_t* codeblock_start, | 220 const uint8_t* codeblock_start, |
| 215 uint8_t *jump_dests, size_t jumpdests_size, | 221 bitmap_word *jump_dests, |
| 222 size_t jumpdests_size, | |
| 216 uint32_t *instruction_info_collected) { | 223 uint32_t *instruction_info_collected) { |
| 217 int8_t offset = (uint8_t) (rip[-1]); | 224 int8_t offset = (uint8_t) (rip[-1]); |
| 218 size_t jump_dest = offset + (rip - codeblock_start); | 225 size_t jump_dest = offset + (rip - codeblock_start); |
| 219 | 226 |
| 220 if (!MarkJumpTarget(jump_dest, jump_dests, jumpdests_size)) { | 227 if (!MarkJumpTarget(jump_dest, jump_dests, jumpdests_size)) { |
| 221 *instruction_info_collected |= DIRECT_JUMP_OUT_OF_RANGE; | 228 *instruction_info_collected |= DIRECT_JUMP_OUT_OF_RANGE; |
| 222 } | 229 } |
| 223 } | 230 } |
| 224 | 231 |
| 225 /* | 232 /* |
| 226 * Process rel32_operand. Note: rip points to the beginning of the next | 233 * Process rel32_operand. Note: rip points to the beginning of the next |
| 227 * instruction here and x86 encoding guarantees rel32 field is the last one | 234 * instruction here and x86 encoding guarantees rel32 field is the last one |
| 228 * in a current instruction. | 235 * in a current instruction. |
| 229 */ | 236 */ |
| 230 static FORCEINLINE void rel32_operand(const uint8_t *rip, | 237 static FORCEINLINE void rel32_operand(const uint8_t *rip, |
| 231 const uint8_t* codeblock_start, | 238 const uint8_t* codeblock_start, |
| 232 uint8_t *jump_dests, | 239 bitmap_word *jump_dests, |
| 233 size_t jumpdests_size, | 240 size_t jumpdests_size, |
| 234 uint32_t *instruction_info_collected) { | 241 uint32_t *instruction_info_collected) { |
| 235 int32_t offset = (rip[-4] + 256U * (rip[-3] + 256U * ( | 242 int32_t offset = (rip[-4] + 256U * (rip[-3] + 256U * ( |
| 236 rip[-2] + 256U * ((uint32_t) rip[-1])))); | 243 rip[-2] + 256U * ((uint32_t) rip[-1])))); |
| 237 size_t jump_dest = offset + (rip - codeblock_start); | 244 size_t jump_dest = offset + (rip - codeblock_start); |
| 238 | 245 |
| 239 if (!MarkJumpTarget(jump_dest, jump_dests, jumpdests_size)) { | 246 if (!MarkJumpTarget(jump_dest, jump_dests, jumpdests_size)) { |
| 240 *instruction_info_collected |= DIRECT_JUMP_OUT_OF_RANGE; | 247 *instruction_info_collected |= DIRECT_JUMP_OUT_OF_RANGE; |
| 241 } | 248 } |
| 242 } | 249 } |
| 243 | 250 |
| 244 static INLINE void check_access(ptrdiff_t instruction_start, | 251 static INLINE void check_access(ptrdiff_t instruction_start, |
| 245 enum register_name base, | 252 enum register_name base, |
| 246 enum register_name index, | 253 enum register_name index, |
| 247 uint8_t restricted_register, | 254 uint8_t restricted_register, |
| 248 uint8_t *valid_targets, | 255 bitmap_word *valid_targets, |
| 249 uint32_t *instruction_info_collected) { | 256 uint32_t *instruction_info_collected) { |
| 250 if ((base == REG_RIP) || (base == REG_R15) || | 257 if ((base == REG_RIP) || (base == REG_R15) || |
| 251 (base == REG_RSP) || (base == REG_RBP)) { | 258 (base == REG_RSP) || (base == REG_RBP)) { |
| 252 if (index == restricted_register) { | 259 if (index == restricted_register) { |
| 253 BitmapClearBit(valid_targets, instruction_start); | 260 BitmapClearBit(valid_targets, instruction_start); |
| 254 } else if ((index != NO_REG) && (index != REG_RIZ)) { | 261 } else if ((index != NO_REG) && (index != REG_RIZ)) { |
| 255 *instruction_info_collected |= UNRESTRICTED_INDEX_REGISTER; | 262 *instruction_info_collected |= UNRESTRICTED_INDEX_REGISTER; |
| 256 } | 263 } |
| 257 } else { | 264 } else { |
| 258 *instruction_info_collected |= FORBIDDEN_BASE_REGISTER; | 265 *instruction_info_collected |= FORBIDDEN_BASE_REGISTER; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; | 347 *instruction_info_collected |= RESTRICTED_RBP_UNPROCESSED; |
| 341 } | 348 } |
| 342 /* Take 2 bits of operand type from operand_states as *restricted_register, | 349 /* Take 2 bits of operand type from operand_states as *restricted_register, |
| 343 * make sure operand_states denotes a register (12th bit == 0). */ | 350 * make sure operand_states denotes a register (12th bit == 0). */ |
| 344 } else if ((operand_states & 0x7000) == (OperandSandboxRestricted << 13)) { | 351 } else if ((operand_states & 0x7000) == (OperandSandboxRestricted << 13)) { |
| 345 *restricted_register = (operand_states & 0x0f00) >> 8; | 352 *restricted_register = (operand_states & 0x0f00) >> 8; |
| 346 } | 353 } |
| 347 } | 354 } |
| 348 | 355 |
| 349 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ */ | 356 #endif /* NATIVE_CLIENT_SRC_TRUSTED_VALIDATOR_RAGEL_VALIDATOR_INTERNAL_H_ */ |
| OLD | NEW |