summaryrefslogtreecommitdiff
diff options
authorPaweł Stołowski <stolowski@gmail.com>2020-08-05 17:14:06 +0200
committerPaweł Stołowski <stolowski@gmail.com>2020-08-06 11:26:41 +0200
commite1df8047fb72fed3c5d9aad8b3af7144271f1061 (patch)
treec2c5bae8390f67f849d6f03fc23fec4b8fca8219
parentd4c159fa49206ea2f485dff27721c8ace6ca9ee1 (diff)
Use emulation mode and skip daemon-reload / starting / stopping of services in systemd security backend if preseeding.preseed/fix-systemd-backend
-rw-r--r--interfaces/systemd/backend.go47
-rw-r--r--interfaces/systemd/backend_test.go50
2 files changed, 82 insertions, 15 deletions
diff --git a/interfaces/systemd/backend.go b/interfaces/systemd/backend.go
index 7163f6be1b..09affdd0be 100644
--- a/interfaces/systemd/backend.go
+++ b/interfaces/systemd/backend.go
@@ -37,10 +37,15 @@ import (
)
// Backend is responsible for maintaining apparmor profiles for ubuntu-core-launcher.
-type Backend struct{}
+type Backend struct {
+ preseed bool
+}
// Initialize does nothing.
-func (b *Backend) Initialize(*interfaces.SecurityBackendOptions) error {
+func (b *Backend) Initialize(opts *interfaces.SecurityBackendOptions) error {
+ if opts != nil && opts.Preseed {
+ b.preseed = true
+ }
return nil
}
@@ -69,16 +74,22 @@ func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementO
}
glob := interfaces.InterfaceServiceName(snapName, "*")
- systemd := sysd.New(dirs.GlobalRootDir, sysd.SystemMode, &dummyReporter{})
+ var systemd sysd.Systemd
+ if b.preseed {
+ systemd = sysd.NewEmulationMode(dirs.GlobalRootDir)
+ } else {
+ systemd = sysd.New(dirs.GlobalRootDir, sysd.SystemMode, &dummyReporter{})
+ }
+
// We need to be carefully here and stop all removed service units before
// we remove their files as otherwise systemd is not able to disable/stop
// them anymore.
- if err := disableRemovedServices(systemd, dir, glob, content); err != nil {
+ if err := b.disableRemovedServices(systemd, dir, glob, content); err != nil {
logger.Noticef("cannot stop removed services: %s", err)
}
changed, removed, errEnsure := osutil.EnsureDirState(dir, glob, content)
// Reload systemd whenever something is added or removed
- if len(changed) > 0 || len(removed) > 0 {
+ if (len(changed) > 0 || len(removed) > 0) && !b.preseed {
err := systemd.DaemonReload()
if err != nil {
logger.Noticef("cannot reload systemd state: %s", err)
@@ -89,10 +100,12 @@ func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementO
if err := systemd.Enable(service); err != nil {
logger.Noticef("cannot enable service %q: %s", service, err)
}
- // If we have a new service here which isn't started yet the restart
- // operation will start it.
- if err := systemd.Restart(service, 10*time.Second); err != nil {
- logger.Noticef("cannot restart service %q: %s", service, err)
+ if !b.preseed {
+ // If we have a new service here which isn't started yet the restart
+ // operation will start it.
+ if err := systemd.Restart(service, 10*time.Second); err != nil {
+ logger.Noticef("cannot restart service %q: %s", service, err)
+ }
}
}
return errEnsure
@@ -108,12 +121,14 @@ func (b *Backend) Remove(snapName string) error {
if err := systemd.Disable(service); err != nil {
logger.Noticef("cannot disable service %q: %s", service, err)
}
- if err := systemd.Stop(service, 5*time.Second); err != nil {
- logger.Noticef("cannot stop service %q: %s", service, err)
+ if !b.preseed {
+ if err := systemd.Stop(service, 5*time.Second); err != nil {
+ logger.Noticef("cannot stop service %q: %s", service, err)
+ }
}
}
// Reload systemd whenever something is removed
- if len(removed) > 0 {
+ if len(removed) > 0 && !b.preseed {
err := systemd.DaemonReload()
if err != nil {
logger.Noticef("cannot reload systemd state: %s", err)
@@ -148,7 +163,7 @@ func deriveContent(spec *Specification, snapInfo *snap.Info) map[string]osutil.F
return content
}
-func disableRemovedServices(systemd sysd.Systemd, dir, glob string, content map[string]osutil.FileState) error {
+func (b *Backend) disableRemovedServices(systemd sysd.Systemd, dir, glob string, content map[string]osutil.FileState) error {
paths, err := filepath.Glob(filepath.Join(dir, glob))
if err != nil {
return err
@@ -159,8 +174,10 @@ func disableRemovedServices(systemd sysd.Systemd, dir, glob string, content map[
if err := systemd.Disable(service); err != nil {
logger.Noticef("cannot disable service %q: %s", service, err)
}
- if err := systemd.Stop(service, 5*time.Second); err != nil {
- logger.Noticef("cannot stop service %q: %s", service, err)
+ if !b.preseed {
+ if err := systemd.Stop(service, 5*time.Second); err != nil {
+ logger.Noticef("cannot stop service %q: %s", service, err)
+ }
}
}
}
diff --git a/interfaces/systemd/backend_test.go b/interfaces/systemd/backend_test.go
index 2e873aba17..75f42bbd04 100644
--- a/interfaces/systemd/backend_test.go
+++ b/interfaces/systemd/backend_test.go
@@ -157,3 +157,53 @@ func (s *backendSuite) TestSettingUpSecurityWithFewerServices(c *C) {
func (s *backendSuite) TestSandboxFeatures(c *C) {
c.Assert(s.Backend.SandboxFeatures(), IsNil)
}
+
+func (s *backendSuite) TestInstallingSnapWhenPreseeding(c *C) {
+ s.Backend = &systemd.Backend{}
+ opts := &interfaces.SecurityBackendOptions{Preseed: true}
+ s.Backend.Initialize(opts)
+
+ var sysdLog [][]string
+ r := sysd.MockSystemctl(func(cmd ...string) ([]byte, error) {
+ sysdLog = append(sysdLog, cmd)
+ return []byte{}, nil
+ })
+ defer r()
+
+ s.Iface.SystemdPermanentSlotCallback = func(spec *systemd.Specification, slot *snap.SlotInfo) error {
+ return spec.AddService("snap.samba.interface.foo.service", &systemd.Service{ExecStart: "/bin/true"})
+ }
+ s.InstallSnap(c, interfaces.ConfinementOptions{}, "", ifacetest.SambaYamlV1, 1)
+ service := filepath.Join(dirs.SnapServicesDir, "snap.samba.interface.foo.service")
+ // the service file was created
+ _, err := os.Stat(service)
+ c.Check(err, IsNil)
+ // the service was enabled but not started
+ c.Check(sysdLog, DeepEquals, [][]string{
+ {"--root", dirs.GlobalRootDir, "enable", "snap.samba.interface.foo.service"},
+ })
+}
+
+// not a viable scenario, but tested for completness
+func (s *backendSuite) TestRemovingSnapWhenPreseeding(c *C) {
+ s.Backend = &systemd.Backend{}
+ opts := &interfaces.SecurityBackendOptions{Preseed: true}
+ s.Backend.Initialize(opts)
+
+ s.Iface.SystemdPermanentSlotCallback = func(spec *systemd.Specification, slot *snap.SlotInfo) error {
+ return spec.AddService("snap.samba.interface.foo.service", &systemd.Service{ExecStart: "/bin/true"})
+ }
+ for _, opts := range testedConfinementOpts {
+ snapInfo := s.InstallSnap(c, opts, "", ifacetest.SambaYamlV1, 1)
+ s.systemctlArgs = nil
+ s.RemoveSnap(c, snapInfo)
+ service := filepath.Join(dirs.SnapServicesDir, "snap.samba.interface.foo.service")
+ // the service file was removed
+ _, err := os.Stat(service)
+ c.Check(os.IsNotExist(err), Equals, true)
+ // the service was disabled (but no other systemctl calls)
+ c.Check(s.systemctlArgs, DeepEquals, [][]string{
+ {"systemctl", "--root", dirs.GlobalRootDir, "disable", "snap.samba.interface.foo.service"},
+ })
+ }
+}