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

Side by Side Diff: src/trusted/validator_arm/validator_small_tests.cc

Issue 11361222: ARM validator: fix sandbox escape with SP update at the end of the last bundle (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: Fix comments from mseaborn. Created 8 years, 1 month 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
« no previous file with comments | « src/trusted/validator_arm/validator.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #ifndef NACL_TRUSTED_BUT_NOT_TCB 7 #ifndef NACL_TRUSTED_BUT_NOT_TCB
8 #error This file is not meant for use in the TCB 8 #error This file is not meant for use in the TCB
9 #endif 9 #endif
10 10
11 /* 11 /*
12 * Small unit tests for the ARM validator 12 * Small unit tests for the ARM validator
13 * 13 *
14 * Also see validator_large_tests.cc, 14 * Also see validator_large_tests.cc,
15 * and validator_tests.h for the testing infrastructure. 15 * and validator_tests.h for the testing infrastructure.
16 */ 16 */
17 17
18 #include "native_client/src/trusted/validator_arm/validator_tests.h" 18 #include "native_client/src/trusted/validator_arm/validator_tests.h"
19 19
20 using nacl_val_arm_test::ProblemRecord; 20 using nacl_val_arm_test::ProblemRecord;
21 using nacl_val_arm_test::ProblemSpy; 21 using nacl_val_arm_test::ProblemSpy;
22 using nacl_val_arm_test::ValidatorTests; 22 using nacl_val_arm_test::ValidatorTests;
23 using nacl_val_arm_test::kDefaultBaseAddr; 23 using nacl_val_arm_test::kDefaultBaseAddr;
24 using nacl_val_arm_test::kCodeRegionSize; 24 using nacl_val_arm_test::kCodeRegionSize;
25 using nacl_val_arm_test::kDataRegionSize; 25 using nacl_val_arm_test::kDataRegionSize;
26 using nacl_val_arm_test::kAbiReadOnlyRegisters; 26 using nacl_val_arm_test::kAbiReadOnlyRegisters;
27 using nacl_val_arm_test::kAbiDataAddrRegisters; 27 using nacl_val_arm_test::kAbiDataAddrRegisters;
28 using nacl_val_arm_test::arm_inst; 28 using nacl_val_arm_test::arm_inst;
29 using nacl_arm_dec::kNop;
29 using nacl_arm_dec::Instruction; 30 using nacl_arm_dec::Instruction;
30 using nacl_arm_dec::ClassDecoder; 31 using nacl_arm_dec::ClassDecoder;
31 32
32 namespace { 33 namespace {
33 34
34 // Holds instruction and message to print if there is an issue when it 35 // Holds instruction and message to print if there is an issue when it
35 // is tested. 36 // is tested.
36 struct AnnotatedInstruction { 37 struct AnnotatedInstruction {
37 arm_inst inst; 38 arm_inst inst;
38 const char *about; 39 const char *about;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 Instruction test(ChangeInstCond(test_inst, cond)); 90 Instruction test(ChangeInstCond(test_inst, cond));
90 const ClassDecoder& decoder = tester->decode(test); 91 const ClassDecoder& decoder = tester->decode(test);
91 Instruction sentinel(decoder.dynamic_code_replacement_sentinel(test)); 92 Instruction sentinel(decoder.dynamic_code_replacement_sentinel(test));
92 EXPECT_TRUE(test.Equals(sentinel)) << 93 EXPECT_TRUE(test.Equals(sentinel)) <<
93 std::hex << test.Bits() << "->" << 94 std::hex << test.Bits() << "->" <<
94 std::hex << sentinel.Bits() << ": " << insts[i].about; 95 std::hex << sentinel.Bits() << ": " << insts[i].about;
95 } 96 }
96 } 97 }
97 } 98 }
98 99
100 TEST_F(ValidatorTests, NopBundle) {
101 vector<arm_inst> code(_validator.InstructionsPerBundle(), kNop);
102 validation_should_pass(&code[0], code.size(), kDefaultBaseAddr,
103 "NOP bundle");
104 }
105
99 /* 106 /*
100 * Primitive tests checking various constructor properties. Any of these 107 * Primitive tests checking various constructor properties. Any of these
101 * failing would be a very bad sign indeed. 108 * failing would be a very bad sign indeed.
102 */ 109 */
103 110
104 TEST_F(ValidatorTests, RecognizesDataAddressRegisters) { 111 TEST_F(ValidatorTests, RecognizesDataAddressRegisters) {
105 // Note that the logic below needs to be kept in sync with the definition 112 // Note that the logic below needs to be kept in sync with the definition
106 // of kAbiDataAddrRegisters at the top of this file. 113 // of kAbiDataAddrRegisters at the top of this file.
107 // 114 //
108 // This test is pretty trivial -- we can exercise the data_address_register 115 // This test is pretty trivial -- we can exercise the data_address_register
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 EXPECT_EQ(nacl_arm_val::kProblemUnsafe, first.problem()) 524 EXPECT_EQ(nacl_arm_val::kProblemUnsafe, first.problem())
518 << "Instruction must be marked unsafe: " 525 << "Instruction must be marked unsafe: "
519 << undefined_insts[i].about; 526 << undefined_insts[i].about;
520 } 527 }
521 } 528 }
522 529
523 TEST_F(ValidatorTests, PcRelativeFirstInst) { 530 TEST_F(ValidatorTests, PcRelativeFirstInst) {
524 // Note: This tests the fix for issue 2771. 531 // Note: This tests the fix for issue 2771.
525 static const arm_inst pcrel_boundary_tests[] = { 532 static const arm_inst pcrel_boundary_tests[] = {
526 0xe59f0000, // ldr r0, [pc, #0] 533 0xe59f0000, // ldr r0, [pc, #0]
527 0xe320f000, // nop {0} 534 kNop,
528 0xe320f000, // nop {0} 535 kNop,
529 0xe320f000, // nop {0}" 536 kNop,
530 }; 537 };
531 validation_should_pass(pcrel_boundary_tests, 538 validation_should_pass(pcrel_boundary_tests,
532 NACL_ARRAY_SIZE(pcrel_boundary_tests), 539 NACL_ARRAY_SIZE(pcrel_boundary_tests),
533 kDefaultBaseAddr, 540 kDefaultBaseAddr,
534 "pc relative first instruction in first bundle"); 541 "pc relative first instruction in first bundle");
535 } 542 }
536 543
537 TEST_F(ValidatorTests, PcRelativeFirst2ndBundle) { 544 TEST_F(ValidatorTests, PcRelativeFirst2ndBundle) {
538 // Note: This tests the fix for issue 2771. 545 // Note: This tests the fix for issue 2771.
539 static const arm_inst pcrel_boundary_tests[] = { 546 static const arm_inst pcrel_boundary_tests[] = {
540 0xe320f000, // nop {0} 547 kNop,
541 0xe320f000, // nop {0} 548 kNop,
542 0xe320f000, // nop {0} 549 kNop,
543 0xe320f000, // nop {0} 550 kNop,
544 0xe59f0000, // ldr r0, [pc, #0] 551 0xe59f0000, // ldr r0, [pc, #0]
545 }; 552 };
546 validation_should_pass(pcrel_boundary_tests, 553 validation_should_pass(pcrel_boundary_tests,
547 NACL_ARRAY_SIZE(pcrel_boundary_tests), 554 NACL_ARRAY_SIZE(pcrel_boundary_tests),
548 kDefaultBaseAddr, 555 kDefaultBaseAddr,
549 "pc relative first instruction in 2nd bundle"); 556 "pc relative first instruction in 2nd bundle");
550 } 557 }
551 558
552 TEST_F(ValidatorTests, SafeConditionalBicLdrTest) { 559 TEST_F(ValidatorTests, SafeConditionalBicLdrTest) {
553 // Test if we fixed bug with conditional Bic Loads (issue 2769). 560 // Test if we fixed bug with conditional Bic Loads (issue 2769).
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 "disallow."); 929 "disallow.");
923 } 930 }
924 } 931 }
925 } 932 }
926 } 933 }
927 } 934 }
928 } 935 }
929 936
930 // TODO(karl): Add pattern rules and test cases for using bfc to update SP. 937 // TODO(karl): Add pattern rules and test cases for using bfc to update SP.
931 938
939 TEST_F(ValidatorTests, UnmaskedSpUpdate) {
940 vector<arm_inst> code(_validator.InstructionsPerBundle(), kNop);
941 for (vector<arm_inst>::size_type i = 0; i < code.size(); ++i) {
942 std::fill(code.begin(), code.end(), kNop);
943 code[i] = 0xE1A0D000; // MOV SP, R0
944 validation_should_fail(&code[0], code.size(), kDefaultBaseAddr,
945 "unmasked SP update");
946 }
947 }
948
949 TEST_F(ValidatorTests, MaskedSpUpdate) {
950 vector<arm_inst> code(_validator.InstructionsPerBundle() * 2, kNop);
951 for (vector<arm_inst>::size_type i = 0; i < code.size() - 1; ++i) {
952 std::fill(code.begin(), code.end(), kNop);
953 code[i] = 0xE1A0D000; // MOV SP, R0
954 code[i + 1] = 0xE3CDD2FF; // BIC SP, SP, #-268435441 ; 0xf000000f
955 if (i == _validator.InstructionsPerBundle() - 1) {
956 validation_should_fail(&code[0], code.size(), kDefaultBaseAddr,
957 "masked SP update straddling a bundle boundary"
958 " (this is technically safe, but we simplify the "
959 "validator by disallowing instruction pairs that "
960 "straddle a bundle boundary)");
961 } else {
962 validation_should_pass(&code[0], code.size(), kDefaultBaseAddr,
963 "masked SP update");
964 }
965 }
966 }
967
932 TEST_F(ValidatorTests, AddConstToSpTest) { 968 TEST_F(ValidatorTests, AddConstToSpTest) {
933 // Show that we can add a constant to the stack pointer is fine, 969 // Show that we can add a constant to the stack pointer is fine,
934 // so long as we follow it with a mask instruction. 970 // so long as we follow it with a mask instruction.
935 static const arm_inst sp_inst[] = { 971 static const arm_inst sp_inst[] = {
936 0xe28dd00c, // add sp, sp, #12 972 0xe28dd00c, // add sp, sp, #12
937 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f 973 0xe3cdd2ff, // bic sp, sp, #-268435441 ; 0xf000000f
938 }; 974 };
939 validation_should_pass(sp_inst, 975 validation_should_pass(sp_inst,
940 NACL_ARRAY_SIZE(sp_inst), 976 NACL_ARRAY_SIZE(sp_inst),
941 kDefaultBaseAddr, 977 kDefaultBaseAddr,
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 // when pointing at the head. 1187 // when pointing at the head.
1152 // Note that we don't actually put anything malicious in the literal pool, 1188 // Note that we don't actually put anything malicious in the literal pool,
1153 // and we still shouldn't be able to jump in the middle of it. 1189 // and we still shouldn't be able to jump in the middle of it.
1154 const size_t bundle_pos = _validator.InstructionsPerBundle(); 1190 const size_t bundle_pos = _validator.InstructionsPerBundle();
1155 vector<arm_inst> code(3 * bundle_pos); 1191 vector<arm_inst> code(3 * bundle_pos);
1156 for (size_t b_pos = 0; b_pos < code.size(); ++b_pos) { 1192 for (size_t b_pos = 0; b_pos < code.size(); ++b_pos) {
1157 if ((bundle_pos <= b_pos) && (b_pos < bundle_pos * 2)) { 1193 if ((bundle_pos <= b_pos) && (b_pos < bundle_pos * 2)) {
1158 // Don't try putting the branch in the middle of the literal pool. 1194 // Don't try putting the branch in the middle of the literal pool.
1159 continue; 1195 continue;
1160 } 1196 }
1161 std::fill(code.begin(), code.end(), 0xE320F000); // NOP 1197 std::fill(code.begin(), code.end(), kNop);
1162 code[bundle_pos] = nacl_arm_dec::kLiteralPoolHead; 1198 code[bundle_pos] = nacl_arm_dec::kLiteralPoolHead;
1163 for (size_t b_target = 0; b_target < code.size(); ++b_target) { 1199 for (size_t b_target = 0; b_target < code.size(); ++b_target) {
1164 // PC reads as current instruction address plus 8 (e.g. two instructions 1200 // PC reads as current instruction address plus 8 (e.g. two instructions
1165 // ahead of b_pos). 1201 // ahead of b_pos).
1166 // imm24 is encoded with the bottom two bits zeroed out, which we 1202 // imm24 is encoded with the bottom two bits zeroed out, which we
1167 // implicitly do by working with instructions instead of bytes. 1203 // implicitly do by working with instructions instead of bytes.
1168 uint32_t imm24 = (b_target - b_pos - 2) & 0x00FFFFFF; 1204 uint32_t imm24 = (b_target - b_pos - 2) & 0x00FFFFFF;
1169 code[b_pos] = 0xEA000000 | imm24; // B #imm 1205 code[b_pos] = 0xEA000000 | imm24; // B #imm
1170 bool target_in_pool = (bundle_pos < b_target) && 1206 bool target_in_pool = (bundle_pos < b_target) &&
1171 (b_target < bundle_pos * 2); // Excluding head. 1207 (b_target < bundle_pos * 2); // Excluding head.
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 } 1328 }
1293 } 1329 }
1294 1330
1295 }; // anonymous namespace 1331 }; // anonymous namespace
1296 1332
1297 // Test driver function. 1333 // Test driver function.
1298 int main(int argc, char *argv[]) { 1334 int main(int argc, char *argv[]) {
1299 testing::InitGoogleTest(&argc, argv); 1335 testing::InitGoogleTest(&argc, argv);
1300 return RUN_ALL_TESTS(); 1336 return RUN_ALL_TESTS();
1301 } 1337 }
OLDNEW
« no previous file with comments | « src/trusted/validator_arm/validator.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698