Skip to content

Commit

Permalink
Merge pull request #3222 from morphis/f/dynamic-mount-dir-in-tests
Browse files Browse the repository at this point in the history
many: fix test cases to work with different DistroLibExecDir
  • Loading branch information
mvo5 committed Jun 19, 2017
2 parents 9daa8b4 + 999789f commit 0719d6b
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 184 deletions.
2 changes: 1 addition & 1 deletion cmd/cmd.go
Expand Up @@ -76,7 +76,7 @@ func distroSupportsReExec() bool {
// Ensure we do not use older version of snapd, look for info file and ignore
// version of core that do not yet have it.
func coreSupportsReExec(corePath string) bool {
fullInfo := filepath.Join(corePath, "/usr/lib/snapd/info")
fullInfo := filepath.Join(corePath, filepath.Join(dirs.CoreLibExecDir, "info"))
if !osutil.FileExists(fullInfo) {
return false
}
Expand Down
18 changes: 9 additions & 9 deletions cmd/snap/cmd_run.go
Expand Up @@ -365,6 +365,15 @@ func migrateXauthority(info *snap.Info) (string, error) {

func runSnapConfine(info *snap.Info, securityTag, snapApp, command, hook string, args []string) error {
snapConfine := filepath.Join(dirs.DistroLibExecDir, "snap-confine")
// if we re-exec, we must run the snap-confine from the core snap
// as well, if they get out of sync, havoc will happen
if isReexeced() {
// run snap-confine from the core snap. that will work because
// snap-confine on the core snap is mostly statically linked
// (except libudev and libc)
snapConfine = filepath.Join(dirs.SnapMountDir, "core/current", dirs.CoreLibExecDir, "snap-confine")
}

if !osutil.FileExists(snapConfine) {
if hook != "" {
logger.Noticef("WARNING: skipping running hook %q of snap %q: missing snap-confine", hook, info.Name())
Expand Down Expand Up @@ -401,15 +410,6 @@ func runSnapConfine(info *snap.Info, securityTag, snapApp, command, hook string,
cmd = append(cmd, snapApp)
cmd = append(cmd, args...)

// if we re-exec, we must run the snap-confine from the core snap
// as well, if they get out of sync, havoc will happen
if isReexeced() {
// run snap-confine from the core snap. that will work because
// snap-confine on the core snap is mostly statically linked
// (except libudev and libc)
cmd[0] = filepath.Join(dirs.SnapMountDir, "core/current", cmd[0])
}

extraEnv := make(map[string]string)
if len(xauthPath) > 0 {
extraEnv["XAUTHORITY"] = xauthPath
Expand Down
46 changes: 23 additions & 23 deletions cmd/snap/cmd_run_test.go
Expand Up @@ -98,7 +98,7 @@ func (s *SnapSuite) TestSnapRunAppIntegration(c *check.C) {
// mock installed snap
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(dirs.DistroLibExecDir)()

si := snaptest.MockSnap(c, string(mockYaml), string(mockContents), &snap.SideInfo{
Revision: snap.R("x2"),
Expand Down Expand Up @@ -126,7 +126,7 @@ func (s *SnapSuite) TestSnapRunAppIntegration(c *check.C) {
c.Check(execArgs, check.DeepEquals, []string{
filepath.Join(dirs.DistroLibExecDir, "snap-confine"),
"snap.snapname.app",
filepath.Join(dirs.DistroLibExecDir, "snap-exec"),
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"snapname.app", "--arg1", "arg2"})
c.Check(execEnv, testutil.Contains, "SNAP_REVISION=x2")
}
Expand All @@ -135,7 +135,7 @@ func (s *SnapSuite) TestSnapRunClassicAppIntegration(c *check.C) {
// mock installed snap
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(dirs.DistroLibExecDir)()

si := snaptest.MockSnap(c, string(mockYaml)+"confinement: classic\n", string(mockContents), &snap.SideInfo{
Revision: snap.R("x2"),
Expand Down Expand Up @@ -163,7 +163,7 @@ func (s *SnapSuite) TestSnapRunClassicAppIntegration(c *check.C) {
c.Check(execArgs, check.DeepEquals, []string{
filepath.Join(dirs.DistroLibExecDir, "snap-confine"), "--classic",
"snap.snapname.app",
filepath.Join(dirs.DistroLibExecDir, "snap-exec"),
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"snapname.app", "--arg1", "arg2"})
c.Check(execEnv, testutil.Contains, "SNAP_REVISION=x2")
}
Expand All @@ -172,7 +172,7 @@ func (s *SnapSuite) TestSnapRunAppWithCommandIntegration(c *check.C) {
// mock installed snap
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(dirs.DistroLibExecDir)()

si := snaptest.MockSnap(c, string(mockYaml), string(mockContents), &snap.SideInfo{
Revision: snap.R(42),
Expand All @@ -199,7 +199,7 @@ func (s *SnapSuite) TestSnapRunAppWithCommandIntegration(c *check.C) {
c.Check(execArgs, check.DeepEquals, []string{
filepath.Join(dirs.DistroLibExecDir, "snap-confine"),
"snap.snapname.app",
filepath.Join(dirs.DistroLibExecDir, "snap-exec"),
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"--command=my-command", "snapname.app", "arg1", "arg2"})
c.Check(execEnv, testutil.Contains, "SNAP_REVISION=42")
}
Expand All @@ -225,7 +225,7 @@ func (s *SnapSuite) TestSnapRunHookIntegration(c *check.C) {
// mock installed snap
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(dirs.DistroLibExecDir)()

si := snaptest.MockSnap(c, string(mockYaml), string(mockContents), &snap.SideInfo{
Revision: snap.R(42),
Expand All @@ -252,7 +252,7 @@ func (s *SnapSuite) TestSnapRunHookIntegration(c *check.C) {
c.Check(execArgs, check.DeepEquals, []string{
filepath.Join(dirs.DistroLibExecDir, "snap-confine"),
"snap.snapname.hook.configure",
filepath.Join(dirs.DistroLibExecDir, "snap-exec"),
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"--hook=configure", "snapname"})
c.Check(execEnv, testutil.Contains, "SNAP_REVISION=42")
}
Expand All @@ -261,7 +261,7 @@ func (s *SnapSuite) TestSnapRunHookUnsetRevisionIntegration(c *check.C) {
// mock installed snap
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(dirs.DistroLibExecDir)()

si := snaptest.MockSnap(c, string(mockYaml), string(mockContents), &snap.SideInfo{
Revision: snap.R(42),
Expand All @@ -288,7 +288,7 @@ func (s *SnapSuite) TestSnapRunHookUnsetRevisionIntegration(c *check.C) {
c.Check(execArgs, check.DeepEquals, []string{
filepath.Join(dirs.DistroLibExecDir, "snap-confine"),
"snap.snapname.hook.configure",
filepath.Join(dirs.DistroLibExecDir, "snap-exec"),
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"--hook=configure", "snapname"})
c.Check(execEnv, testutil.Contains, "SNAP_REVISION=42")
}
Expand All @@ -297,7 +297,7 @@ func (s *SnapSuite) TestSnapRunHookSpecificRevisionIntegration(c *check.C) {
// mock installed snap
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(dirs.DistroLibExecDir)()

// Create both revisions 41 and 42
snaptest.MockSnap(c, string(mockYaml), string(mockContents), &snap.SideInfo{
Expand Down Expand Up @@ -326,7 +326,7 @@ func (s *SnapSuite) TestSnapRunHookSpecificRevisionIntegration(c *check.C) {
c.Check(execArgs, check.DeepEquals, []string{
filepath.Join(dirs.DistroLibExecDir, "snap-confine"),
"snap.snapname.hook.configure",
filepath.Join(dirs.DistroLibExecDir, "snap-exec"),
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"--hook=configure", "snapname"})
c.Check(execEnv, testutil.Contains, "SNAP_REVISION=41")
}
Expand Down Expand Up @@ -398,14 +398,14 @@ func (s *SnapSuite) TestSnapRunErorsForMissingApp(c *check.C) {

func (s *SnapSuite) TestSnapRunErorrForUnavailableApp(c *check.C) {
_, err := snaprun.Parser().ParseArgs([]string{"run", "not-there"})
c.Assert(err, check.ErrorMatches, "cannot find current revision for snap not-there: readlink /snap/not-there/current: no such file or directory")
c.Assert(err, check.ErrorMatches, fmt.Sprintf("cannot find current revision for snap not-there: readlink %s/not-there/current: no such file or directory", dirs.SnapMountDir))
}

func (s *SnapSuite) TestSnapRunSaneEnvironmentHandling(c *check.C) {
// mock installed snap
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(dirs.DistroLibExecDir)()

si := snaptest.MockSnap(c, string(mockYaml), string(mockContents), &snap.SideInfo{
Revision: snap.R(42),
Expand Down Expand Up @@ -451,8 +451,8 @@ func (s *SnapSuite) TestSnapRunIsReexeced(c *check.C) {
readlink string
expected bool
}{
{filepath.Join(dirs.SnapMountDir, "/usr/lib/snapd/snapd"), true},
{"/usr/lib/snapd/snapd", false},
{filepath.Join(dirs.SnapMountDir, dirs.CoreLibExecDir, "snapd"), true},
{filepath.Join(dirs.DistroLibExecDir, "snapd"), false},
} {
osReadlinkResult = t.readlink
c.Check(snaprun.IsReexeced(), check.Equals, t.expected)
Expand All @@ -463,7 +463,7 @@ func (s *SnapSuite) TestSnapRunAppIntegrationFromCore(c *check.C) {
// mock installed snap
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(filepath.Join(dirs.SnapMountDir, "core", "current", dirs.CoreLibExecDir))()

si := snaptest.MockSnap(c, string(mockYaml), string(mockContents), &snap.SideInfo{
Revision: snap.R("x2"),
Expand All @@ -473,7 +473,7 @@ func (s *SnapSuite) TestSnapRunAppIntegrationFromCore(c *check.C) {

// pretend to be running from core
restorer := snaprun.MockOsReadlink(func(string) (string, error) {
return filepath.Join(dirs.SnapMountDir, "/core/111//usr/bin/snap"), nil
return filepath.Join(dirs.SnapMountDir, "core/111/usr/bin/snap"), nil
})
defer restorer()

Expand All @@ -493,11 +493,11 @@ func (s *SnapSuite) TestSnapRunAppIntegrationFromCore(c *check.C) {
rest, err := snaprun.Parser().ParseArgs([]string{"run", "snapname.app", "--arg1", "arg2"})
c.Assert(err, check.IsNil)
c.Assert(rest, check.DeepEquals, []string{"snapname.app", "--arg1", "arg2"})
c.Check(execArg0, check.Equals, filepath.Join(dirs.SnapMountDir, "/core/current", dirs.DistroLibExecDir, "snap-confine"))
c.Check(execArg0, check.Equals, filepath.Join(dirs.SnapMountDir, "/core/current", dirs.CoreLibExecDir, "snap-confine"))
c.Check(execArgs, check.DeepEquals, []string{
filepath.Join(dirs.SnapMountDir, "/core/current", dirs.DistroLibExecDir, "snap-confine"),
filepath.Join(dirs.SnapMountDir, "/core/current", dirs.CoreLibExecDir, "snap-confine"),
"snap.snapname.app",
filepath.Join(dirs.DistroLibExecDir, "snap-exec"),
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"snapname.app", "--arg1", "arg2"})
c.Check(execEnv, testutil.Contains, "SNAP_REVISION=x2")
}
Expand All @@ -507,7 +507,7 @@ func (s *SnapSuite) TestSnapRunXauthorityMigration(c *check.C) {
// below /tmp which the Xauthority migration expects.
dirs.SetRootDir(c.MkDir())
defer func() { dirs.SetRootDir("/") }()
defer mockSnapConfine()()
defer mockSnapConfine(dirs.DistroLibExecDir)()

u, err := user.Current()
c.Assert(err, check.IsNil)
Expand Down Expand Up @@ -553,7 +553,7 @@ func (s *SnapSuite) TestSnapRunXauthorityMigration(c *check.C) {
c.Check(execArgs, check.DeepEquals, []string{
filepath.Join(dirs.DistroLibExecDir, "snap-confine"),
"snap.snapname.app",
filepath.Join(dirs.DistroLibExecDir, "snap-exec"),
filepath.Join(dirs.CoreLibExecDir, "snap-exec"),
"snapname.app"})

expectedXauthPath := filepath.Join(dirs.XdgRuntimeDirBase, u.Uid, ".Xauthority")
Expand Down
6 changes: 3 additions & 3 deletions cmd/snap/main_test.go
Expand Up @@ -152,9 +152,9 @@ func mockVersion(v string) (restore func()) {
return func() { cmd.Version = old }
}

func mockSnapConfine() func() {
snapConfine := filepath.Join(dirs.DistroLibExecDir, "snap-confine")
if err := os.MkdirAll(dirs.DistroLibExecDir, 0755); err != nil {
func mockSnapConfine(libExecDir string) func() {
snapConfine := filepath.Join(libExecDir, "snap-confine")
if err := os.MkdirAll(libExecDir, 0755); err != nil {
panic(err)
}
if err := ioutil.WriteFile(snapConfine, nil, 0644); err != nil {
Expand Down
16 changes: 10 additions & 6 deletions dirs/dirs.go
Expand Up @@ -32,7 +32,10 @@ import (
var (
GlobalRootDir string

SnapMountDir string
SnapMountDir string

DistroLibExecDir string

SnapBlobDir string
SnapDataDir string
SnapDataHomeGlob string
Expand Down Expand Up @@ -73,9 +76,6 @@ var (

ClassicDir string

DistroLibExecDir string
CoreLibExecDir string

XdgRuntimeDirBase string
XdgRuntimeDirGlob string

Expand All @@ -84,6 +84,12 @@ var (

const (
defaultSnapMountDir = "/snap"

// These are directories which are static inside the core snap and
// can never be prefixed as they will be always absolute once we
// are in the snap confinement environment.
CoreLibExecDir = "/usr/lib/snapd"
CoreSnapMountDir = "/snap"
)

var (
Expand Down Expand Up @@ -183,8 +189,6 @@ func SetRootDir(rootdir string) {
DistroLibExecDir = filepath.Join(rootdir, "/usr/lib/snapd")
}

CoreLibExecDir = filepath.Join(rootdir, "/usr/lib/snapd")

XdgRuntimeDirBase = filepath.Join(rootdir, "/run/user")
XdgRuntimeDirGlob = filepath.Join(rootdir, XdgRuntimeDirBase, "*/")

Expand Down
3 changes: 3 additions & 0 deletions dirs/dirs_test.go
Expand Up @@ -50,6 +50,9 @@ func (s *DirsTestSuite) TestStripRootDir(c *C) {
}

func (s *DirsTestSuite) TestClassicConfinementSupport(c *C) {
// Ensure that we have a distribution as base which supports classic confinement
reset := release.MockReleaseInfo(&release.OS{ID: "ubuntu"})
defer reset()
dirs.SetRootDir("/")
c.Assert(dirs.SupportsClassicConfinement(), Equals, true)
dirs.SetRootDir("/alt")
Expand Down
9 changes: 7 additions & 2 deletions interfaces/builtin/content.go
Expand Up @@ -25,6 +25,7 @@ import (
"path/filepath"
"strings"

"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/interfaces"
"github.com/snapcore/snapd/interfaces/apparmor"
"github.com/snapcore/snapd/interfaces/mount"
Expand Down Expand Up @@ -130,7 +131,11 @@ func (iface *contentInterface) path(slot *interfaces.Slot, name string) []string
// (this is the behavior that was used before the variables were supporter).
func resolveSpecialVariable(path string, snapInfo *snap.Info) string {
if strings.HasPrefix(path, "$SNAP/") || path == "$SNAP" {
return strings.Replace(path, "$SNAP", snapInfo.MountDir(), 1)
// NOTE: We use dirs.CoreSnapMountDir here as the path used will be always
// inside the mount namespace snap-confine creates and there we will
// always have a /snap directory available regardless if the system
// we're running on supports this or not.
return strings.Replace(path, "$SNAP", filepath.Join(dirs.CoreSnapMountDir, snapInfo.Name(), snapInfo.Revision.String()), 1)
}
if strings.HasPrefix(path, "$SNAP_DATA/") || path == "$SNAP_DATA" {
return strings.Replace(path, "$SNAP_DATA", snapInfo.DataDir(), 1)
Expand All @@ -139,7 +144,7 @@ func resolveSpecialVariable(path string, snapInfo *snap.Info) string {
return strings.Replace(path, "$SNAP_COMMON", snapInfo.CommonDataDir(), 1)
}
// NOTE: assume $SNAP by default if nothing else is provided, for compatibility
return filepath.Join(snapInfo.MountDir(), path)
return filepath.Join(filepath.Join(dirs.CoreSnapMountDir, snapInfo.Name(), snapInfo.Revision.String()), path)
}

func mountEntry(plug *interfaces.Plug, slot *interfaces.Slot, relSrc string, extraOptions ...string) mount.Entry {
Expand Down
24 changes: 14 additions & 10 deletions interfaces/builtin/content_test.go
Expand Up @@ -20,8 +20,12 @@
package builtin_test

import (
"fmt"
"path/filepath"

. "gopkg.in/check.v1"

"github.com/snapcore/snapd/dirs"
"github.com/snapcore/snapd/interfaces"
"github.com/snapcore/snapd/interfaces/apparmor"
"github.com/snapcore/snapd/interfaces/builtin"
Expand Down Expand Up @@ -196,11 +200,11 @@ apps:

func (s *ContentSuite) TestResolveSpecialVariable(c *C) {
info := snaptest.MockInfo(c, "name: name", &snap.SideInfo{Revision: snap.R(42)})
c.Check(builtin.ResolveSpecialVariable("foo", info), Equals, "/snap/name/42/foo")
c.Check(builtin.ResolveSpecialVariable("$SNAP/foo", info), Equals, "/snap/name/42/foo")
c.Check(builtin.ResolveSpecialVariable("foo", info), Equals, filepath.Join(dirs.CoreSnapMountDir, "name/42/foo"))
c.Check(builtin.ResolveSpecialVariable("$SNAP/foo", info), Equals, filepath.Join(dirs.CoreSnapMountDir, "name/42/foo"))
c.Check(builtin.ResolveSpecialVariable("$SNAP_DATA/foo", info), Equals, "/var/snap/name/42/foo")
c.Check(builtin.ResolveSpecialVariable("$SNAP_COMMON/foo", info), Equals, "/var/snap/name/common/foo")
c.Check(builtin.ResolveSpecialVariable("$SNAP", info), Equals, "/snap/name/42")
c.Check(builtin.ResolveSpecialVariable("$SNAP", info), Equals, filepath.Join(dirs.CoreSnapMountDir, "name/42"))
c.Check(builtin.ResolveSpecialVariable("$SNAP_DATA", info), Equals, "/var/snap/name/42")
c.Check(builtin.ResolveSpecialVariable("$SNAP_COMMON", info), Equals, "/var/snap/name/common")
}
Expand All @@ -226,8 +230,8 @@ slots:
spec := &mount.Specification{}
c.Assert(spec.AddConnectedPlug(s.iface, plug, nil, slot, nil), IsNil)
expectedMnt := []mount.Entry{{
Name: "/snap/producer/5/export",
Dir: "/snap/consumer/7/import",
Name: filepath.Join(dirs.CoreSnapMountDir, "producer/5/export"),
Dir: filepath.Join(dirs.CoreSnapMountDir, "consumer/7/import"),
Options: []string{"bind", "ro"},
}}
c.Assert(spec.MountEntries(), DeepEquals, expectedMnt)
Expand Down Expand Up @@ -257,8 +261,8 @@ slots:
spec := &mount.Specification{}
c.Assert(spec.AddConnectedPlug(s.iface, plug, nil, slot, nil), IsNil)
expectedMnt := []mount.Entry{{
Name: "/snap/producer/5/export",
Dir: "/snap/consumer/7/import",
Name: filepath.Join(dirs.CoreSnapMountDir, "producer/5/export"),
Dir: filepath.Join(dirs.CoreSnapMountDir, "consumer/7/import"),
Options: []string{"bind", "ro"},
}}
c.Assert(spec.MountEntries(), DeepEquals, expectedMnt)
Expand All @@ -267,12 +271,12 @@ slots:
err := apparmorSpec.AddConnectedPlug(s.iface, plug, nil, slot, nil)
c.Assert(err, IsNil)
c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"})
expected := `
expected := fmt.Sprintf(`
# In addition to the bind mount, add any AppArmor rules so that
# snaps may directly access the slot implementation's files
# read-only.
/snap/producer/5/export/** mrkix,
`
%s/producer/5/export/** mrkix,
`, dirs.CoreSnapMountDir)
c.Assert(apparmorSpec.SnippetForTag("snap.consumer.app"), Equals, expected)
}

Expand Down

0 comments on commit 0719d6b

Please sign in to comment.