github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/bpf/program_builder_test.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bpf 16 17 import ( 18 "fmt" 19 "testing" 20 21 "github.com/SagerNet/gvisor/pkg/abi/linux" 22 ) 23 24 func validate(p *ProgramBuilder, expected []linux.BPFInstruction) error { 25 instructions, err := p.Instructions() 26 if err != nil { 27 return fmt.Errorf("Instructions() failed: %v", err) 28 } 29 got, err := DecodeInstructions(instructions) 30 if err != nil { 31 return fmt.Errorf("DecodeInstructions('instructions') failed: %v", err) 32 } 33 expectedDecoded, err := DecodeInstructions(expected) 34 if err != nil { 35 return fmt.Errorf("DecodeInstructions('expected') failed: %v", err) 36 } 37 if got != expectedDecoded { 38 return fmt.Errorf("DecodeInstructions() failed, expected: %q, got: %q", expectedDecoded, got) 39 } 40 return nil 41 } 42 43 func TestProgramBuilderSimple(t *testing.T) { 44 p := NewProgramBuilder() 45 p.AddStmt(Ld+Abs+W, 10) 46 p.AddJump(Jmp+Ja, 10, 0, 0) 47 48 expected := []linux.BPFInstruction{ 49 Stmt(Ld+Abs+W, 10), 50 Jump(Jmp+Ja, 10, 0, 0), 51 } 52 53 if err := validate(p, expected); err != nil { 54 t.Errorf("Validate() failed: %v", err) 55 } 56 } 57 58 func TestProgramBuilderLabels(t *testing.T) { 59 p := NewProgramBuilder() 60 p.AddJumpTrueLabel(Jmp+Jeq+K, 11, "label_1", 0) 61 p.AddJumpFalseLabel(Jmp+Jeq+K, 12, 0, "label_2") 62 p.AddJumpLabels(Jmp+Jeq+K, 13, "label_3", "label_4") 63 if err := p.AddLabel("label_1"); err != nil { 64 t.Errorf("AddLabel(label_1) failed: %v", err) 65 } 66 p.AddStmt(Ld+Abs+W, 1) 67 if err := p.AddLabel("label_3"); err != nil { 68 t.Errorf("AddLabel(label_3) failed: %v", err) 69 } 70 p.AddJumpLabels(Jmp+Jeq+K, 14, "label_4", "label_5") 71 if err := p.AddLabel("label_2"); err != nil { 72 t.Errorf("AddLabel(label_2) failed: %v", err) 73 } 74 p.AddJumpLabels(Jmp+Jeq+K, 15, "label_4", "label_6") 75 if err := p.AddLabel("label_4"); err != nil { 76 t.Errorf("AddLabel(label_4) failed: %v", err) 77 } 78 p.AddStmt(Ld+Abs+W, 4) 79 if err := p.AddLabel("label_5"); err != nil { 80 t.Errorf("AddLabel(label_5) failed: %v", err) 81 } 82 if err := p.AddLabel("label_6"); err != nil { 83 t.Errorf("AddLabel(label_6) failed: %v", err) 84 } 85 p.AddStmt(Ld+Abs+W, 5) 86 87 expected := []linux.BPFInstruction{ 88 Jump(Jmp+Jeq+K, 11, 2, 0), 89 Jump(Jmp+Jeq+K, 12, 0, 3), 90 Jump(Jmp+Jeq+K, 13, 1, 3), 91 Stmt(Ld+Abs+W, 1), 92 Jump(Jmp+Jeq+K, 14, 1, 2), 93 Jump(Jmp+Jeq+K, 15, 0, 1), 94 Stmt(Ld+Abs+W, 4), 95 Stmt(Ld+Abs+W, 5), 96 } 97 if err := validate(p, expected); err != nil { 98 t.Errorf("Validate() failed: %v", err) 99 } 100 // Calling validate()=>p.Instructions() again to make sure 101 // Instructions can be called multiple times without ruining 102 // the program. 103 if err := validate(p, expected); err != nil { 104 t.Errorf("Validate() failed: %v", err) 105 } 106 } 107 108 func TestProgramBuilderMissingErrorTarget(t *testing.T) { 109 p := NewProgramBuilder() 110 p.AddJumpTrueLabel(Jmp+Jeq+K, 10, "label_1", 0) 111 if _, err := p.Instructions(); err == nil { 112 t.Errorf("Instructions() should have failed") 113 } 114 } 115 116 func TestProgramBuilderLabelWithNoInstruction(t *testing.T) { 117 p := NewProgramBuilder() 118 p.AddJumpTrueLabel(Jmp+Jeq+K, 10, "label_1", 0) 119 if err := p.AddLabel("label_1"); err != nil { 120 t.Errorf("AddLabel(label_1) failed: %v", err) 121 } 122 if _, err := p.Instructions(); err == nil { 123 t.Errorf("Instructions() should have failed") 124 } 125 } 126 127 // TestProgramBuilderUnusedLabel tests that adding an unused label doesn't 128 // cause program generation to fail. 129 func TestProgramBuilderUnusedLabel(t *testing.T) { 130 p := NewProgramBuilder() 131 p.AddStmt(Ld+Abs+W, 10) 132 p.AddJump(Jmp+Ja, 10, 0, 0) 133 134 expected := []linux.BPFInstruction{ 135 Stmt(Ld+Abs+W, 10), 136 Jump(Jmp+Ja, 10, 0, 0), 137 } 138 139 if err := p.AddLabel("unused"); err != nil { 140 t.Errorf("AddLabel(unused) should have succeeded") 141 } 142 143 if err := validate(p, expected); err != nil { 144 t.Errorf("Validate() failed: %v", err) 145 } 146 } 147 148 // TestProgramBuilderBackwardsReference tests that including a backwards 149 // reference to a label in a program causes a failure. 150 func TestProgramBuilderBackwardsReference(t *testing.T) { 151 p := NewProgramBuilder() 152 if err := p.AddLabel("bw_label"); err != nil { 153 t.Errorf("failed to add label") 154 } 155 p.AddStmt(Ld+Abs+W, 10) 156 p.AddJumpTrueLabel(Jmp+Jeq+K, 10, "bw_label", 0) 157 if _, err := p.Instructions(); err == nil { 158 t.Errorf("Instructions() should have failed") 159 } 160 } 161 162 func TestProgramBuilderLabelAddedTwice(t *testing.T) { 163 p := NewProgramBuilder() 164 p.AddJumpTrueLabel(Jmp+Jeq+K, 10, "label_1", 0) 165 if err := p.AddLabel("label_1"); err != nil { 166 t.Errorf("AddLabel(label_1) failed: %v", err) 167 } 168 p.AddStmt(Ld+Abs+W, 0) 169 if err := p.AddLabel("label_1"); err == nil { 170 t.Errorf("AddLabel(label_1) failed: %v", err) 171 } 172 } 173 174 func TestProgramBuilderJumpBackwards(t *testing.T) { 175 p := NewProgramBuilder() 176 p.AddJumpTrueLabel(Jmp+Jeq+K, 10, "label_1", 0) 177 if err := p.AddLabel("label_1"); err != nil { 178 t.Errorf("AddLabel(label_1) failed: %v", err) 179 } 180 p.AddStmt(Ld+Abs+W, 0) 181 p.AddJumpTrueLabel(Jmp+Jeq+K, 10, "label_1", 0) 182 if _, err := p.Instructions(); err == nil { 183 t.Errorf("Instructions() should have failed") 184 } 185 }