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