github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/engine/profiles/seccomp/seccomp_test.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package seccomp // import "github.com/docker/docker/profiles/seccomp"
     5  
     6  import (
     7  	"encoding/json"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/opencontainers/runtime-spec/specs-go"
    13  	"gotest.tools/v3/assert"
    14  )
    15  
    16  func TestLoadProfile(t *testing.T) {
    17  	f, err := os.ReadFile("fixtures/example.json")
    18  	if err != nil {
    19  		t.Fatal(err)
    20  	}
    21  	rs := createSpec()
    22  	if _, err := LoadProfile(string(f), &rs); err != nil {
    23  		t.Fatal(err)
    24  	}
    25  }
    26  
    27  // TestLoadLegacyProfile tests loading a seccomp profile in the old format
    28  // (before https://github.com/docker/docker/pull/24510)
    29  func TestLoadLegacyProfile(t *testing.T) {
    30  	f, err := os.ReadFile("fixtures/default-old-format.json")
    31  	if err != nil {
    32  		t.Fatal(err)
    33  	}
    34  	rs := createSpec()
    35  	if _, err := LoadProfile(string(f), &rs); err != nil {
    36  		t.Fatal(err)
    37  	}
    38  }
    39  
    40  func TestLoadDefaultProfile(t *testing.T) {
    41  	f, err := os.ReadFile("default.json")
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  	rs := createSpec()
    46  	if _, err := LoadProfile(string(f), &rs); err != nil {
    47  		t.Fatal(err)
    48  	}
    49  }
    50  
    51  func TestUnmarshalDefaultProfile(t *testing.T) {
    52  	expected := DefaultProfile()
    53  	if expected == nil {
    54  		t.Skip("seccomp not supported")
    55  	}
    56  
    57  	f, err := os.ReadFile("default.json")
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  	var profile Seccomp
    62  	err = json.Unmarshal(f, &profile)
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	assert.DeepEqual(t, expected.Architectures, profile.Architectures)
    67  	assert.DeepEqual(t, expected.ArchMap, profile.ArchMap)
    68  	assert.DeepEqual(t, expected.DefaultAction, profile.DefaultAction)
    69  	assert.DeepEqual(t, expected.Syscalls, profile.Syscalls)
    70  }
    71  
    72  func TestMarshalUnmarshalFilter(t *testing.T) {
    73  	t.Parallel()
    74  	tests := []struct {
    75  		in    string
    76  		out   string
    77  		error bool
    78  	}{
    79  		{in: `{"arches":["s390x"],"minKernel":3}`, error: true},
    80  		{in: `{"arches":["s390x"],"minKernel":3.12}`, error: true},
    81  		{in: `{"arches":["s390x"],"minKernel":true}`, error: true},
    82  		{in: `{"arches":["s390x"],"minKernel":"0.0"}`, error: true},
    83  		{in: `{"arches":["s390x"],"minKernel":"3"}`, error: true},
    84  		{in: `{"arches":["s390x"],"minKernel":".3"}`, error: true},
    85  		{in: `{"arches":["s390x"],"minKernel":"3."}`, error: true},
    86  		{in: `{"arches":["s390x"],"minKernel":"true"}`, error: true},
    87  		{in: `{"arches":["s390x"],"minKernel":"3.12.1\""}`, error: true},
    88  		{in: `{"arches":["s390x"],"minKernel":"4.15abc"}`, error: true},
    89  		{in: `{"arches":["s390x"],"minKernel":null}`, out: `{"arches":["s390x"]}`},
    90  		{in: `{"arches":["s390x"],"minKernel":""}`, out: `{"arches":["s390x"],"minKernel":""}`}, // FIXME: try to fix omitempty for this
    91  		{in: `{"arches":["s390x"],"minKernel":"0.5"}`, out: `{"arches":["s390x"],"minKernel":"0.5"}`},
    92  		{in: `{"arches":["s390x"],"minKernel":"0.50"}`, out: `{"arches":["s390x"],"minKernel":"0.50"}`},
    93  		{in: `{"arches":["s390x"],"minKernel":"5.0"}`, out: `{"arches":["s390x"],"minKernel":"5.0"}`},
    94  		{in: `{"arches":["s390x"],"minKernel":"50.0"}`, out: `{"arches":["s390x"],"minKernel":"50.0"}`},
    95  		{in: `{"arches":["s390x"],"minKernel":"4.15"}`, out: `{"arches":["s390x"],"minKernel":"4.15"}`},
    96  	}
    97  	for _, tc := range tests {
    98  		tc := tc
    99  		t.Run(tc.in, func(t *testing.T) {
   100  			var filter Filter
   101  			err := json.Unmarshal([]byte(tc.in), &filter)
   102  			if tc.error {
   103  				if err == nil {
   104  					t.Fatal("expected an error")
   105  				} else if !strings.Contains(err.Error(), "invalid kernel version") {
   106  					t.Fatal("unexpected error:", err)
   107  				}
   108  				return
   109  			}
   110  			if err != nil {
   111  				t.Fatal(err)
   112  			}
   113  			out, err := json.Marshal(filter)
   114  			if err != nil {
   115  				t.Fatal(err)
   116  			}
   117  			if string(out) != tc.out {
   118  				t.Fatalf("expected %s, got %s", tc.out, string(out))
   119  			}
   120  		})
   121  	}
   122  }
   123  
   124  func TestLoadConditional(t *testing.T) {
   125  	f, err := os.ReadFile("fixtures/conditional_include.json")
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	tests := []struct {
   130  		doc      string
   131  		cap      string
   132  		expected []string
   133  	}{
   134  		{doc: "no caps", expected: []string{"chmod", "ptrace"}},
   135  		{doc: "with syslog", cap: "CAP_SYSLOG", expected: []string{"chmod", "syslog", "ptrace"}},
   136  		{doc: "no ptrace", cap: "CAP_SYS_ADMIN", expected: []string{"chmod"}},
   137  	}
   138  
   139  	for _, tc := range tests {
   140  		tc := tc
   141  		t.Run(tc.doc, func(t *testing.T) {
   142  			rs := createSpec(tc.cap)
   143  			p, err := LoadProfile(string(f), &rs)
   144  			if err != nil {
   145  				t.Fatal(err)
   146  			}
   147  			if len(p.Syscalls) != len(tc.expected) {
   148  				t.Fatalf("expected %d syscalls in profile, have %d", len(tc.expected), len(p.Syscalls))
   149  			}
   150  			for i, v := range p.Syscalls {
   151  				if v.Names[0] != tc.expected[i] {
   152  					t.Fatalf("expected %s syscall, have %s", tc.expected[i], v.Names[0])
   153  				}
   154  			}
   155  		})
   156  	}
   157  }
   158  
   159  // createSpec() creates a minimum spec for testing
   160  func createSpec(caps ...string) specs.Spec {
   161  	rs := specs.Spec{
   162  		Process: &specs.Process{
   163  			Capabilities: &specs.LinuxCapabilities{},
   164  		},
   165  	}
   166  	if caps != nil {
   167  		rs.Process.Capabilities.Bounding = append(rs.Process.Capabilities.Bounding, caps...)
   168  	}
   169  	return rs
   170  }