Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sandbox/linux/seccomp-bpf/codegen.h" | 5 #include "sandbox/linux/seccomp-bpf/codegen.h" |
| 6 | 6 |
| 7 #include <linux/filter.h> | 7 #include <linux/filter.h> |
| 8 | 8 |
| 9 #include <cstring> | 9 #include <cstring> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 | 106 |
| 107 // MakeInstruction calls CodeGen::MakeInstruction() and associated | 107 // MakeInstruction calls CodeGen::MakeInstruction() and associated |
| 108 // the returned address with a hash of the instruction. | 108 // the returned address with a hash of the instruction. |
| 109 CodeGen::Addr MakeInstruction(uint16_t code, | 109 CodeGen::Addr MakeInstruction(uint16_t code, |
| 110 uint32_t k, | 110 uint32_t k, |
| 111 CodeGen::Addr jt = CodeGen::kNullAddr, | 111 CodeGen::Addr jt = CodeGen::kNullAddr, |
| 112 CodeGen::Addr jf = CodeGen::kNullAddr) { | 112 CodeGen::Addr jf = CodeGen::kNullAddr) { |
| 113 CodeGen::Addr res = gen_.MakeInstruction(code, k, jt, jf); | 113 CodeGen::Addr res = gen_.MakeInstruction(code, k, jt, jf); |
| 114 EXPECT_NE(CodeGen::kNullAddr, res); | 114 EXPECT_NE(CodeGen::kNullAddr, res); |
| 115 | 115 |
| 116 Hash digest; | 116 Hash digest(code, k, Lookup(jt), Lookup(jf)); |
| 117 if (code == BPF_JMP + BPF_JA) { | |
| 118 // TODO(mdempsky): Disallow use of JA. | |
| 119 digest = Lookup(jt); | |
| 120 } else { | |
| 121 digest = Hash(code, k, Lookup(jt), Lookup(jf)); | |
| 122 } | |
| 123 auto it = addr_hashes_.insert(std::make_pair(res, digest)); | 117 auto it = addr_hashes_.insert(std::make_pair(res, digest)); |
| 124 EXPECT_EQ(digest, it.first->second); | 118 EXPECT_EQ(digest, it.first->second); |
| 125 | 119 |
| 126 return res; | 120 return res; |
| 127 } | 121 } |
| 128 | 122 |
| 129 // RunTest compiles the program and verifies that the output matches | 123 // RunTest compiles the program and verifies that the output matches |
| 130 // what is expected. It should be called at the end of each program | 124 // what is expected. It should be called at the end of each program |
| 131 // test case. | 125 // test case. |
| 132 void RunTest(CodeGen::Addr head) { | 126 void RunTest(CodeGen::Addr head) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 // the same object, we do not actually have any "mergeable" branches. | 198 // the same object, we do not actually have any "mergeable" branches. |
| 205 // This needs to be reflected in our choice of "flags". | 199 // This needs to be reflected in our choice of "flags". |
| 206 RunTest(head); | 200 RunTest(head); |
| 207 } | 201 } |
| 208 | 202 |
| 209 TEST_F(ProgramTest, Complex) { | 203 TEST_F(ProgramTest, Complex) { |
| 210 // Creates a basic BPF program that we'll use to test some of the code: | 204 // Creates a basic BPF program that we'll use to test some of the code: |
| 211 // JUMP if eq 42 the $0 else $1 (insn6) | 205 // JUMP if eq 42 the $0 else $1 (insn6) |
| 212 // 0: LD 23 (insn5) | 206 // 0: LD 23 (insn5) |
| 213 // 1: JUMP if eq 42 then $2 else $4 (insn4) | 207 // 1: JUMP if eq 42 then $2 else $4 (insn4) |
| 214 // 2: JUMP to $3 (insn2) | 208 // 2: JUMP to $3 (insn2) |
|
rickyz (no longer on Chrome)
2014/11/12 23:43:50
Update this comment now that we got rid of the jum
mdempsky
2014/11/18 01:07:30
So my reasoning was this is the description of the
| |
| 215 // 3: LD 42 (insn1) | 209 // 3: LD 42 (insn1) |
| 216 // RET 42 (insn0) | 210 // RET 42 (insn0) |
| 217 // 4: LD 42 (insn3) | 211 // 4: LD 42 (insn3) |
| 218 // RET 42 (insn3+) | 212 // RET 42 (insn3+) |
| 219 CodeGen::Addr insn0 = MakeInstruction(BPF_RET + BPF_K, 42); | 213 CodeGen::Addr insn0 = MakeInstruction(BPF_RET + BPF_K, 42); |
| 220 CodeGen::Addr insn1 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, insn0); | 214 CodeGen::Addr insn1 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, insn0); |
| 221 CodeGen::Addr insn2 = MakeInstruction(BPF_JMP + BPF_JA, 0, insn1); | 215 CodeGen::Addr insn2 = insn1; // Implicit JUMP |
| 222 | 216 |
| 223 // We explicitly duplicate instructions so that MergeTails() can coalesce | 217 // We explicitly duplicate instructions to check that CodeGen merges them. |
| 224 // them later. | |
| 225 CodeGen::Addr insn3 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, | 218 CodeGen::Addr insn3 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 42, |
| 226 MakeInstruction(BPF_RET + BPF_K, 42)); | 219 MakeInstruction(BPF_RET + BPF_K, 42)); |
| 220 EXPECT_EQ(insn2, insn3); | |
| 227 | 221 |
| 228 CodeGen::Addr insn4 = | 222 CodeGen::Addr insn4 = |
| 229 MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 42, insn2, insn3); | 223 MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 42, insn2, insn3); |
| 230 CodeGen::Addr insn5 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 23, insn4); | 224 CodeGen::Addr insn5 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 23, insn4); |
| 231 | 225 |
| 232 // Force a basic block that ends in neither a jump instruction nor a return | 226 // Force a basic block that ends in neither a jump instruction nor a return |
| 233 // instruction. It only contains "insn5". This exercises one of the less | 227 // instruction. It only contains "insn5". This exercises one of the less |
| 234 // common code paths in the topo-sort algorithm. | 228 // common code paths in the topo-sort algorithm. |
| 235 // This also gives us a diamond-shaped pattern in our graph, which stresses | 229 // This also gives us a diamond-shaped pattern in our graph, which stresses |
| 236 // another aspect of the topo-sort algorithm (namely, the ability to | 230 // another aspect of the topo-sort algorithm (namely, the ability to |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 CodeGen::Addr i5 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7); | 309 CodeGen::Addr i5 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7); |
| 316 CodeGen::Addr i4 = MakeInstruction(BPF_RET + BPF_K, 42); | 310 CodeGen::Addr i4 = MakeInstruction(BPF_RET + BPF_K, 42); |
| 317 CodeGen::Addr i3 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); | 311 CodeGen::Addr i3 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5); |
| 318 CodeGen::Addr i2 = MakeInstruction(BPF_RET + BPF_K, 42); | 312 CodeGen::Addr i2 = MakeInstruction(BPF_RET + BPF_K, 42); |
| 319 CodeGen::Addr i1 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); | 313 CodeGen::Addr i1 = MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3); |
| 320 CodeGen::Addr i0 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); | 314 CodeGen::Addr i0 = MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1); |
| 321 | 315 |
| 322 RunTest(i0); | 316 RunTest(i0); |
| 323 } | 317 } |
| 324 | 318 |
| 319 TEST_F(ProgramTest, InstructionFolding) { | |
| 320 // Check that simple instructions are folded as expected. | |
| 321 CodeGen::Addr a = MakeInstruction(BPF_RET + BPF_K, 0); | |
| 322 EXPECT_EQ(a, MakeInstruction(BPF_RET + BPF_K, 0)); | |
| 323 CodeGen::Addr b = MakeInstruction(BPF_RET + BPF_K, 1); | |
| 324 EXPECT_EQ(a, MakeInstruction(BPF_RET + BPF_K, 0)); | |
| 325 EXPECT_EQ(b, MakeInstruction(BPF_RET + BPF_K, 1)); | |
| 326 EXPECT_EQ(b, MakeInstruction(BPF_RET + BPF_K, 1)); | |
| 327 | |
| 328 // Check that complex sequences are folded too. | |
| 329 CodeGen::Addr c = | |
| 330 MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, | |
| 331 MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, 0x100, a, b)); | |
| 332 EXPECT_EQ(c, MakeInstruction( | |
| 333 BPF_LD + BPF_W + BPF_ABS, 0, | |
| 334 MakeInstruction(BPF_JMP + BPF_JSET + BPF_K, 0x100, a, b))); | |
| 335 | |
| 336 RunTest(c); | |
| 337 } | |
| 338 | |
| 325 } // namespace | 339 } // namespace |
|
rickyz (no longer on Chrome)
2014/11/12 23:43:50
Can you add a test that calls MakeInstruction with
mdempsky
2014/11/18 01:07:30
Done.
| |
| 326 } // namespace sandbox | 340 } // namespace sandbox |
| OLD | NEW |