Permalink
Browse files

Merge pull request #1602 from arges/kernel-module

interfaces: add kernel-module interface for module insertion.
  • Loading branch information...
2 parents 6cc7949 + 3f91f8d commit a22b514513c020673b290e3dd723d0bbe9a496ad @mvo5 mvo5 committed Aug 15, 2016
View
@@ -255,6 +255,12 @@ Can query hardware information from the system.
* Auto-Connect: no
+### kernel-module-control
+
+Can insert kernel modules. This interface gives privileged access to the device.
+
+* Auto-Connect: no
+
### locale-control
Can manage locales directly separate from ``config core``.
@@ -201,8 +201,6 @@ var defaultTemplate = []byte(`
@{PROC}/@{pid}/ r,
@{PROC}/@{pid}/fd/ r,
owner @{PROC}/@{pid}/auxv r,
- @{PROC}/@{pid}/version_signature r,
- @{PROC}/@{pid}/version r,
@{PROC}/sys/vm/zone_reclaim_mode r,
/etc/lsb-release r,
/sys/devices/**/read_ahead_kb r,
@@ -220,6 +218,8 @@ var defaultTemplate = []byte(`
/etc/machine-id r,
/etc/mime.types r,
@{PROC}/ r,
+ @{PROC}/version r,
+ @{PROC}/version_signature r,
/etc/{,writable/}hostname r,
/etc/{,writable/}localtime r,
/etc/{,writable/}timezone r,
@@ -63,6 +63,7 @@ var allInterfaces = []interfaces.Interface{
NewOpticalDriveInterface(),
NewCameraInterface(),
NewBluetoothControlInterface(),
+ NewKernelModuleControlInterface(),
}
// Interfaces returns all of the built-in interfaces.
@@ -65,4 +65,5 @@ func (s *AllSuite) TestInterfaces(c *C) {
c.Check(all, DeepContains, builtin.NewCupsControlInterface())
c.Check(all, DeepContains, builtin.NewOpticalDriveInterface())
c.Check(all, DeepContains, builtin.NewCameraInterface())
+ c.Check(all, DeepContains, builtin.NewKernelModuleControlInterface())
}
@@ -29,12 +29,19 @@ const hardwareObserveConnectedPlugAppArmor = `
# from the system. this is reserved because it allows reading potentially sensitive information.
# Usage: reserved
+# used by lscpu
+capability sys_rawio,
+
# files in /sys pertaining to hardware
-/sys/{block,bus,class,devices}/{,**} r,
+/sys/{block,bus,class,devices,firmware}/{,**} r,
# DMI tables
/sys/firmware/dmi/tables/DMI r,
/sys/firmware/dmi/tables/smbios_entry_point r,
+
+# util-linux
+/{,usr/}bin/lscpu ixr,
+@{PROC}/bus/pci/devices r,
`
// NewHardwareObserveInterface returns a new "hardware-observe" interface.
@@ -0,0 +1,54 @@
+// -*- Mode: Go; indent-tabs-mode: t -*-
+
+/*
+ * Copyright (C) 2016 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package builtin
+
+import (
+ "github.com/snapcore/snapd/interfaces"
+)
+
+const kernelModuleControlConnectedPlugAppArmor = `
+# Description: Allow insertion, removal and querying of modules.
+
+ capability sys_module,
+ @{PROC}/modules r,
+
+ # NOTE: needed by lscpu. In the future this may be moved to system-trace or
+ # system-observe.
+ /dev/mem r,
+`
+
+const kernelModuleControlConnectedPlugSecComp = `
+# Description: Allow insertion, removal and querying of modules.
+
+init_module
+finit_module
+delete_module
+`
+
+// NewKernelModuleControlInterface returns a new "kernel-module" interface.
+func NewKernelModuleControlInterface() interfaces.Interface {
+ return &commonInterface{
+ name: "kernel-module-control",
+ connectedPlugAppArmor: kernelModuleControlConnectedPlugAppArmor,
+ connectedPlugSecComp: kernelModuleControlConnectedPlugSecComp,
+ reservedForOS: true,
+ autoConnect: false,
+ }
+}
@@ -0,0 +1,128 @@
+// -*- Mode: Go; indent-tabs-mode: t -*-
+
+/*
+ * Copyright (C) 2016 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package builtin_test
+
+import (
+ . "gopkg.in/check.v1"
+
+ "github.com/snapcore/snapd/interfaces"
+ "github.com/snapcore/snapd/interfaces/builtin"
+ "github.com/snapcore/snapd/snap"
+)
+
+type KernelModuleControlInterfaceSuite struct {
+ iface interfaces.Interface
+ slot *interfaces.Slot
+ plug *interfaces.Plug
+}
+
+var _ = Suite(&KernelModuleControlInterfaceSuite{
+ iface: builtin.NewKernelModuleControlInterface(),
+ slot: &interfaces.Slot{
+ SlotInfo: &snap.SlotInfo{
+ Snap: &snap.Info{SuggestedName: "ubuntu-core", Type: snap.TypeOS},
+ Name: "kernel-module-control",
+ Interface: "kernel-module-control",
+ },
+ },
+ plug: &interfaces.Plug{
+ PlugInfo: &snap.PlugInfo{
+ Snap: &snap.Info{SuggestedName: "other"},
+ Name: "kernel-module-control",
+ Interface: "kernel-module-control",
+ },
+ },
+})
+
+func (s *KernelModuleControlInterfaceSuite) TestName(c *C) {
+ c.Assert(s.iface.Name(), Equals, "kernel-module-control")
+}
+
+func (s *KernelModuleControlInterfaceSuite) TestSanitizeSlot(c *C) {
+ err := s.iface.SanitizeSlot(s.slot)
+ c.Assert(err, IsNil)
+ err = s.iface.SanitizeSlot(&interfaces.Slot{SlotInfo: &snap.SlotInfo{
+ Snap: &snap.Info{SuggestedName: "some-snap"},
+ Name: "kernel-module-control",
+ Interface: "kernel-module-control",
+ }})
+ c.Assert(err, ErrorMatches, "kernel-module-control slots are reserved for the operating system snap")
+}
+
+func (s *KernelModuleControlInterfaceSuite) TestSanitizePlug(c *C) {
+ err := s.iface.SanitizePlug(s.plug)
+ c.Assert(err, IsNil)
+}
+
+func (s *KernelModuleControlInterfaceSuite) TestSanitizeIncorrectInterface(c *C) {
+ c.Assert(func() { s.iface.SanitizeSlot(&interfaces.Slot{SlotInfo: &snap.SlotInfo{Interface: "other"}}) },
+ PanicMatches, `slot is not of interface "kernel-module-control"`)
+ c.Assert(func() { s.iface.SanitizePlug(&interfaces.Plug{PlugInfo: &snap.PlugInfo{Interface: "other"}}) },
+ PanicMatches, `plug is not of interface "kernel-module-control"`)
+}
+
+func (s *KernelModuleControlInterfaceSuite) TestUnusedSecuritySystems(c *C) {
+ systems := [...]interfaces.SecuritySystem{interfaces.SecurityAppArmor,
+ interfaces.SecuritySecComp, interfaces.SecurityDBus,
+ interfaces.SecurityUDev}
+ for _, system := range systems {
+ snippet, err := s.iface.PermanentPlugSnippet(s.plug, system)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, IsNil)
+ snippet, err = s.iface.PermanentSlotSnippet(s.slot, system)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, IsNil)
+ snippet, err = s.iface.ConnectedSlotSnippet(s.plug, s.slot, system)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, IsNil)
+ }
+ snippet, err := s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecurityDBus)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, IsNil)
+ snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecurityUDev)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, IsNil)
+}
+
+func (s *KernelModuleControlInterfaceSuite) TestUsedSecuritySystems(c *C) {
+ // connected plugs have a non-nil security snippet for apparmor
+ snippet, err := s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecurityAppArmor)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, Not(IsNil))
+ // connected plugs have a non-nil security snippet for seccomp
+ snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecuritySecComp)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, Not(IsNil))
+}
+
+func (s *KernelModuleControlInterfaceSuite) TestUnexpectedSecuritySystems(c *C) {
+ snippet, err := s.iface.PermanentPlugSnippet(s.plug, "foo")
+ c.Assert(err, Equals, interfaces.ErrUnknownSecurity)
+ c.Assert(snippet, IsNil)
+ snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, "foo")
+ c.Assert(err, Equals, interfaces.ErrUnknownSecurity)
+ c.Assert(snippet, IsNil)
+ snippet, err = s.iface.PermanentSlotSnippet(s.slot, "foo")
+ c.Assert(err, Equals, interfaces.ErrUnknownSecurity)
+ c.Assert(snippet, IsNil)
+ snippet, err = s.iface.ConnectedSlotSnippet(s.plug, s.slot, "foo")
+ c.Assert(err, Equals, interfaces.ErrUnknownSecurity)
+ c.Assert(snippet, IsNil)
+}
View
@@ -48,6 +48,7 @@ var implicitSlots = []string{
"timeserver-control",
"timezone-control",
"tpm",
+ "kernel-module-control",
}
var implicitClassicSlots = []string{
View
@@ -42,7 +42,7 @@ func (s *InfoSnapYamlTestSuite) TestAddImplicitSlotsOutsideClassic(c *C) {
c.Assert(info.Slots["network"].Interface, Equals, "network")
c.Assert(info.Slots["network"].Name, Equals, "network")
c.Assert(info.Slots["network"].Snap, Equals, info)
- c.Assert(info.Slots, HasLen, 20)
+ c.Assert(info.Slots, HasLen, 21)
}
func (s *InfoSnapYamlTestSuite) TestAddImplicitSlotsOnClassic(c *C) {
@@ -56,7 +56,7 @@ func (s *InfoSnapYamlTestSuite) TestAddImplicitSlotsOnClassic(c *C) {
c.Assert(info.Slots["unity7"].Interface, Equals, "unity7")
c.Assert(info.Slots["unity7"].Name, Equals, "unity7")
c.Assert(info.Slots["unity7"].Snap, Equals, info)
- c.Assert(info.Slots, HasLen, 30)
+ c.Assert(info.Slots, HasLen, 31)
}
func (s *InfoSnapYamlTestSuite) TestImplicitSlotsAreRealInterfaces(c *C) {

0 comments on commit a22b514

Please sign in to comment.