Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Already on GitHub? Sign in to your account
interfaces: add random interface #3045
Merged
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
747fe68
Adds hw-random interface
femdom 45233b8
Fixes base declaration test
femdom 9fea7e0
Removed gadget snap from the basedeclaration entry
femdom 8b964ee
Deny auto-connection
femdom be38c2b
Changing auto-connection to true
femdom ef09f63
Updated after the review
femdom 6e4f7ac
Added missing /sys directory prefix
femdom 2f5cd22
Merge branch 'master' into hw-random-interface-new-api
stolowski 0326d3c
Updated for new API.
stolowski 0ac754d
snap,interfaces: split random into hardwar-random-{observe,control}
zyga 8f1f3e3
Merge branch 'master' of github.com:snapcore/snapd into hw-random-int…
zyga d0caae2
interfaces/builtin: add extra checks for hardware-random-*
zyga b126df3
interfaces/builtin: tweak description for hardware-random-observe
zyga 767cda6
interfaces/builtin: wrap description to 80 columns
zyga 999426d
interfaces/builtin: reorder apparmor rules for association
zyga c9fe5c4
interfaces/builtin: add newlines for visual spacing
zyga ffb36da
interfaces/builtin: add comments for consistency
zyga
Jump to file or symbol
Failed to load files and symbols.
| @@ -0,0 +1,93 @@ | ||
| +// -*- Mode: Go; indent-tabs-mode: t -*- | ||
| + | ||
| +/* | ||
| + * Copyright (C) 2017 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 ( | ||
| + "fmt" | ||
| + | ||
| + "github.com/snapcore/snapd/interfaces" | ||
| + "github.com/snapcore/snapd/interfaces/apparmor" | ||
| + "github.com/snapcore/snapd/interfaces/udev" | ||
| + "github.com/snapcore/snapd/snap" | ||
| +) | ||
| + | ||
| +const hardwareRandomControlConnectedPlugAppArmor = ` | ||
| +# Description: allow direct access to the hardware random number generator | ||
| +# device. Usually, the default access to /dev/random is sufficient, but this | ||
| +# allows applications such as rng-tools to use /dev/hwrng directly or change | ||
| +# the hwrng via sysfs. For details, see | ||
| +# https://www.kernel.org/doc/Documentation/hw_random.txt | ||
| + | ||
| +/dev/hwrng rw, | ||
| +/run/udev/data/c10:183 r, | ||
| +/sys/devices/virtual/misc/ r, | ||
| +/sys/devices/virtual/misc/hw_random/rng_{available,current} r, | ||
| + | ||
| +# Allow changing the hwrng | ||
| +/sys/devices/virtual/misc/hw_random/rng_current w, | ||
| +` | ||
| + | ||
| +// The type for physical-memory-control interface | ||
| +type HardwareRandomControlInterface struct{} | ||
| + | ||
| +// Getter for the name of the physical-memory-control interface | ||
| +func (iface *HardwareRandomControlInterface) Name() string { | ||
| + return "hardware-random-control" | ||
| +} | ||
| + | ||
| +// Check validity of the defined slot | ||
| +func (iface *HardwareRandomControlInterface) SanitizeSlot(slot *interfaces.Slot) error { | ||
| + // Does it have right type? | ||
| + if iface.Name() != slot.Interface { | ||
| + panic(fmt.Sprintf("slot is not of interface %q", iface.Name())) | ||
| + } | ||
| + if slot.Snap.Type != snap.TypeOS { | ||
| + return fmt.Errorf("%s slots are reserved for the operating system snap", iface.Name()) | ||
| + } | ||
| + return nil | ||
| +} | ||
| + | ||
| +// Checks and possibly modifies a plug | ||
| +func (iface *HardwareRandomControlInterface) SanitizePlug(plug *interfaces.Plug) error { | ||
| + if iface.Name() != plug.Interface { | ||
| + panic(fmt.Sprintf("plug is not of interface %q", iface.Name())) | ||
| + } | ||
| + // Currently nothing is checked on the plug side | ||
| + return nil | ||
| +} | ||
| + | ||
| +func (iface *HardwareRandomControlInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.Plug, slot *interfaces.Slot) error { | ||
| + spec.AddSnippet(hardwareRandomControlConnectedPlugAppArmor) | ||
| + return nil | ||
| +} | ||
| + | ||
| +func (iface *HardwareRandomControlInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.Plug, slot *interfaces.Slot) error { | ||
| + const udevRule = `KERNEL=="hwrng", TAG+="%s"` | ||
| + for appName := range plug.Apps { | ||
| + tag := udevSnapSecurityName(plug.Snap.Name(), appName) | ||
| + spec.AddSnippet(fmt.Sprintf(udevRule, tag)) | ||
| + } | ||
| + return nil | ||
| +} | ||
| + | ||
| +func (iface *HardwareRandomControlInterface) AutoConnect(*interfaces.Plug, *interfaces.Slot) bool { | ||
| + // Allow what is allowed in the declarations | ||
| + return true | ||
| +} |
| @@ -0,0 +1,104 @@ | ||
| +// -*- 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/apparmor" | ||
| + "github.com/snapcore/snapd/interfaces/builtin" | ||
| + "github.com/snapcore/snapd/interfaces/udev" | ||
| + "github.com/snapcore/snapd/snap" | ||
| + "github.com/snapcore/snapd/snap/snaptest" | ||
| + "github.com/snapcore/snapd/testutil" | ||
| +) | ||
| + | ||
| +type HardwareRandomControlInterfaceSuite struct { | ||
| + iface interfaces.Interface | ||
| + slot *interfaces.Slot | ||
| + plug *interfaces.Plug | ||
| +} | ||
| + | ||
| +var _ = Suite(&HardwareRandomControlInterfaceSuite{ | ||
| + iface: &builtin.HardwareRandomControlInterface{}, | ||
| +}) | ||
| + | ||
| +func (s *HardwareRandomControlInterfaceSuite) SetUpTest(c *C) { | ||
| + // Mock for OS Snap | ||
| + osSnapInfo := snaptest.MockInfo(c, ` | ||
| +name: core | ||
| +type: os | ||
| +slots: | ||
| + hardware-random-control: | ||
| +`, nil) | ||
| + s.slot = &interfaces.Slot{SlotInfo: osSnapInfo.Slots["hardware-random-control"]} | ||
| + | ||
| + // Snap Consumers | ||
| + consumingSnapInfo := snaptest.MockInfo(c, ` | ||
| +name: snap | ||
| +apps: | ||
| + app: | ||
| + command: foo | ||
| + plugs: [hardware-random-control] | ||
| +`, nil) | ||
| + s.plug = &interfaces.Plug{PlugInfo: consumingSnapInfo.Plugs["hardware-random-control"]} | ||
| +} | ||
| + | ||
| +func (s *HardwareRandomControlInterfaceSuite) TestName(c *C) { | ||
| + c.Assert(s.iface.Name(), Equals, "hardware-random-control") | ||
| +} | ||
| + | ||
| +func (s *HardwareRandomControlInterfaceSuite) 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: "hardware-random-control", | ||
| + Interface: "hardware-random-control", | ||
| + }}) | ||
| + c.Assert(err, ErrorMatches, "hardware-random-control slots are reserved for the operating system snap") | ||
| +} | ||
| + | ||
| +func (s *HardwareRandomControlInterfaceSuite) TestSanitizePlug(c *C) { | ||
| + err := s.iface.SanitizePlug(s.plug) | ||
| + c.Assert(err, IsNil) | ||
| +} | ||
| + | ||
| +func (s *HardwareRandomControlInterfaceSuite) TestSanitizeIncorrectInterface(c *C) { | ||
| + c.Assert(func() { s.iface.SanitizeSlot(&interfaces.Slot{SlotInfo: &snap.SlotInfo{Interface: "other"}}) }, | ||
| + PanicMatches, `slot is not of interface "hardware-random-control"`) | ||
| + c.Assert(func() { s.iface.SanitizePlug(&interfaces.Plug{PlugInfo: &snap.PlugInfo{Interface: "other"}}) }, | ||
| + PanicMatches, `plug is not of interface "hardware-random-control"`) | ||
| +} | ||
| + | ||
| +func (s *HardwareRandomControlInterfaceSuite) TestAppArmorSpec(c *C) { | ||
| + spec := &apparmor.Specification{} | ||
| + c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil) | ||
| + c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.snap.app"}) | ||
| + c.Assert(spec.SnippetForTag("snap.snap.app"), testutil.Contains, "hw_random/rng_current w,") | ||
| +} | ||
| + | ||
| +func (s *HardwareRandomControlInterfaceSuite) TestUDevSpec(c *C) { | ||
| + spec := &udev.Specification{} | ||
| + c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil) | ||
| + expected := []string{`KERNEL=="hwrng", TAG+="snap_snap_app"`} | ||
| + c.Assert(spec.Snippets(), DeepEquals, expected) | ||
| +} |
| @@ -0,0 +1,87 @@ | ||
| +// -*- Mode: Go; indent-tabs-mode: t -*- | ||
| + | ||
| +/* | ||
| + * Copyright (C) 2017 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 ( | ||
| + "fmt" | ||
| + | ||
| + "github.com/snapcore/snapd/interfaces" | ||
| + "github.com/snapcore/snapd/interfaces/apparmor" | ||
| + "github.com/snapcore/snapd/interfaces/udev" | ||
| + "github.com/snapcore/snapd/snap" | ||
| +) | ||
| + | ||
| +const hardwareRandomObserveConnectedPlugAppArmor = ` | ||
| +# Description: allow direct read-only access to the hardware random number | ||
| +# generator device. In addition allow observing the available and | ||
| +# currently-selected hardware random number generator devices. | ||
| + | ||
| +/dev/hwrng r, | ||
| +/run/udev/data/c10:183 r, | ||
| +/sys/devices/virtual/misc/ r, | ||
| +/sys/devices/virtual/misc/hw_random/rng_{available,current} r, | ||
| +` | ||
| + | ||
| +// The type for physical-memory-control interface | ||
| +type HardwareRandomObserveInterface struct{} | ||
| + | ||
| +// Getter for the name of the physical-memory-control interface | ||
| +func (iface *HardwareRandomObserveInterface) Name() string { | ||
| + return "hardware-random-observe" | ||
| +} | ||
| + | ||
| +// Check validity of the defined slot | ||
| +func (iface *HardwareRandomObserveInterface) SanitizeSlot(slot *interfaces.Slot) error { | ||
| + if iface.Name() != slot.Interface { | ||
| + panic(fmt.Sprintf("slot is not of interface %q", iface.Name())) | ||
| + } | ||
| + if slot.Snap.Type != snap.TypeOS { | ||
| + return fmt.Errorf("%s slots are reserved for the operating system snap", iface.Name()) | ||
| + } | ||
| + return nil | ||
| +} | ||
| + | ||
| +// Checks and possibly modifies a plug | ||
| +func (iface *HardwareRandomObserveInterface) SanitizePlug(plug *interfaces.Plug) error { | ||
| + if iface.Name() != plug.Interface { | ||
| + panic(fmt.Sprintf("plug is not of interface %q", iface.Name())) | ||
| + } | ||
| + // Currently nothing is checked on the plug side | ||
| + return nil | ||
| +} | ||
| + | ||
| +func (iface *HardwareRandomObserveInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.Plug, slot *interfaces.Slot) error { | ||
| + spec.AddSnippet(hardwareRandomObserveConnectedPlugAppArmor) | ||
| + return nil | ||
| +} | ||
| + | ||
| +func (iface *HardwareRandomObserveInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.Plug, slot *interfaces.Slot) error { | ||
| + const udevRule = `KERNEL=="hwrng", TAG+="%s"` | ||
| + for appName := range plug.Apps { | ||
| + tag := udevSnapSecurityName(plug.Snap.Name(), appName) | ||
| + spec.AddSnippet(fmt.Sprintf(udevRule, tag)) | ||
| + } | ||
| + return nil | ||
| +} | ||
| + | ||
| +func (iface *HardwareRandomObserveInterface) AutoConnect(*interfaces.Plug, *interfaces.Slot) bool { | ||
| + // Allow what is allowed in the declarations | ||
| + return true | ||
| +} |
Oops, something went wrong.