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 }