github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/moby/profiles/seccomp/seccomp_test.go (about)

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