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  }