github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/interfaces/apparmor/spec_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2018 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 20 package apparmor_test 21 22 import ( 23 "strings" 24 25 . "gopkg.in/check.v1" 26 27 "github.com/snapcore/snapd/interfaces" 28 "github.com/snapcore/snapd/interfaces/apparmor" 29 "github.com/snapcore/snapd/interfaces/ifacetest" 30 "github.com/snapcore/snapd/snap" 31 "github.com/snapcore/snapd/snap/snaptest" 32 "github.com/snapcore/snapd/testutil" 33 ) 34 35 type specSuite struct { 36 testutil.BaseTest 37 iface *ifacetest.TestInterface 38 spec *apparmor.Specification 39 plugInfo *snap.PlugInfo 40 plug *interfaces.ConnectedPlug 41 slotInfo *snap.SlotInfo 42 slot *interfaces.ConnectedSlot 43 } 44 45 var _ = Suite(&specSuite{ 46 iface: &ifacetest.TestInterface{ 47 InterfaceName: "test", 48 AppArmorConnectedPlugCallback: func(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 49 spec.AddSnippet("connected-plug") 50 return nil 51 }, 52 AppArmorConnectedSlotCallback: func(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 53 spec.AddSnippet("connected-slot") 54 return nil 55 }, 56 AppArmorPermanentPlugCallback: func(spec *apparmor.Specification, plug *snap.PlugInfo) error { 57 spec.AddSnippet("permanent-plug") 58 return nil 59 }, 60 AppArmorPermanentSlotCallback: func(spec *apparmor.Specification, slot *snap.SlotInfo) error { 61 spec.AddSnippet("permanent-slot") 62 return nil 63 }, 64 }, 65 plugInfo: &snap.PlugInfo{ 66 Snap: &snap.Info{SuggestedName: "snap1"}, 67 Name: "name", 68 Interface: "test", 69 Apps: map[string]*snap.AppInfo{ 70 "app1": { 71 Snap: &snap.Info{ 72 SuggestedName: "snap1", 73 }, 74 Name: "app1"}}, 75 }, 76 slotInfo: &snap.SlotInfo{ 77 Snap: &snap.Info{SuggestedName: "snap2"}, 78 Name: "name", 79 Interface: "test", 80 Apps: map[string]*snap.AppInfo{ 81 "app2": { 82 Snap: &snap.Info{ 83 SuggestedName: "snap2", 84 }, 85 Name: "app2"}}, 86 }, 87 }) 88 89 func (s *specSuite) SetUpTest(c *C) { 90 s.BaseTest.SetUpTest(c) 91 s.BaseTest.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})) 92 93 s.spec = &apparmor.Specification{} 94 s.plug = interfaces.NewConnectedPlug(s.plugInfo, nil, nil) 95 s.slot = interfaces.NewConnectedSlot(s.slotInfo, nil, nil) 96 } 97 98 func (s *specSuite) TearDownTest(c *C) { 99 s.BaseTest.TearDownTest(c) 100 } 101 102 // The spec.Specification can be used through the interfaces.Specification interface 103 func (s *specSuite) TestSpecificationIface(c *C) { 104 var r interfaces.Specification = s.spec 105 c.Assert(r.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil) 106 c.Assert(r.AddConnectedSlot(s.iface, s.plug, s.slot), IsNil) 107 c.Assert(r.AddPermanentPlug(s.iface, s.plugInfo), IsNil) 108 c.Assert(r.AddPermanentSlot(s.iface, s.slotInfo), IsNil) 109 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{ 110 "snap.snap1.app1": {"connected-plug", "permanent-plug"}, 111 "snap.snap2.app2": {"connected-slot", "permanent-slot"}, 112 }) 113 } 114 115 // AddSnippet adds a snippet for the given security tag. 116 func (s *specSuite) TestAddSnippet(c *C) { 117 restore := apparmor.SetSpecScope(s.spec, []string{"snap.demo.command", "snap.demo.service"}) 118 defer restore() 119 120 // Add two snippets in the context we are in. 121 s.spec.AddSnippet("snippet 1") 122 s.spec.AddSnippet("snippet 2") 123 124 // The snippets were recorded correctly. 125 c.Assert(s.spec.UpdateNS(), HasLen, 0) 126 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{ 127 "snap.demo.command": {"snippet 1", "snippet 2"}, 128 "snap.demo.service": {"snippet 1", "snippet 2"}, 129 }) 130 c.Assert(s.spec.SnippetsForTag("snap.demo.command"), DeepEquals, []string{"snippet 1", "snippet 2"}) 131 c.Assert(s.spec.SnippetForTag("snap.demo.command"), Equals, "snippet 1\nsnippet 2") 132 c.Assert(s.spec.SecurityTags(), DeepEquals, []string{"snap.demo.command", "snap.demo.service"}) 133 } 134 135 // AddDeduplicatedSnippet adds a snippet for the given security tag. 136 func (s *specSuite) TestAddDeduplicatedSnippet(c *C) { 137 restore := apparmor.SetSpecScope(s.spec, []string{"snap.demo.command", "snap.demo.service"}) 138 defer restore() 139 140 // Add two snippets in the context we are in. 141 s.spec.AddDeduplicatedSnippet("dedup snippet 1") 142 s.spec.AddDeduplicatedSnippet("dedup snippet 1") 143 s.spec.AddDeduplicatedSnippet("dedup snippet 2") 144 s.spec.AddDeduplicatedSnippet("dedup snippet 2") 145 146 // The snippets were recorded correctly. 147 c.Assert(s.spec.UpdateNS(), HasLen, 0) 148 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{ 149 "snap.demo.command": {"dedup snippet 1", "dedup snippet 2"}, 150 "snap.demo.service": {"dedup snippet 1", "dedup snippet 2"}, 151 }) 152 c.Assert(s.spec.SnippetsForTag("snap.demo.command"), DeepEquals, []string{"dedup snippet 1", "dedup snippet 2"}) 153 c.Assert(s.spec.SnippetForTag("snap.demo.command"), Equals, "dedup snippet 1\ndedup snippet 2") 154 c.Assert(s.spec.SecurityTags(), DeepEquals, []string{"snap.demo.command", "snap.demo.service"}) 155 } 156 157 func (s *specSuite) TestAddParametricSnippet(c *C) { 158 restore := apparmor.SetSpecScope(s.spec, []string{"snap.demo.command", "snap.demo.service"}) 159 defer restore() 160 161 s.spec.AddParametricSnippet([]string{"prefix ", " postfix"}, "param1") 162 s.spec.AddParametricSnippet([]string{"prefix ", " postfix"}, "param1") 163 s.spec.AddParametricSnippet([]string{"prefix ", " postfix"}, "param2") 164 s.spec.AddParametricSnippet([]string{"prefix ", " postfix"}, "param2") 165 s.spec.AddParametricSnippet([]string{"other "}, "param") 166 c.Assert(s.spec.SnippetsForTag("snap.demo.command"), DeepEquals, []string{ 167 "other param", 168 "prefix {param1,param2} postfix", 169 }) 170 c.Assert(s.spec.SnippetForTag("snap.demo.command"), Equals, "other param\nprefix {param1,param2} postfix") 171 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{ 172 "snap.demo.command": {"other param", "prefix {param1,param2} postfix"}, 173 "snap.demo.service": {"other param", "prefix {param1,param2} postfix"}, 174 }) 175 } 176 177 // All of AddSnippet, AddDeduplicatedSnippet, AddParameticSnippet work correctly together. 178 func (s *specSuite) TestAddSnippetAndAddDeduplicatedAndParamSnippet(c *C) { 179 restore := apparmor.SetSpecScope(s.spec, []string{"snap.demo.command", "snap.demo.service"}) 180 defer restore() 181 182 // Add three snippets in the context we are in. 183 s.spec.AddSnippet("normal") 184 s.spec.AddDeduplicatedSnippet("dedup") 185 s.spec.AddParametricSnippet([]string{""}, "param") 186 187 // The snippets were recorded correctly. 188 c.Assert(s.spec.UpdateNS(), HasLen, 0) 189 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{ 190 "snap.demo.command": {"normal", "dedup", "param"}, 191 "snap.demo.service": {"normal", "dedup", "param"}, 192 }) 193 c.Assert(s.spec.SnippetsForTag("snap.demo.command"), DeepEquals, []string{"normal", "dedup", "param"}) 194 c.Assert(s.spec.SnippetForTag("snap.demo.command"), Equals, "normal\ndedup\nparam") 195 c.Assert(s.spec.SecurityTags(), DeepEquals, []string{"snap.demo.command", "snap.demo.service"}) 196 } 197 198 // Define tags but don't add any snippets. 199 func (s *specSuite) TestTagsButNoSnippets(c *C) { 200 restore := apparmor.SetSpecScope(s.spec, []string{"snap.demo.command", "snap.demo.service"}) 201 defer restore() 202 203 c.Assert(s.spec.UpdateNS(), HasLen, 0) 204 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{}) 205 c.Assert(s.spec.SnippetsForTag("snap.demo.command"), DeepEquals, []string(nil)) 206 c.Assert(s.spec.SnippetForTag("snap.demo.command"), Equals, "") 207 c.Assert(s.spec.SecurityTags(), DeepEquals, []string(nil)) 208 } 209 210 // Don't define any tags but add snippets. 211 func (s *specSuite) TestNoTagsButWithSnippets(c *C) { 212 restore := apparmor.SetSpecScope(s.spec, []string{}) 213 defer restore() 214 215 s.spec.AddSnippet("normal") 216 s.spec.AddDeduplicatedSnippet("dedup") 217 s.spec.AddParametricSnippet([]string{""}, "param") 218 219 c.Assert(s.spec.UpdateNS(), HasLen, 0) 220 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{}) 221 c.Assert(s.spec.SnippetsForTag("snap.demo.command"), DeepEquals, []string(nil)) 222 c.Assert(s.spec.SnippetForTag("snap.demo.command"), Equals, "") 223 c.Assert(s.spec.SecurityTags(), DeepEquals, []string(nil)) 224 } 225 226 // Don't define any tags or snippets. 227 func (s *specSuite) TestsNoTagsOrSnippets(c *C) { 228 restore := apparmor.SetSpecScope(s.spec, []string{}) 229 defer restore() 230 231 c.Assert(s.spec.UpdateNS(), HasLen, 0) 232 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{}) 233 c.Assert(s.spec.SnippetsForTag("snap.demo.command"), DeepEquals, []string(nil)) 234 c.Assert(s.spec.SnippetForTag("snap.demo.command"), Equals, "") 235 c.Assert(s.spec.SecurityTags(), DeepEquals, []string(nil)) 236 } 237 238 // AddUpdateNS adds a snippet for the snap-update-ns profile for a given snap. 239 func (s *specSuite) TestAddUpdateNS(c *C) { 240 restore := apparmor.SetSpecScope(s.spec, []string{"snap.demo.command", "snap.demo.service"}) 241 defer restore() 242 243 // Add a two snap-update-ns snippets in the context we are in. 244 s.spec.AddUpdateNS("s-u-n snippet 1") 245 s.spec.AddUpdateNS("s-u-n snippet 2") 246 247 // Check the order of the snippets can be retrieved. 248 idx, ok := s.spec.UpdateNSIndexOf("s-u-n snippet 2") 249 c.Assert(ok, Equals, true) 250 c.Check(idx, Equals, 1) 251 252 // The snippets were recorded correctly and in the right place. 253 c.Assert(s.spec.UpdateNS(), DeepEquals, []string{ 254 "s-u-n snippet 1", "s-u-n snippet 2", 255 }) 256 c.Assert(s.spec.SnippetForTag("snap.demo.command"), Equals, "") 257 c.Assert(s.spec.SecurityTags(), HasLen, 0) 258 } 259 260 const snapWithLayout = ` 261 name: vanguard 262 version: 0 263 apps: 264 vanguard: 265 command: vanguard 266 layout: 267 /usr/foo: 268 bind: $SNAP/usr/foo 269 /var/tmp: 270 type: tmpfs 271 mode: 1777 272 /var/cache/mylink: 273 symlink: $SNAP_DATA/link/target 274 /etc/foo.conf: 275 bind-file: $SNAP/foo.conf 276 ` 277 278 func (s *specSuite) TestApparmorSnippetsFromLayout(c *C) { 279 snapInfo := snaptest.MockInfo(c, snapWithLayout, &snap.SideInfo{Revision: snap.R(42)}) 280 restore := apparmor.SetSpecScope(s.spec, []string{"snap.vanguard.vanguard"}) 281 defer restore() 282 283 s.spec.AddLayout(snapInfo) 284 c.Assert(s.spec.Snippets(), DeepEquals, map[string][]string{ 285 "snap.vanguard.vanguard": { 286 "# Layout path: /etc/foo.conf\n/etc/foo.conf mrwklix,", 287 "# Layout path: /usr/foo\n/usr/foo{,/**} mrwklix,", 288 "# Layout path: /var/cache/mylink\n# (no extra permissions required for symlink)", 289 "# Layout path: /var/tmp\n/var/tmp{,/**} mrwklix,", 290 }, 291 }) 292 updateNS := s.spec.UpdateNS() 293 294 profile0 := ` # Layout /etc/foo.conf: bind-file $SNAP/foo.conf 295 mount options=(bind, rw) /snap/vanguard/42/foo.conf -> /etc/foo.conf, 296 mount options=(rprivate) -> /etc/foo.conf, 297 umount /etc/foo.conf, 298 # Writable mimic /etc 299 # .. permissions for traversing the prefix that is assumed to exist 300 / r, 301 # .. variant with mimic at /etc/ 302 # Allow reading the mimic directory, it must exist in the first place. 303 /etc/ r, 304 # Allow setting the read-only directory aside via a bind mount. 305 /tmp/.snap/etc/ rw, 306 mount options=(rbind, rw) /etc/ -> /tmp/.snap/etc/, 307 # Allow mounting tmpfs over the read-only directory. 308 mount fstype=tmpfs options=(rw) tmpfs -> /etc/, 309 # Allow creating empty files and directories for bind mounting things 310 # to reconstruct the now-writable parent directory. 311 /tmp/.snap/etc/*/ rw, 312 /etc/*/ rw, 313 mount options=(rbind, rw) /tmp/.snap/etc/*/ -> /etc/*/, 314 /tmp/.snap/etc/* rw, 315 /etc/* rw, 316 mount options=(bind, rw) /tmp/.snap/etc/* -> /etc/*, 317 # Allow unmounting the auxiliary directory. 318 # TODO: use fstype=tmpfs here for more strictness (LP: #1613403) 319 mount options=(rprivate) -> /tmp/.snap/etc/, 320 umount /tmp/.snap/etc/, 321 # Allow unmounting the destination directory as well as anything 322 # inside. This lets us perform the undo plan in case the writable 323 # mimic fails. 324 mount options=(rprivate) -> /etc/, 325 mount options=(rprivate) -> /etc/*, 326 mount options=(rprivate) -> /etc/*/, 327 umount /etc/, 328 umount /etc/*, 329 umount /etc/*/, 330 # Writable mimic /snap/vanguard/42 331 /snap/ r, 332 /snap/vanguard/ r, 333 # .. variant with mimic at /snap/vanguard/42/ 334 /snap/vanguard/42/ r, 335 /tmp/.snap/snap/vanguard/42/ rw, 336 mount options=(rbind, rw) /snap/vanguard/42/ -> /tmp/.snap/snap/vanguard/42/, 337 mount fstype=tmpfs options=(rw) tmpfs -> /snap/vanguard/42/, 338 /tmp/.snap/snap/vanguard/42/*/ rw, 339 /snap/vanguard/42/*/ rw, 340 mount options=(rbind, rw) /tmp/.snap/snap/vanguard/42/*/ -> /snap/vanguard/42/*/, 341 /tmp/.snap/snap/vanguard/42/* rw, 342 /snap/vanguard/42/* rw, 343 mount options=(bind, rw) /tmp/.snap/snap/vanguard/42/* -> /snap/vanguard/42/*, 344 mount options=(rprivate) -> /tmp/.snap/snap/vanguard/42/, 345 umount /tmp/.snap/snap/vanguard/42/, 346 mount options=(rprivate) -> /snap/vanguard/42/, 347 mount options=(rprivate) -> /snap/vanguard/42/*, 348 mount options=(rprivate) -> /snap/vanguard/42/*/, 349 umount /snap/vanguard/42/, 350 umount /snap/vanguard/42/*, 351 umount /snap/vanguard/42/*/, 352 ` 353 // Find the slice that describes profile0 by looking for the first unique 354 // line of the next profile. 355 start := 0 356 end, _ := s.spec.UpdateNSIndexOf(" # Layout /usr/foo: bind $SNAP/usr/foo\n") 357 c.Assert(strings.Join(updateNS[start:end], ""), Equals, profile0) 358 359 profile1 := ` # Layout /usr/foo: bind $SNAP/usr/foo 360 mount options=(rbind, rw) /snap/vanguard/42/usr/foo/ -> /usr/foo/, 361 mount options=(rprivate) -> /usr/foo/, 362 umount /usr/foo/, 363 # Writable mimic /usr 364 # .. variant with mimic at /usr/ 365 /usr/ r, 366 /tmp/.snap/usr/ rw, 367 mount options=(rbind, rw) /usr/ -> /tmp/.snap/usr/, 368 mount fstype=tmpfs options=(rw) tmpfs -> /usr/, 369 /tmp/.snap/usr/*/ rw, 370 /usr/*/ rw, 371 mount options=(rbind, rw) /tmp/.snap/usr/*/ -> /usr/*/, 372 /tmp/.snap/usr/* rw, 373 /usr/* rw, 374 mount options=(bind, rw) /tmp/.snap/usr/* -> /usr/*, 375 mount options=(rprivate) -> /tmp/.snap/usr/, 376 umount /tmp/.snap/usr/, 377 mount options=(rprivate) -> /usr/, 378 mount options=(rprivate) -> /usr/*, 379 mount options=(rprivate) -> /usr/*/, 380 umount /usr/, 381 umount /usr/*, 382 umount /usr/*/, 383 # Writable mimic /snap/vanguard/42/usr 384 # .. variant with mimic at /snap/vanguard/42/usr/ 385 /snap/vanguard/42/usr/ r, 386 /tmp/.snap/snap/vanguard/42/usr/ rw, 387 mount options=(rbind, rw) /snap/vanguard/42/usr/ -> /tmp/.snap/snap/vanguard/42/usr/, 388 mount fstype=tmpfs options=(rw) tmpfs -> /snap/vanguard/42/usr/, 389 /tmp/.snap/snap/vanguard/42/usr/*/ rw, 390 /snap/vanguard/42/usr/*/ rw, 391 mount options=(rbind, rw) /tmp/.snap/snap/vanguard/42/usr/*/ -> /snap/vanguard/42/usr/*/, 392 /tmp/.snap/snap/vanguard/42/usr/* rw, 393 /snap/vanguard/42/usr/* rw, 394 mount options=(bind, rw) /tmp/.snap/snap/vanguard/42/usr/* -> /snap/vanguard/42/usr/*, 395 mount options=(rprivate) -> /tmp/.snap/snap/vanguard/42/usr/, 396 umount /tmp/.snap/snap/vanguard/42/usr/, 397 mount options=(rprivate) -> /snap/vanguard/42/usr/, 398 mount options=(rprivate) -> /snap/vanguard/42/usr/*, 399 mount options=(rprivate) -> /snap/vanguard/42/usr/*/, 400 umount /snap/vanguard/42/usr/, 401 umount /snap/vanguard/42/usr/*, 402 umount /snap/vanguard/42/usr/*/, 403 ` 404 // Find the slice that describes profile1 by looking for the first unique 405 // line of the next profile. 406 start = end 407 end, _ = s.spec.UpdateNSIndexOf(" # Layout /var/cache/mylink: symlink $SNAP_DATA/link/target\n") 408 c.Assert(strings.Join(updateNS[start:end], ""), Equals, profile1) 409 410 profile2 := ` # Layout /var/cache/mylink: symlink $SNAP_DATA/link/target 411 /var/cache/mylink rw, 412 # Writable mimic /var/cache 413 # .. variant with mimic at /var/ 414 /var/ r, 415 /tmp/.snap/var/ rw, 416 mount options=(rbind, rw) /var/ -> /tmp/.snap/var/, 417 mount fstype=tmpfs options=(rw) tmpfs -> /var/, 418 /tmp/.snap/var/*/ rw, 419 /var/*/ rw, 420 mount options=(rbind, rw) /tmp/.snap/var/*/ -> /var/*/, 421 /tmp/.snap/var/* rw, 422 /var/* rw, 423 mount options=(bind, rw) /tmp/.snap/var/* -> /var/*, 424 mount options=(rprivate) -> /tmp/.snap/var/, 425 umount /tmp/.snap/var/, 426 mount options=(rprivate) -> /var/, 427 mount options=(rprivate) -> /var/*, 428 mount options=(rprivate) -> /var/*/, 429 umount /var/, 430 umount /var/*, 431 umount /var/*/, 432 # .. variant with mimic at /var/cache/ 433 /var/cache/ r, 434 /tmp/.snap/var/cache/ rw, 435 mount options=(rbind, rw) /var/cache/ -> /tmp/.snap/var/cache/, 436 mount fstype=tmpfs options=(rw) tmpfs -> /var/cache/, 437 /tmp/.snap/var/cache/*/ rw, 438 /var/cache/*/ rw, 439 mount options=(rbind, rw) /tmp/.snap/var/cache/*/ -> /var/cache/*/, 440 /tmp/.snap/var/cache/* rw, 441 /var/cache/* rw, 442 mount options=(bind, rw) /tmp/.snap/var/cache/* -> /var/cache/*, 443 mount options=(rprivate) -> /tmp/.snap/var/cache/, 444 umount /tmp/.snap/var/cache/, 445 mount options=(rprivate) -> /var/cache/, 446 mount options=(rprivate) -> /var/cache/*, 447 mount options=(rprivate) -> /var/cache/*/, 448 umount /var/cache/, 449 umount /var/cache/*, 450 umount /var/cache/*/, 451 ` 452 // Find the slice that describes profile2 by looking for the first unique 453 // line of the next profile. 454 start = end 455 end, _ = s.spec.UpdateNSIndexOf(" # Layout /var/tmp: type tmpfs, mode: 01777\n") 456 c.Assert(strings.Join(updateNS[start:end], ""), Equals, profile2) 457 458 profile3 := ` # Layout /var/tmp: type tmpfs, mode: 01777 459 mount fstype=tmpfs tmpfs -> /var/tmp/, 460 mount options=(rprivate) -> /var/tmp/, 461 umount /var/tmp/, 462 # Writable mimic /var 463 ` 464 // Find the slice that describes profile2 by looking till the end of the list. 465 start = end 466 c.Assert(strings.Join(updateNS[start:], ""), Equals, profile3) 467 c.Assert(strings.Join(updateNS, ""), DeepEquals, strings.Join([]string{profile0, profile1, profile2, profile3}, "")) 468 } 469 470 const snapTrivial = ` 471 name: some-snap 472 version: 0 473 apps: 474 app: 475 command: app-command 476 ` 477 478 func (s *specSuite) TestApparmorOvernameSnippetsNotInstanceKeyed(c *C) { 479 snapInfo := snaptest.MockInfo(c, snapTrivial, &snap.SideInfo{Revision: snap.R(42)}) 480 restore := apparmor.SetSpecScope(s.spec, []string{"snap.some-snap.app"}) 481 defer restore() 482 483 s.spec.AddOvername(snapInfo) 484 c.Assert(s.spec.Snippets(), HasLen, 0) 485 // non instance-keyed snaps require no extra snippets 486 c.Assert(s.spec.UpdateNS(), HasLen, 0) 487 } 488 489 func (s *specSuite) TestApparmorOvernameSnippets(c *C) { 490 snapInfo := snaptest.MockInfo(c, snapTrivial, &snap.SideInfo{Revision: snap.R(42)}) 491 snapInfo.InstanceKey = "instance" 492 493 restore := apparmor.SetSpecScope(s.spec, []string{"snap.some-snap_instace.app"}) 494 defer restore() 495 496 s.spec.AddOvername(snapInfo) 497 c.Assert(s.spec.Snippets(), HasLen, 0) 498 499 updateNS := s.spec.UpdateNS() 500 c.Assert(updateNS, HasLen, 1) 501 502 profile := ` # Allow parallel instance snap mount namespace adjustments 503 mount options=(rw rbind) /snap/some-snap_instance/ -> /snap/some-snap/, 504 mount options=(rw rbind) /var/snap/some-snap_instance/ -> /var/snap/some-snap/, 505 ` 506 c.Assert(updateNS[0], Equals, profile) 507 } 508 509 func (s *specSuite) TestUsesPtraceTrace(c *C) { 510 c.Assert(s.spec.UsesPtraceTrace(), Equals, false) 511 s.spec.SetUsesPtraceTrace() 512 c.Assert(s.spec.UsesPtraceTrace(), Equals, true) 513 } 514 515 func (s *specSuite) TestSuppressPtraceTrace(c *C) { 516 c.Assert(s.spec.SuppressPtraceTrace(), Equals, false) 517 s.spec.SetSuppressPtraceTrace() 518 c.Assert(s.spec.SuppressPtraceTrace(), Equals, true) 519 } 520 521 func (s *specSuite) TestSetSuppressHomeIx(c *C) { 522 c.Assert(s.spec.SuppressHomeIx(), Equals, false) 523 s.spec.SetSuppressHomeIx() 524 c.Assert(s.spec.SuppressHomeIx(), Equals, true) 525 }