Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

interfaces,overlord: allow access to kernel snap in profiles #14899

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions interfaces/apparmor/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,15 @@ func (b *Backend) addContent(securityTag string, snapInfo *snap.Info, cmdName st
}
policy = templatePattern.ReplaceAllStringFunc(policy, func(placeholder string) string {
switch placeholder {
case "###KERNEL_MODULES_AND_FIRMWARE###":
if opts.KernelSnap != "" {
return fmt.Sprintf(`
# Allow access to kernel modules and firmware from the kernel snap
/snap/%[1]s/*/{modules,firmware}/{,**} r,
pedronis marked this conversation as resolved.
Show resolved Hide resolved
/snap/%[1]s/components/mnt/*/*/{modules,firmware}/{,**} r,
/var/snap/%[1]s/*/{modules,firmware}/{,**} r,`, opts.KernelSnap)
}
return ""
case "###DEVMODE_SNAP_CONFINE###":
if !opts.DevMode {
// nothing to add if we are not in devmode
Expand Down
36 changes: 36 additions & 0 deletions interfaces/apparmor/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2986,3 +2986,39 @@ func (s *backendSuite) TestRemoveAllSnapAppArmorProfiles(c *C) {
c.Check(os.IsNotExist(err), Equals, true)
}
}

func (s *backendSuite) TestKernelModulesAndFwRule(c *C) {
restoreTemplate := apparmor.MockTemplate("template\n###KERNEL_MODULES_AND_FIRMWARE###\n")
defer restoreTemplate()
restore := apparmor_sandbox.MockLevel(apparmor_sandbox.Full)
defer restore()
restore = osutil.MockIsHomeUsingRemoteFS(func() (bool, error) { return false, nil })
defer restore()

for _, tc := range []struct {
opts interfaces.ConfinementOptions
suppress bool
expected Checker
}{
{
opts: interfaces.ConfinementOptions{},
expected: Not(testutil.Contains),
},
{
opts: interfaces.ConfinementOptions{KernelSnap: "mykernel"},
expected: testutil.Contains,
},
} {
snapInfo := s.InstallSnap(c, tc.opts, "", ifacetest.SambaYamlV1, 1)
profile := filepath.Join(dirs.SnapAppArmorDir, "snap.samba.smbd")
data, err := os.ReadFile(profile)
c.Assert(err, IsNil)

c.Assert(string(data), tc.expected, `
# Allow access to kernel modules and firmware from the kernel snap
/snap/mykernel/*/{modules,firmware}/{,**} r,
/snap/mykernel/components/mnt/*/*/{modules,firmware}/{,**} r,
/var/snap/mykernel/*/{modules,firmware}/{,**} r,`)
s.RemoveSnap(c, snapInfo)
}
}
1 change: 1 addition & 0 deletions interfaces/apparmor/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ var templateCommon = `
#include <abstractions/base>
#include <abstractions/consoles>
#include <abstractions/openssl>
###KERNEL_MODULES_AND_FIRMWARE###

# While in later versions of the base abstraction, include this explicitly
# for series 16 and cross-distro
Expand Down
3 changes: 3 additions & 0 deletions interfaces/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ type ConfinementOptions struct {
// AppArmorPrompting indicates whether the prompt prefix should be used in
// relevant rules when generating AppArmor security profiles.
AppArmorPrompting bool
// KernelSnap is the name of the kernel snap in the system
// (empty for classic systems).
KernelSnap string
}

// SecurityBackendOptions carries extra flags that affect initialization of the
Expand Down
7 changes: 7 additions & 0 deletions overlord/ifacestate/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,19 @@ func (m *InterfaceManager) buildConfinementOptions(st *state.State, snapInfo *sn
return interfaces.ConfinementOptions{}, fmt.Errorf("cannot get extra mount layouts of snap %q: %s", snapInfo.InstanceName(), err)
}

kernelSnap := ""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code here probably needs to take the task so we can do the right thin during remodel

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, fixed now

deviceCtx, err := snapstate.DeviceCtx(st, nil, nil)
if err == nil {
kernelSnap = deviceCtx.Kernel()
}

return interfaces.ConfinementOptions{
DevMode: flags.DevMode,
JailMode: flags.JailMode,
Classic: flags.Classic,
ExtraLayouts: extraLayouts,
AppArmorPrompting: m.useAppArmorPrompting,
KernelSnap: kernelSnap,
}, nil
}

Expand Down
10 changes: 10 additions & 0 deletions overlord/ifacestate/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (

"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/overlord/configstate/config"
"github.com/snapcore/snapd/overlord/devicestate"
"github.com/snapcore/snapd/overlord/ifacestate"
"github.com/snapcore/snapd/overlord/servicestate/servicestatetest"
"github.com/snapcore/snapd/overlord/snapstate"
Expand All @@ -34,6 +35,7 @@ import (
"github.com/snapcore/snapd/snap"
"github.com/snapcore/snapd/snap/quota"
"github.com/snapcore/snapd/snap/snaptest"
"github.com/snapcore/snapd/testutil"
)

const snapAyaml = `name: snap-a
Expand All @@ -42,14 +44,22 @@ base: base-snap-a
`

type handlersSuite struct {
testutil.BaseTest
st *state.State
}

var _ = Suite(&handlersSuite{})

func (s *handlersSuite) mockModel() func() {
old := snapstate.DeviceCtx
snapstate.DeviceCtx = devicestate.DeviceCtx
return func() { snapstate.DeviceCtx = old }
}

func (s *handlersSuite) SetUpTest(c *C) {
s.st = state.New(nil)
dirs.SetRootDir(c.MkDir())
s.AddCleanup(s.mockModel())
}

func (s *handlersSuite) TearDownTest(c *C) {
Expand Down
44 changes: 22 additions & 22 deletions overlord/ifacestate/ifacestate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1814,8 +1814,8 @@ func (s *interfaceManagerSuite) testDisconnect(c *C, plugSnap, plugName, slotSna
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)

c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})

consumerAppSet := s.secBackend.SetupCalls[0].AppSet
c.Check(consumerAppSet.InstanceName(), Equals, "consumer")
Expand Down Expand Up @@ -4192,8 +4192,8 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecurityReloadsConnectionsWhenInv
c.Check(s.secBackend.SetupCalls[0].AppSet.InstanceName(), Equals, "consumer")
c.Check(s.secBackend.SetupCalls[1].AppSet.InstanceName(), Equals, "producer")

c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
}

func (s *interfaceManagerSuite) TestDoSetupSnapSecurityReloadsConnectionsWhenInvokedOnSlotSide(c *C) {
Expand All @@ -4210,8 +4210,8 @@ func (s *interfaceManagerSuite) TestDoSetupSnapSecurityReloadsConnectionsWhenInv
c.Check(s.secBackend.SetupCalls[0].AppSet.InstanceName(), Equals, "producer")
c.Check(s.secBackend.SetupCalls[1].AppSet.InstanceName(), Equals, "consumer")

c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
}

func (s *interfaceManagerSuite) testDoSetupSnapSecurityReloadsConnectionsWhenInvokedOn(c *C, snapName string, revision snap.Revision) {
Expand Down Expand Up @@ -4281,7 +4281,7 @@ func (s *interfaceManagerSuite) TestSetupProfilesHonorsDevMode(c *C) {
c.Assert(s.secBackend.SetupCalls, HasLen, 1)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
c.Check(s.secBackend.SetupCalls[0].AppSet.InstanceName(), Equals, "snap")
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{DevMode: true})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{DevMode: true, KernelSnap: "krnl"})
}

func (s *interfaceManagerSuite) TestSetupProfilesSetupManyError(c *C) {
Expand Down Expand Up @@ -5323,8 +5323,8 @@ func (s *interfaceManagerSuite) TestConnectSetsUpSecurity(c *C) {
c.Check(s.secBackend.SetupCalls[0].AppSet.InstanceName(), Equals, "producer")
c.Check(s.secBackend.SetupCalls[1].AppSet.InstanceName(), Equals, "consumer")

c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
}

func (s *interfaceManagerSuite) TestConnectWithComponentsSetsUpSecurity(c *C) {
Expand Down Expand Up @@ -5363,8 +5363,8 @@ func (s *interfaceManagerSuite) TestConnectWithComponentsSetsUpSecurity(c *C) {
c.Assert(s.secBackend.SetupCalls, HasLen, 2)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)

c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})

producerAppSet := s.secBackend.SetupCalls[0].AppSet
consumerAppSet := s.secBackend.SetupCalls[1].AppSet
Expand Down Expand Up @@ -5462,8 +5462,8 @@ func (s *interfaceManagerSuite) TestDisconnectSetsUpSecurity(c *C) {
c.Check(s.secBackend.SetupCalls[0].AppSet.InstanceName(), Equals, "consumer")
c.Check(s.secBackend.SetupCalls[1].AppSet.InstanceName(), Equals, "producer")

c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
}

func (s *interfaceManagerSuite) TestDisconnectTracksConnectionsInState(c *C) {
Expand Down Expand Up @@ -5893,13 +5893,13 @@ func (s *interfaceManagerSuite) TestSetupProfilesDevModeMultiple(c *C) {
c.Assert(s.secBackend.SetupCalls, HasLen, 4)
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
c.Check(s.secBackend.SetupCalls[0].AppSet.InstanceName(), Equals, siC.InstanceName())
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{DevMode: true})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{DevMode: true, KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[1].AppSet.InstanceName(), Equals, siP.InstanceName())
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[2].AppSet.InstanceName(), Equals, siC.InstanceName())
c.Check(s.secBackend.SetupCalls[2].Options, DeepEquals, interfaces.ConfinementOptions{DevMode: true})
c.Check(s.secBackend.SetupCalls[2].Options, DeepEquals, interfaces.ConfinementOptions{DevMode: true, KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[3].AppSet.InstanceName(), Equals, siP.InstanceName())
c.Check(s.secBackend.SetupCalls[3].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[3].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
}

func (s *interfaceManagerSuite) TestCheckInterfacesDeny(c *C) {
Expand Down Expand Up @@ -6352,7 +6352,7 @@ func (s *interfaceManagerSuite) TestUndoSetupProfilesOnRefresh(c *C) {
c.Assert(s.secBackend.RemoveCalls, HasLen, 0)
c.Check(s.secBackend.SetupCalls[0].AppSet.InstanceName(), Equals, snapInfo.InstanceName())
c.Check(s.secBackend.SetupCalls[0].AppSet.Info().Revision, Equals, snapInfo.Revision)
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})

var snapst snapstate.SnapState
err := snapstate.Get(s.state, "snap", &snapst)
Expand Down Expand Up @@ -6741,16 +6741,16 @@ func (s *interfaceManagerSuite) TestUndoConnect(c *C) {
c.Assert(s.secBackend.SetupCalls, HasLen, 4)
c.Check(s.secBackend.SetupCalls[0].AppSet.InstanceName(), Equals, "producer")
c.Check(s.secBackend.SetupCalls[1].AppSet.InstanceName(), Equals, "consumer")
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[0].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[1].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[0].AppSet.Runnables(), testutil.DeepUnsortedMatches, producerRunnablesFullSet)
c.Check(s.secBackend.SetupCalls[1].AppSet.Runnables(), testutil.DeepUnsortedMatches, consumerRunnablesFullSet)

// by undo
c.Check(s.secBackend.SetupCalls[2].AppSet.InstanceName(), Equals, "producer")
c.Check(s.secBackend.SetupCalls[3].AppSet.InstanceName(), Equals, "consumer")
c.Check(s.secBackend.SetupCalls[2].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[3].Options, DeepEquals, interfaces.ConfinementOptions{})
c.Check(s.secBackend.SetupCalls[2].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[3].Options, DeepEquals, interfaces.ConfinementOptions{KernelSnap: "krnl"})
c.Check(s.secBackend.SetupCalls[2].AppSet.Runnables(), testutil.DeepUnsortedMatches, producerRunnablesFullSet)
c.Check(s.secBackend.SetupCalls[3].AppSet.Runnables(), testutil.DeepUnsortedMatches, consumerRunnablesFullSet)
}
Expand Down
Loading