github.com/rigado/snapd@v2.42.5-go-mod+incompatible/sandbox/seccomp/compiler_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 package seccomp_test 20 21 import ( 22 "errors" 23 "fmt" 24 "testing" 25 26 . "gopkg.in/check.v1" 27 28 seccomp "github.com/snapcore/snapd/sandbox/seccomp" 29 "github.com/snapcore/snapd/testutil" 30 ) 31 32 type compilerSuite struct{} 33 34 var _ = Suite(&compilerSuite{}) 35 36 func TestSeccomp(t *testing.T) { TestingT(t) } 37 38 func fromCmd(c *C, cmd *testutil.MockCmd) func(string) (string, error) { 39 return func(name string) (string, error) { 40 c.Check(name, Equals, "snap-seccomp") 41 return cmd.Exe(), nil 42 } 43 } 44 45 func (s *compilerSuite) TestVersionInfoValidate(c *C) { 46 47 for i, tc := range []struct { 48 v string 49 exp string 50 err string 51 }{ 52 // all valid 53 // 20-byte sha1 build ID added by GNU ld 54 {"7ac348ac9c934269214b00d1692dfa50d5d4a157 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c bpf-actlog", "7ac348ac9c934269214b00d1692dfa50d5d4a157 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c bpf-actlog", ""}, 55 {"7ac348ac9c934269214b00d1692dfa50d5d4a157 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c foo:bar", "7ac348ac9c934269214b00d1692dfa50d5d4a157 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c foo:bar", ""}, 56 {"7ac348ac9c934269214b00d1692dfa50d5d4a157 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c -", "7ac348ac9c934269214b00d1692dfa50d5d4a157 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c -", ""}, 57 // 16-byte md5/uuid build ID added by GNU ld 58 {"3817b197e7abe71a952c1245e8bdf8d9 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c -", "3817b197e7abe71a952c1245e8bdf8d9 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c -", ""}, 59 // 83-byte Go build ID 60 {"4e444571495f482d30796b5f57307065544e47692f594c61795f384b7a5258362d6a6f4272736e38302f773374475869496e433176527749797a457a4b532f3967324d4f76556f3130323644572d56326e6248 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c -", "4e444571495f482d30796b5f57307065544e47692f594c61795f384b7a5258362d6a6f4272736e38302f773374475869496e433176527749797a457a4b532f3967324d4f76556f3130323644572d56326e6248 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c -", ""}, 61 // sanity 62 {"abcdef 0.0.0 abcd bpf-actlog", "abcdef 0.0.0 abcd bpf-actlog", ""}, 63 {"abcdef 0.0.0 abcd -", "abcdef 0.0.0 abcd -", ""}, 64 65 // invalid all the way down from here 66 // this is over/under the sane length limit for the fields 67 {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 2.4.1 0000000000000000000000000000000000000000000000000000000000000000 -", "", "invalid format of version-info: .*"}, 68 {"0000000000000000000000000000000000000000 123456.0.0 0000000000000000000000000000000000000000000000000000000000000000 -", "", "invalid format of version-info: .*"}, 69 {"0000000000000000000000000000000000000000 0.123456.0 0000000000000000000000000000000000000000000000000000000000000000 -", "", "invalid format of version-info: .*"}, 70 {"0000000000000000000000000000000000000000 0.0.123456 0000000000000000000000000000000000000000000000000000000000000000 -", "", "invalid format of version-info: .*"}, 71 {"0000000000000000000000000000000000000000 2.4.1 00000000000000000000000000000000000000000000000000000000000000001 -", "", "invalid format of version-info: .*"}, 72 {"0000000000000000000000000000000000000000 2.4.1 0000000000000000000000000000000000000000000000000000000000000000 012345678901234567890123456789a", "", "invalid format of version-info: .*"}, 73 {"0000000000000000000000000000000000000000 .4.1 0000000000000000000000000000000000000000000000000000000000000000 -", "", "invalid format of version-info: .*"}, 74 {"0000000000000000000000000000000000000000 2.4 0000000000000000000000000000000000000000000000000000000000000000 -", "", "invalid format of version-info: .*"}, 75 {"0000000000000000000000000000000000000000 2.4. 0000000000000000000000000000000000000000000000000000000000000000 -", "", "invalid format of version-info: .*"}, 76 {"0000000000000000000000000000000000000000 2..1 0000000000000000000000000000000000000000000000000000000000000000 -", "", "invalid format of version-info: .*"}, 77 {"0000000000000000000000000000000000000000 2.4.1 0000000000000000000000000000000000000000000000000000000000000000 ", "", "invalid format of version-info: .*"}, 78 // incorrect format 79 {"abcd 0.0.0 fg", "", "invalid format of version-info: .*"}, 80 {"ggg 0.0.0 abc", "", "invalid format of version-info: .*"}, 81 {"foo", "", "invalid format of version-info: .*"}, 82 {"1", "", "invalid format of version-info: .*"}, 83 {"i\ncan\nhave\nnewlines", "", "invalid format of version-info: .*"}, 84 {"# invalid", "", "invalid format of version-info: .*"}, 85 {"-1", "", "invalid format of version-info: .*"}, 86 } { 87 c.Logf("tc: %v", i) 88 cmd := testutil.MockCommand(c, "snap-seccomp", fmt.Sprintf("echo \"%s\"", tc.v)) 89 compiler, err := seccomp.New(fromCmd(c, cmd)) 90 c.Assert(err, IsNil) 91 92 v, err := compiler.VersionInfo() 93 if tc.err != "" { 94 c.Check(err, ErrorMatches, tc.err) 95 c.Check(v, Equals, seccomp.VersionInfo("")) 96 } else { 97 c.Check(err, IsNil) 98 c.Check(v, Equals, seccomp.VersionInfo(tc.exp)) 99 _, err := seccomp.VersionInfo(v).LibseccompVersion() 100 c.Check(err, IsNil) 101 _, err = seccomp.VersionInfo(v).Features() 102 c.Check(err, IsNil) 103 } 104 c.Check(cmd.Calls(), DeepEquals, [][]string{ 105 {"snap-seccomp", "version-info"}, 106 }) 107 cmd.Restore() 108 } 109 110 } 111 112 func (s *compilerSuite) TestCompilerVersionInfo(c *C) { 113 const vi = "7ac348ac9c934269214b00d1692dfa50d5d4a157 2.3.3 03e996919907bc7163bc83b95bca0ecab31300f20dfa365ea14047c698340e7c bpf-actlog" 114 cmd := testutil.MockCommand(c, "snap-seccomp", fmt.Sprintf(`echo "%s"`, vi)) 115 116 vi1, err := seccomp.CompilerVersionInfo(fromCmd(c, cmd)) 117 c.Check(err, IsNil) 118 c.Check(vi1, Equals, seccomp.VersionInfo(vi)) 119 } 120 121 func (s *compilerSuite) TestEmptyVersionInfo(c *C) { 122 vi := seccomp.VersionInfo("") 123 124 _, err := vi.LibseccompVersion() 125 c.Check(err, ErrorMatches, "empty version-info") 126 127 _, err = vi.Features() 128 c.Check(err, ErrorMatches, "empty version-info") 129 } 130 131 func (s *compilerSuite) TestVersionInfoUnhappy(c *C) { 132 cmd := testutil.MockCommand(c, "snap-seccomp", ` 133 if [ "$1" = "version-info" ]; then echo "unknown command version-info"; exit 1; fi 134 exit 0 135 `) 136 defer cmd.Restore() 137 compiler, err := seccomp.New(fromCmd(c, cmd)) 138 c.Assert(err, IsNil) 139 140 _, err = compiler.VersionInfo() 141 c.Assert(err, ErrorMatches, "unknown command version-info") 142 c.Check(cmd.Calls(), DeepEquals, [][]string{ 143 {"snap-seccomp", "version-info"}, 144 }) 145 } 146 147 func (s *compilerSuite) TestCompileEasy(c *C) { 148 cmd := testutil.MockCommand(c, "snap-seccomp", ` 149 if [ "$1" = "compile" ]; then exit 0; fi 150 exit 1 151 `) 152 defer cmd.Restore() 153 compiler, err := seccomp.New(fromCmd(c, cmd)) 154 c.Assert(err, IsNil) 155 156 err = compiler.Compile("foo.src", "foo.bin") 157 c.Assert(err, IsNil) 158 c.Check(cmd.Calls(), DeepEquals, [][]string{ 159 {"snap-seccomp", "compile", "foo.src", "foo.bin"}, 160 }) 161 } 162 163 func (s *compilerSuite) TestCompileUnhappy(c *C) { 164 cmd := testutil.MockCommand(c, "snap-seccomp", ` 165 if [ "$1" = "compile" ]; then echo "i will not"; exit 1; fi 166 exit 0 167 `) 168 defer cmd.Restore() 169 compiler, err := seccomp.New(fromCmd(c, cmd)) 170 c.Assert(err, IsNil) 171 172 err = compiler.Compile("foo.src", "foo.bin") 173 c.Assert(err, ErrorMatches, "i will not") 174 c.Check(cmd.Calls(), DeepEquals, [][]string{ 175 {"snap-seccomp", "compile", "foo.src", "foo.bin"}, 176 }) 177 } 178 179 func (s *compilerSuite) TestCompilerNewUnhappy(c *C) { 180 compiler, err := seccomp.New(func(name string) (string, error) { return "", errors.New("failed") }) 181 c.Assert(err, ErrorMatches, "failed") 182 c.Assert(compiler, IsNil) 183 184 c.Assert(func() { seccomp.New(nil) }, PanicMatches, "lookup tool func not provided") 185 } 186 187 func (s *compilerSuite) TestLibseccompVersion(c *C) { 188 v, err := seccomp.VersionInfo("a 2.4.1 b -").LibseccompVersion() 189 c.Assert(err, IsNil) 190 c.Check(v, Equals, "2.4.1") 191 192 v, err = seccomp.VersionInfo("a phooey b -").LibseccompVersion() 193 c.Assert(err, ErrorMatches, "invalid format of version-info: .*") 194 c.Check(v, Equals, "") 195 } 196 197 func (s *compilerSuite) TestGetGoSeccompFeatures(c *C) { 198 for _, tc := range []struct { 199 v string 200 exp string 201 err string 202 }{ 203 // valid 204 {"a 2.4.1 b -", "-", ""}, 205 {"a 2.4.1 b foo", "foo", ""}, 206 {"a 2.4.1 b foo:bar", "foo:bar", ""}, 207 // invalid 208 {"a 2.4.1 b b@rf", "", "invalid format of version-info: .*"}, 209 } { 210 v, err := seccomp.VersionInfo(tc.v).Features() 211 if err == nil { 212 c.Assert(err, IsNil) 213 c.Check(v, Equals, tc.exp) 214 } else { 215 c.Assert(err, ErrorMatches, "invalid format of version-info: .*") 216 c.Check(v, Equals, tc.exp) 217 } 218 } 219 } 220 221 func (s *compilerSuite) TestHasFeature(c *C) { 222 for _, tc := range []struct { 223 v string 224 f string 225 exp bool 226 err string 227 }{ 228 // valid negative 229 {"a 2.4.1 b -", "foo", false, ""}, 230 {"a 2.4.1 b foo:bar", "foo:bar", false, ""}, 231 // valid affirmative 232 {"a 2.4.1 b foo", "foo", true, ""}, 233 {"a 2.4.1 b foo:bar", "foo", true, ""}, 234 {"a 2.4.1 b foo:bar", "bar", true, ""}, 235 // invalid 236 {"a 1.2.3 b b@rf", "b@rf", false, "invalid format of version-info: .*"}, 237 } { 238 v, err := seccomp.VersionInfo(tc.v).HasFeature(tc.f) 239 if err == nil { 240 c.Assert(err, IsNil) 241 c.Check(v, Equals, tc.exp) 242 } else { 243 c.Assert(err, ErrorMatches, "invalid format of version-info: .*") 244 c.Check(v, Equals, tc.exp) 245 } 246 } 247 } 248 249 func (s *compilerSuite) TestSupportsRobustArgumentFiltering(c *C) { 250 for _, tc := range []struct { 251 v string 252 err string 253 }{ 254 // libseccomp < 2.3.3 and golang-seccomp < 0.9.1 255 {"a 2.3.3 b -", "robust argument filtering requires a snapd built against libseccomp >= 2.4, golang-seccomp >= 0.9.1"}, 256 // libseccomp < 2.3.3 257 {"a 2.3.3 b bpf-actlog", "robust argument filtering requires a snapd built against libseccomp >= 2.4"}, 258 // golang-seccomp < 0.9.1 259 {"a 2.4.1 b -", "robust argument filtering requires a snapd built against golang-seccomp >= 0.9.1"}, 260 {"a 2.4.1 b bpf-other", "robust argument filtering requires a snapd built against golang-seccomp >= 0.9.1"}, 261 // libseccomp >= 2.4.1 and golang-seccomp >= 0.9.1 262 {"a 2.4.1 b bpf-actlog", ""}, 263 {"a 3.0.0 b bpf-actlog", ""}, 264 // invalid 265 {"a 1.2.3 b b@rf", "invalid format of version-info: .*"}, 266 } { 267 err := seccomp.VersionInfo(tc.v).SupportsRobustArgumentFiltering() 268 if tc.err == "" { 269 c.Assert(err, IsNil) 270 } else { 271 c.Assert(err, ErrorMatches, tc.err) 272 } 273 } 274 }