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