-
Notifications
You must be signed in to change notification settings - Fork 573
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2424 from tonyespy/add-dev-mem-interfaces
interfaces/builtin: add physical-memory-* and io-ports-control
- Loading branch information
Showing
10 changed files
with
728 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// -*- 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 ( | ||
"bytes" | ||
"fmt" | ||
|
||
"github.com/snapcore/snapd/interfaces" | ||
) | ||
|
||
const ioPortsControlConnectedPlugAppArmor = ` | ||
# Description: Allow write access to all I/O ports. | ||
# See 'man 4 mem' for details. | ||
capability sys_rawio, # required by iopl | ||
/dev/ports rw, | ||
` | ||
|
||
const ioPortsControlConnectedPlugSecComp = ` | ||
# Description: Allow changes to the I/O port permissions and | ||
# privilege level of the calling process. In addition to granting | ||
# unrestricted I/O port access, running at a higher I/O privilege | ||
# level also allows the process to disable interrupts. This will | ||
# probably crash the system, and is not recommended. | ||
ioperm | ||
iopl | ||
` | ||
|
||
// The type for io-ports-control interface | ||
type IioPortsControlInterface struct{} | ||
|
||
// Getter for the name of the io-ports-control interface | ||
func (iface *IioPortsControlInterface) Name() string { | ||
return "io-ports-control" | ||
} | ||
|
||
func (iface *IioPortsControlInterface) String() string { | ||
return iface.Name() | ||
} | ||
|
||
// Check validity of the defined slot | ||
func (iface *IioPortsControlInterface) 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)) | ||
} | ||
|
||
// Creation of the slot of this type | ||
// is allowed only by a gadget or os snap | ||
if !(slot.Snap.Type == "os") { | ||
return fmt.Errorf("%s slots only allowed on core snap", iface.Name()) | ||
} | ||
return nil | ||
} | ||
|
||
// Checks and possibly modifies a plug | ||
func (iface *IioPortsControlInterface) SanitizePlug(plug *interfaces.Plug) error { | ||
if iface.Name() != plug.Interface { | ||
panic(fmt.Sprintf("plug is not of interface %q", iface)) | ||
} | ||
// Currently nothing is checked on the plug side | ||
return nil | ||
} | ||
|
||
// Returns snippet granted on install | ||
func (iface *IioPortsControlInterface) PermanentSlotSnippet(slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) { | ||
return nil, nil | ||
} | ||
|
||
// Getter for the security snippet specific to the plug | ||
func (iface *IioPortsControlInterface) ConnectedPlugSnippet(plug *interfaces.Plug, slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) { | ||
switch securitySystem { | ||
case interfaces.SecurityAppArmor: | ||
return []byte(ioPortsControlConnectedPlugAppArmor), nil | ||
|
||
case interfaces.SecuritySecComp: | ||
return []byte(ioPortsControlConnectedPlugSecComp), nil | ||
|
||
case interfaces.SecurityUDev: | ||
var tagSnippet bytes.Buffer | ||
const udevRule = `KERNEL=="ports", TAG+="%s"` | ||
for appName := range plug.Apps { | ||
tag := udevSnapSecurityName(plug.Snap.Name(), appName) | ||
tagSnippet.WriteString(fmt.Sprintf(udevRule, tag)) | ||
tagSnippet.WriteString("\n") | ||
} | ||
return tagSnippet.Bytes(), nil | ||
} | ||
return nil, nil | ||
} | ||
|
||
// No extra permissions granted on connection | ||
func (iface *IioPortsControlInterface) ConnectedSlotSnippet(plug *interfaces.Plug, slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) { | ||
return nil, nil | ||
} | ||
|
||
// No permissions granted to plug permanently | ||
func (iface *IioPortsControlInterface) PermanentPlugSnippet(plug *interfaces.Plug, securitySystem interfaces.SecuritySystem) ([]byte, error) { | ||
return nil, nil | ||
} | ||
|
||
func (iface *IioPortsControlInterface) AutoConnect(*interfaces.Plug, *interfaces.Slot) bool { | ||
// Allow what is allowed in the declarations | ||
return true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
"github.com/snapcore/snapd/snap/snaptest" | ||
) | ||
|
||
type IioPortsControlInterfaceSuite struct { | ||
iface interfaces.Interface | ||
slot *interfaces.Slot | ||
plug *interfaces.Plug | ||
} | ||
|
||
var _ = Suite(&IioPortsControlInterfaceSuite{ | ||
iface: &builtin.IioPortsControlInterface{}, | ||
}) | ||
|
||
func (s *IioPortsControlInterfaceSuite) SetUpTest(c *C) { | ||
// Mock for OS Snap | ||
osSnapInfo := snaptest.MockInfo(c, ` | ||
name: ubuntu-core | ||
type: os | ||
slots: | ||
test-io-ports: | ||
interface: io-ports-control | ||
`, nil) | ||
s.slot = &interfaces.Slot{SlotInfo: osSnapInfo.Slots["test-io-ports"]} | ||
|
||
// Snap Consumers | ||
consumingSnapInfo := snaptest.MockInfo(c, ` | ||
name: client-snap | ||
plugs: | ||
plug-for-io-ports: | ||
interface: io-ports-control | ||
apps: | ||
app-accessing-io-ports: | ||
command: foo | ||
plugs: [plug-for-io-ports] | ||
`, nil) | ||
s.plug = &interfaces.Plug{PlugInfo: consumingSnapInfo.Plugs["plug-for-io-ports"]} | ||
} | ||
|
||
func (s *IioPortsControlInterfaceSuite) TestName(c *C) { | ||
c.Assert(s.iface.Name(), Equals, "io-ports-control") | ||
} | ||
|
||
func (s *IioPortsControlInterfaceSuite) 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: "io-ports-control", | ||
Interface: "io-ports-control", | ||
}}) | ||
c.Assert(err, ErrorMatches, "io-ports-control slots only allowed on core snap") | ||
} | ||
|
||
func (s *IioPortsControlInterfaceSuite) TestSanitizePlug(c *C) { | ||
err := s.iface.SanitizePlug(s.plug) | ||
c.Assert(err, IsNil) | ||
} | ||
|
||
func (s *IioPortsControlInterfaceSuite) TestSanitizeIncorrectInterface(c *C) { | ||
c.Assert(func() { s.iface.SanitizeSlot(&interfaces.Slot{SlotInfo: &snap.SlotInfo{Interface: "other"}}) }, | ||
PanicMatches, `slot is not of interface "io-ports-control"`) | ||
c.Assert(func() { s.iface.SanitizePlug(&interfaces.Plug{PlugInfo: &snap.PlugInfo{Interface: "other"}}) }, | ||
PanicMatches, `plug is not of interface "io-ports-control"`) | ||
} | ||
|
||
func (s *IioPortsControlInterfaceSuite) TestUsedSecuritySystems(c *C) { | ||
expectedSnippet1 := []byte(` | ||
# Description: Allow write access to all I/O ports. | ||
# See 'man 4 mem' for details. | ||
capability sys_rawio, # required by iopl | ||
/dev/ports rw, | ||
`) | ||
|
||
expectedSnippet2 := []byte(` | ||
# Description: Allow changes to the I/O port permissions and | ||
# privilege level of the calling process. In addition to granting | ||
# unrestricted I/O port access, running at a higher I/O privilege | ||
# level also allows the process to disable interrupts. This will | ||
# probably crash the system, and is not recommended. | ||
ioperm | ||
iopl | ||
`) | ||
|
||
expectedSnippet3 := []byte(`KERNEL=="ports", TAG+="snap_client-snap_app-accessing-io-ports" | ||
`) | ||
|
||
// 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, DeepEquals, expectedSnippet1, Commentf("\nexpected:\n%s\nfound:\n%s", expectedSnippet1, snippet)) | ||
|
||
snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecuritySecComp) | ||
c.Assert(err, IsNil) | ||
c.Assert(snippet, DeepEquals, expectedSnippet2, Commentf("\nexpected:\n%s\nfound:\n%s", expectedSnippet2, snippet)) | ||
|
||
snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecurityUDev) | ||
c.Assert(err, IsNil) | ||
c.Assert(snippet, DeepEquals, expectedSnippet3, Commentf("\nexpected:\n%s\nfound:\n%s", expectedSnippet3, snippet)) | ||
} |
Oops, something went wrong.