Skip to content

Commit

Permalink
interfaces: add cifs-mount interface (#5340)
Browse files Browse the repository at this point in the history
  • Loading branch information
datenhahn authored and niemeyer committed Aug 22, 2018
1 parent 9c41e57 commit 7cce3f5
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 0 deletions.
74 changes: 74 additions & 0 deletions interfaces/builtin/cifs_mount.go
@@ -0,0 +1,74 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2018 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

const cifsMountSummary = `allows mounting and unmounting CIFS filesystems`

const cifsMountBaseDeclarationSlots = `
cifs-mount:
allow-installation:
slot-snap-type:
- core
deny-auto-connection: true
`

const cifsMountConnectedPlugSecComp = `
# Description: Allow mount and umount syscall access.
mount
umount
umount2
`

const cifsMountConnectedPlugAppArmor = `
# Description: Allow mounting and unmounting CIFS filesystems.
# Required for mounts and unmounts
capability sys_admin,
# Allow mounts to our snap-specific writable directories
mount fstype=cifs //** -> /var/snap/@{SNAP_NAME}/@{SNAP_REVISION}/{,**},
mount fstype=cifs //** -> /var/snap/@{SNAP_NAME}/common/{,**},
# NOTE: due to LP: #1613403, fstype is not mediated and as such, these rules
# allow, for example, unmounting bind mounts from the content interface
umount /var/snap/@{SNAP_NAME}/@{SNAP_REVISION}/{,**},
umount /var/snap/@{SNAP_NAME}/common/{,**},
# Due to an unsolved issue with namespace awareness of libmount the unmount tries to access
# /run/mount/utab but fails. The resulting apparmor warning can be ignored. The log warning
# was not removed via an explicit deny to not interfere with other interfaces which might
# decide to allow access (deny rules have precedence).
# - https://github.com/snapcore/snapd/pull/5340#issuecomment-398071797
# - https://forum.snapcraft.io/t/namespace-awareness-of-run-mount-utab-and-libmount/5987
#deny /run/mount/utab w,
`

func init() {
registerIface(&commonInterface{
name: "cifs-mount",
summary: cifsMountSummary,
implicitOnCore: true,
implicitOnClassic: true,
baseDeclarationSlots: cifsMountBaseDeclarationSlots,
connectedPlugAppArmor: cifsMountConnectedPlugAppArmor,
connectedPlugSecComp: cifsMountConnectedPlugSecComp,
reservedForOS: true,
})
}
107 changes: 107 additions & 0 deletions interfaces/builtin/cifs_mount_test.go
@@ -0,0 +1,107 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2016-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_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/seccomp"
"github.com/snapcore/snapd/snap"
"github.com/snapcore/snapd/testutil"
)

type CifsMountInterfaceSuite struct {
iface interfaces.Interface
slotInfo *snap.SlotInfo
slot *interfaces.ConnectedSlot
plugInfo *snap.PlugInfo
plug *interfaces.ConnectedPlug
}

const cifsMountConsumerYaml = `name: consumer
version: 0
apps:
app:
plugs: [cifs-mount]
`

const cifsMountCoreYaml = `name: core
version: 0
type: os
slots:
cifs-mount:
`

var _ = Suite(&CifsMountInterfaceSuite{
iface: builtin.MustInterface("cifs-mount"),
})

func (s *CifsMountInterfaceSuite) SetUpTest(c *C) {
s.plug, s.plugInfo = MockConnectedPlug(c, cifsMountConsumerYaml, nil, "cifs-mount")
s.slot, s.slotInfo = MockConnectedSlot(c, cifsMountCoreYaml, nil, "cifs-mount")
}

func (s *CifsMountInterfaceSuite) TestName(c *C) {
c.Assert(s.iface.Name(), Equals, "cifs-mount")
}

func (s *CifsMountInterfaceSuite) TestSanitizeSlot(c *C) {
c.Assert(interfaces.BeforePrepareSlot(s.iface, s.slotInfo), IsNil)
slot := &snap.SlotInfo{
Snap: &snap.Info{SuggestedName: "some-snap"},
Name: "cifs-mount",
Interface: "cifs-mount",
}
c.Assert(interfaces.BeforePrepareSlot(s.iface, slot), ErrorMatches,
"cifs-mount slots are reserved for the core snap")
}

func (s *CifsMountInterfaceSuite) TestSanitizePlug(c *C) {
c.Assert(interfaces.BeforePreparePlug(s.iface, s.plugInfo), IsNil)
}

func (s *CifsMountInterfaceSuite) TestAppArmorSpec(c *C) {
spec := &apparmor.Specification{}
c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil)
c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"})
c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `#deny /run/mount/utab w,`)
}

func (s *CifsMountInterfaceSuite) TestSecCompSpec(c *C) {
spec := &seccomp.Specification{}
c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil)
c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"})
c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, "umount2\n")
}

func (s *CifsMountInterfaceSuite) TestStaticInfo(c *C) {
si := interfaces.StaticInfoOf(s.iface)
c.Assert(si.ImplicitOnCore, Equals, true)
c.Assert(si.ImplicitOnClassic, Equals, true)
c.Assert(si.Summary, Equals, `allows mounting and unmounting CIFS filesystems`)
c.Assert(si.BaseDeclarationSlots, testutil.Contains, "cifs-mount")
}

func (s *CifsMountInterfaceSuite) TestInterfaces(c *C) {
c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface)
}
3 changes: 3 additions & 0 deletions tests/lib/snaps/test-snapd-policy-app-consumer/meta/snap.yaml
Expand Up @@ -41,6 +41,9 @@ apps:
camera:
command: bin/run
plugs: [ camera ]
cifs-mount:
command: bin/run
plugs: [ cifs-mount ]
classic-support:
command: bin/run
plugs: [ classic-support ]
Expand Down

0 comments on commit 7cce3f5

Please sign in to comment.