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 }