github.com/rigado/snapd@v2.42.5-go-mod+incompatible/overlord/snapstate/check_snap_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package snapstate_test
    21  
    22  import (
    23  	"errors"
    24  	"fmt"
    25  	"io/ioutil"
    26  	"os"
    27  	"path/filepath"
    28  
    29  	. "gopkg.in/check.v1"
    30  
    31  	"github.com/snapcore/snapd/arch"
    32  	"github.com/snapcore/snapd/cmd"
    33  	"github.com/snapcore/snapd/dirs"
    34  	"github.com/snapcore/snapd/osutil"
    35  	"github.com/snapcore/snapd/overlord/state"
    36  	"github.com/snapcore/snapd/release"
    37  	seccomp_compiler "github.com/snapcore/snapd/sandbox/seccomp"
    38  	"github.com/snapcore/snapd/snap"
    39  	"github.com/snapcore/snapd/snap/snapdir"
    40  	"github.com/snapcore/snapd/snap/snaptest"
    41  	"github.com/snapcore/snapd/testutil"
    42  
    43  	"github.com/snapcore/snapd/overlord/snapstate"
    44  	"github.com/snapcore/snapd/overlord/snapstate/snapstatetest"
    45  )
    46  
    47  type checkSnapSuite struct {
    48  	testutil.BaseTest
    49  	st        *state.State
    50  	deviceCtx snapstate.DeviceContext
    51  }
    52  
    53  var _ = Suite(&checkSnapSuite{})
    54  
    55  func (s *checkSnapSuite) SetUpTest(c *C) {
    56  	s.BaseTest.SetUpTest(c)
    57  	dirs.SetRootDir(c.MkDir())
    58  	s.st = state.New(nil)
    59  	s.BaseTest.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {}))
    60  	s.deviceCtx = &snapstatetest.TrivialDeviceContext{DeviceModel: MakeModel(map[string]interface{}{
    61  		"kernel": "kernel",
    62  		"gadget": "gadget",
    63  	})}
    64  }
    65  
    66  func (s *checkSnapSuite) TearDownTest(c *C) {
    67  	s.BaseTest.TearDownTest(c)
    68  	dirs.SetRootDir("")
    69  }
    70  
    71  func (s *checkSnapSuite) TestCheckSnapErrorOnUnsupportedArchitecture(c *C) {
    72  	const yaml = `name: hello
    73  version: 1.10
    74  architectures:
    75      - yadayada
    76      - blahblah
    77  `
    78  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
    79  	c.Assert(err, IsNil)
    80  
    81  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
    82  		c.Check(path, Equals, "snap-path")
    83  		c.Check(si, IsNil)
    84  		return info, emptyContainer(c), nil
    85  	}
    86  	restore := snapstate.MockOpenSnapFile(openSnapFile)
    87  	defer restore()
    88  
    89  	err = snapstate.CheckSnap(s.st, "snap-path", "hello", nil, nil, snapstate.Flags{}, nil)
    90  
    91  	errorMsg := fmt.Sprintf(`snap "hello" supported architectures (yadayada, blahblah) are incompatible with this system (%s)`, arch.DpkgArchitecture())
    92  	c.Assert(err.Error(), Equals, errorMsg)
    93  }
    94  
    95  var assumesTests = []struct {
    96  	version string
    97  	assumes string
    98  	classic bool
    99  	error   string
   100  }{{
   101  	assumes: "[common-data-dir]",
   102  }, {
   103  	assumes: "[f1, f2]",
   104  	error:   `snap "foo" assumes unsupported features: f1, f2 \(try to refresh the core snap\)`,
   105  }, {
   106  	assumes: "[f1, f2]",
   107  	classic: true,
   108  	error:   `snap "foo" assumes unsupported features: f1, f2 \(try to update snapd and refresh the core snap\)`,
   109  }, {
   110  	assumes: "[snapd2.15]",
   111  	version: "unknown",
   112  }, {
   113  	assumes: "[snapdnono]",
   114  	version: "unknown",
   115  	error:   `.* unsupported features: snapdnono .*`,
   116  }, {
   117  	assumes: "[snapd2.15nono]",
   118  	version: "unknown",
   119  	error:   `.* unsupported features: snapd2.15nono .*`,
   120  }, {
   121  	assumes: "[snapd2.15]",
   122  	version: "2.15",
   123  }, {
   124  	assumes: "[snapd2.15]",
   125  	version: "2.15.1",
   126  }, {
   127  	assumes: "[snapd2.15]",
   128  	version: "2.15+git",
   129  }, {
   130  	assumes: "[snapd2.15]",
   131  	version: "2.16",
   132  }, {
   133  	assumes: "[snapd2.15.1]",
   134  	version: "2.16",
   135  }, {
   136  	assumes: "[snapd2.15.2]",
   137  	version: "2.16.1",
   138  }, {
   139  	assumes: "[snapd3]",
   140  	version: "3.1",
   141  }, {
   142  	assumes: "[snapd2.16]",
   143  	version: "2.15",
   144  	error:   `.* unsupported features: snapd2\.16 .*`,
   145  }, {
   146  	assumes: "[snapd2.15.1]",
   147  	version: "2.15",
   148  	error:   `.* unsupported features: snapd2\.15\.1 .*`,
   149  }, {
   150  	assumes: "[snapd2.15.1]",
   151  	version: "2.15.0",
   152  	error:   `.* unsupported features: snapd2\.15\.1 .*`,
   153  }, {
   154  	// Note that this is different from how strconv.VersionCompare
   155  	// (dpkg version numbering) would behave - it would error here
   156  	assumes: "[snapd2.15]",
   157  	version: "2.15~pre1",
   158  }, {
   159  	assumes: "[command-chain]",
   160  }}
   161  
   162  func (s *checkSnapSuite) TestCheckSnapAssumes(c *C) {
   163  	restore := cmd.MockVersion("2.15")
   164  	defer restore()
   165  
   166  	restore = release.MockOnClassic(false)
   167  	defer restore()
   168  
   169  	for _, test := range assumesTests {
   170  		cmd.Version = test.version
   171  		if cmd.Version == "" {
   172  			cmd.Version = "2.15"
   173  		}
   174  		release.OnClassic = test.classic
   175  
   176  		yaml := fmt.Sprintf("name: foo\nversion: 1.0\nassumes: %s\n", test.assumes)
   177  
   178  		info, err := snap.InfoFromSnapYaml([]byte(yaml))
   179  		c.Assert(err, IsNil)
   180  
   181  		var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   182  			return info, emptyContainer(c), nil
   183  		}
   184  		restore := snapstate.MockOpenSnapFile(openSnapFile)
   185  		defer restore()
   186  		err = snapstate.CheckSnap(s.st, "snap-path", "foo", nil, nil, snapstate.Flags{}, nil)
   187  		if test.error != "" {
   188  			c.Check(err, ErrorMatches, test.error)
   189  		} else {
   190  			c.Assert(err, IsNil)
   191  		}
   192  	}
   193  }
   194  
   195  func (s *checkSnapSuite) TestCheckSnapCheckCallbackOK(c *C) {
   196  	const yaml = `name: foo
   197  version: 1.0`
   198  
   199  	si := &snap.SideInfo{
   200  		SnapID: "snap-id",
   201  	}
   202  
   203  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   204  		info := snaptest.MockInfo(c, yaml, si)
   205  		return info, emptyContainer(c), nil
   206  	}
   207  	r1 := snapstate.MockOpenSnapFile(openSnapFile)
   208  	defer r1()
   209  
   210  	checkCbCalled := false
   211  	checkCb := func(st *state.State, s, cur *snap.Info, flags snapstate.Flags, deviceCtx snapstate.DeviceContext) error {
   212  		c.Assert(s.InstanceName(), Equals, "foo")
   213  		c.Assert(s.SnapID, Equals, "snap-id")
   214  		checkCbCalled = true
   215  		return nil
   216  	}
   217  	r2 := snapstate.MockCheckSnapCallbacks([]snapstate.CheckSnapCallback{checkCb})
   218  	defer r2()
   219  
   220  	err := snapstate.CheckSnap(s.st, "snap-path", "foo", si, nil, snapstate.Flags{}, nil)
   221  	c.Check(err, IsNil)
   222  
   223  	c.Check(checkCbCalled, Equals, true)
   224  }
   225  
   226  func (s *checkSnapSuite) TestCheckSnapCheckCallbackFail(c *C) {
   227  	const yaml = `name: foo
   228  version: 1.0`
   229  
   230  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   231  	c.Assert(err, IsNil)
   232  
   233  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   234  		return info, emptyContainer(c), nil
   235  	}
   236  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   237  	defer restore()
   238  
   239  	fail := errors.New("bad snap")
   240  	checkCb := func(st *state.State, s, cur *snap.Info, flags snapstate.Flags, deviceCtx snapstate.DeviceContext) error {
   241  		return fail
   242  	}
   243  	r2 := snapstate.MockCheckSnapCallbacks(nil)
   244  	defer r2()
   245  	snapstate.AddCheckSnapCallback(checkCb)
   246  
   247  	err = snapstate.CheckSnap(s.st, "snap-path", "foo", nil, nil, snapstate.Flags{}, nil)
   248  	c.Check(err, Equals, fail)
   249  }
   250  
   251  func (s *checkSnapSuite) TestCheckSnapGadgetUpdate(c *C) {
   252  	reset := release.MockOnClassic(false)
   253  	defer reset()
   254  
   255  	st := state.New(nil)
   256  	st.Lock()
   257  	defer st.Unlock()
   258  
   259  	si := &snap.SideInfo{RealName: "gadget", Revision: snap.R(2), SnapID: "gadget-id"}
   260  	snaptest.MockSnap(c, `
   261  name: gadget
   262  type: gadget
   263  version: 1
   264  `, si)
   265  	snapstate.Set(st, "gadget", &snapstate.SnapState{
   266  		SnapType: "gadget",
   267  		Active:   true,
   268  		Sequence: []*snap.SideInfo{si},
   269  		Current:  si.Revision,
   270  	})
   271  
   272  	const yaml = `name: gadget
   273  type: gadget
   274  version: 2
   275  `
   276  
   277  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   278  	info.SnapID = "gadget-id"
   279  	c.Assert(err, IsNil)
   280  
   281  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   282  		return info, emptyContainer(c), nil
   283  	}
   284  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   285  	defer restore()
   286  
   287  	st.Unlock()
   288  	err = snapstate.CheckSnap(st, "snap-path", "gadget", nil, nil, snapstate.Flags{}, s.deviceCtx)
   289  	st.Lock()
   290  	c.Check(err, IsNil)
   291  }
   292  
   293  func (s *checkSnapSuite) TestCheckSnapGadgetUpdateLocal(c *C) {
   294  	reset := release.MockOnClassic(false)
   295  	defer reset()
   296  
   297  	st := state.New(nil)
   298  	st.Lock()
   299  	defer st.Unlock()
   300  
   301  	si := &snap.SideInfo{RealName: "gadget", Revision: snap.R(2)}
   302  	snaptest.MockSnap(c, `
   303  name: gadget
   304  type: gadget
   305  version: 1
   306  `, si)
   307  	snapstate.Set(st, "gadget", &snapstate.SnapState{
   308  		SnapType: "gadget",
   309  		Active:   true,
   310  		Sequence: []*snap.SideInfo{si},
   311  		Current:  si.Revision,
   312  	})
   313  
   314  	const yaml = `name: gadget
   315  type: gadget
   316  version: 2
   317  `
   318  
   319  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   320  	// no SnapID => local!
   321  	c.Assert(err, IsNil)
   322  
   323  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   324  		return info, emptyContainer(c), nil
   325  	}
   326  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   327  	defer restore()
   328  
   329  	st.Unlock()
   330  	err = snapstate.CheckSnap(st, "snap-path", "gadget", nil, nil, snapstate.Flags{}, s.deviceCtx)
   331  	st.Lock()
   332  	c.Check(err, IsNil)
   333  }
   334  
   335  func (s *checkSnapSuite) TestCheckSnapGadgetUpdateToUnassertedProhibited(c *C) {
   336  	reset := release.MockOnClassic(false)
   337  	defer reset()
   338  
   339  	st := state.New(nil)
   340  	st.Lock()
   341  	defer st.Unlock()
   342  
   343  	si := &snap.SideInfo{RealName: "gadget", Revision: snap.R(2), SnapID: "gadget-id"}
   344  	snaptest.MockSnap(c, `
   345  name: gadget
   346  type: gadget
   347  version: 1
   348  `, si)
   349  	snapstate.Set(st, "gadget", &snapstate.SnapState{
   350  		SnapType: "gadget",
   351  		Active:   true,
   352  		Sequence: []*snap.SideInfo{si},
   353  		Current:  si.Revision,
   354  	})
   355  
   356  	const yaml = `name: gadget
   357  type: gadget
   358  version: 2
   359  `
   360  
   361  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   362  	c.Assert(err, IsNil)
   363  
   364  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   365  		return info, emptyContainer(c), nil
   366  	}
   367  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   368  	defer restore()
   369  
   370  	st.Unlock()
   371  	err = snapstate.CheckSnap(st, "snap-path", "gadget", nil, nil, snapstate.Flags{}, s.deviceCtx)
   372  	st.Lock()
   373  	c.Check(err, ErrorMatches, `cannot replace signed gadget snap with an unasserted one`)
   374  }
   375  
   376  func (s *checkSnapSuite) TestCheckSnapGadgetAdditionProhibited(c *C) {
   377  	reset := release.MockOnClassic(false)
   378  	defer reset()
   379  
   380  	st := state.New(nil)
   381  	st.Lock()
   382  	defer st.Unlock()
   383  
   384  	si := &snap.SideInfo{RealName: "gadget", Revision: snap.R(2)}
   385  	snaptest.MockSnap(c, `
   386  name: gadget
   387  type: gadget
   388  version: 1
   389  `, si)
   390  	snapstate.Set(st, "gadget", &snapstate.SnapState{
   391  		SnapType: "gadget",
   392  		Active:   true,
   393  		Sequence: []*snap.SideInfo{si},
   394  		Current:  si.Revision,
   395  	})
   396  
   397  	const yaml = `name: zgadget
   398  type: gadget
   399  version: 2
   400  `
   401  
   402  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   403  	c.Assert(err, IsNil)
   404  
   405  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   406  		return info, emptyContainer(c), nil
   407  	}
   408  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   409  	defer restore()
   410  
   411  	st.Unlock()
   412  	err = snapstate.CheckSnap(st, "snap-path", "gadget", nil, nil, snapstate.Flags{}, s.deviceCtx)
   413  	st.Lock()
   414  	c.Check(err, ErrorMatches, "cannot replace gadget snap with a different one")
   415  }
   416  
   417  func (s *checkSnapSuite) TestCheckSnapGadgetAdditionProhibitedBySnapID(c *C) {
   418  	reset := release.MockOnClassic(false)
   419  	defer reset()
   420  
   421  	st := state.New(nil)
   422  	st.Lock()
   423  	defer st.Unlock()
   424  
   425  	si := &snap.SideInfo{RealName: "gadget", Revision: snap.R(2), SnapID: "gadget-id"}
   426  	snaptest.MockSnap(c, `
   427  name: gadget
   428  type: gadget
   429  version: 1
   430  `, si)
   431  	snapstate.Set(st, "gadget", &snapstate.SnapState{
   432  		SnapType: "gadget",
   433  		Active:   true,
   434  		Sequence: []*snap.SideInfo{si},
   435  		Current:  si.Revision,
   436  	})
   437  
   438  	const yaml = `name: zgadget
   439  type: gadget
   440  version: 2
   441  `
   442  
   443  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   444  	info.SnapID = "zgadget-id"
   445  	c.Assert(err, IsNil)
   446  
   447  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   448  		return info, emptyContainer(c), nil
   449  	}
   450  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   451  	defer restore()
   452  
   453  	st.Unlock()
   454  	err = snapstate.CheckSnap(st, "snap-path", "gadget", nil, nil, snapstate.Flags{}, s.deviceCtx)
   455  	st.Lock()
   456  	c.Check(err, ErrorMatches, "cannot replace gadget snap with a different one")
   457  }
   458  
   459  func (s *checkSnapSuite) TestCheckSnapGadgetNoPrior(c *C) {
   460  	reset := release.MockOnClassic(false)
   461  	defer reset()
   462  
   463  	st := state.New(nil)
   464  	st.Lock()
   465  	defer st.Unlock()
   466  	st.Set("seeded", true)
   467  
   468  	const yaml = `name: gadget
   469  type: gadget
   470  version: 1
   471  `
   472  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   473  	c.Assert(err, IsNil)
   474  
   475  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   476  		return info, emptyContainer(c), nil
   477  	}
   478  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   479  	defer restore()
   480  
   481  	st.Unlock()
   482  	err = snapstate.CheckSnap(st, "snap-path", "gadget", nil, nil, snapstate.Flags{}, nil)
   483  	st.Lock()
   484  	c.Check(err, IsNil)
   485  }
   486  
   487  func (s *checkSnapSuite) TestCheckSnapErrorOnDevModeDisallowed(c *C) {
   488  	const yaml = `name: hello
   489  version: 1.10
   490  confinement: devmode
   491  `
   492  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   493  	c.Assert(err, IsNil)
   494  
   495  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   496  		c.Check(path, Equals, "snap-path")
   497  		c.Check(si, IsNil)
   498  		return info, emptyContainer(c), nil
   499  	}
   500  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   501  	defer restore()
   502  
   503  	err = snapstate.CheckSnap(s.st, "snap-path", "hello", nil, nil, snapstate.Flags{}, nil)
   504  
   505  	c.Assert(err, ErrorMatches, ".* requires devmode or confinement override")
   506  }
   507  
   508  func (s *checkSnapSuite) TestCheckSnapErrorOnClassicDisallowed(c *C) {
   509  	const yaml = `name: hello
   510  version: 1.10
   511  confinement: classic
   512  `
   513  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   514  	c.Assert(err, IsNil)
   515  
   516  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   517  		c.Check(path, Equals, "snap-path")
   518  		c.Check(si, IsNil)
   519  		return info, emptyContainer(c), nil
   520  	}
   521  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   522  	defer restore()
   523  
   524  	restore = release.MockOnClassic(true)
   525  	defer restore()
   526  
   527  	err = snapstate.CheckSnap(s.st, "snap-path", "hello", nil, nil, snapstate.Flags{}, nil)
   528  
   529  	c.Assert(err, ErrorMatches, ".* requires classic confinement")
   530  }
   531  
   532  func (s *checkSnapSuite) TestCheckSnapErrorClassicOnCoreDisallowed(c *C) {
   533  	const yaml = `name: hello
   534  version: 1.10
   535  confinement: classic
   536  `
   537  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   538  	c.Assert(err, IsNil)
   539  
   540  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   541  		c.Check(path, Equals, "snap-path")
   542  		c.Check(si, IsNil)
   543  		return info, emptyContainer(c), nil
   544  	}
   545  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   546  	defer restore()
   547  
   548  	restore = release.MockOnClassic(false)
   549  	defer restore()
   550  
   551  	err = snapstate.CheckSnap(s.st, "snap-path", "hello", nil, nil, snapstate.Flags{Classic: true}, nil)
   552  
   553  	c.Assert(err, ErrorMatches, ".* requires classic confinement which is only available on classic systems")
   554  }
   555  
   556  func (s *checkSnapSuite) TestCheckSnapErrorClassicModeForStrictOrDevmode(c *C) {
   557  	const yaml = `name: hello
   558  version: 1.10
   559  confinement: strict
   560  `
   561  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   562  	c.Assert(err, IsNil)
   563  
   564  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   565  		c.Check(path, Equals, "snap-path")
   566  		c.Check(si, IsNil)
   567  		return info, emptyContainer(c), nil
   568  	}
   569  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   570  	defer restore()
   571  
   572  	err = snapstate.CheckSnap(s.st, "snap-path", "hello", nil, nil, snapstate.Flags{Classic: true}, nil)
   573  
   574  	c.Assert(err, ErrorMatches, `snap "hello" is not a classic confined snap`)
   575  }
   576  
   577  func (s *checkSnapSuite) TestCheckSnapKernelUpdate(c *C) {
   578  	reset := release.MockOnClassic(false)
   579  	defer reset()
   580  
   581  	st := state.New(nil)
   582  	st.Lock()
   583  	defer st.Unlock()
   584  
   585  	si := &snap.SideInfo{RealName: "kernel", Revision: snap.R(2), SnapID: "kernel-id"}
   586  	snaptest.MockSnap(c, `
   587  name: kernel
   588  type: kernel
   589  version: 1
   590  `, si)
   591  	snapstate.Set(st, "kernel", &snapstate.SnapState{
   592  		SnapType: "kernel",
   593  		Active:   true,
   594  		Sequence: []*snap.SideInfo{si},
   595  		Current:  si.Revision,
   596  	})
   597  
   598  	const yaml = `name: kernel
   599  type: kernel
   600  version: 2
   601  `
   602  
   603  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   604  	info.SnapID = "kernel-id"
   605  	c.Assert(err, IsNil)
   606  
   607  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   608  		return info, emptyContainer(c), nil
   609  	}
   610  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   611  	defer restore()
   612  
   613  	st.Unlock()
   614  	err = snapstate.CheckSnap(st, "snap-path", "kernel", nil, nil, snapstate.Flags{}, s.deviceCtx)
   615  	st.Lock()
   616  	c.Check(err, IsNil)
   617  }
   618  
   619  func (s *checkSnapSuite) TestCheckSnapKernelAdditionProhibitedBySnapID(c *C) {
   620  	reset := release.MockOnClassic(false)
   621  	defer reset()
   622  
   623  	st := state.New(nil)
   624  	st.Lock()
   625  	defer st.Unlock()
   626  
   627  	si := &snap.SideInfo{RealName: "kernel", Revision: snap.R(2), SnapID: "kernel-id"}
   628  	snaptest.MockSnap(c, `
   629  name: kernel
   630  type: kernel
   631  version: 1
   632  `, si)
   633  	snapstate.Set(st, "kernel", &snapstate.SnapState{
   634  		SnapType: "kernel",
   635  		Active:   true,
   636  		Sequence: []*snap.SideInfo{si},
   637  		Current:  si.Revision,
   638  	})
   639  
   640  	const yaml = `name: zkernel
   641  type: kernel
   642  version: 2
   643  `
   644  
   645  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   646  	info.SnapID = "zkernel-id"
   647  	c.Assert(err, IsNil)
   648  
   649  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   650  		return info, emptyContainer(c), nil
   651  	}
   652  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   653  	defer restore()
   654  
   655  	st.Unlock()
   656  	err = snapstate.CheckSnap(st, "snap-path", "kernel", nil, nil, snapstate.Flags{}, s.deviceCtx)
   657  	st.Lock()
   658  	c.Check(err, ErrorMatches, "cannot replace kernel snap with a different one")
   659  }
   660  
   661  func (s *checkSnapSuite) TestCheckSnapBasesErrorsIfMissing(c *C) {
   662  	st := state.New(nil)
   663  	st.Lock()
   664  	defer st.Unlock()
   665  
   666  	const yaml = `name: requires-base
   667  version: 1
   668  base: some-base
   669  `
   670  
   671  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   672  	c.Assert(err, IsNil)
   673  
   674  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   675  		return info, emptyContainer(c), nil
   676  	}
   677  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   678  	defer restore()
   679  
   680  	st.Unlock()
   681  	err = snapstate.CheckSnap(st, "snap-path", "requires-base", nil, nil, snapstate.Flags{}, nil)
   682  	st.Lock()
   683  	c.Check(err, ErrorMatches, "cannot find required base \"some-base\"")
   684  }
   685  
   686  func (s *checkSnapSuite) TestCheckSnapBasesNoneHappy(c *C) {
   687  	st := state.New(nil)
   688  	st.Lock()
   689  	defer st.Unlock()
   690  
   691  	const yaml = `name: use-base-none
   692  version: 1
   693  base: none
   694  `
   695  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   696  	c.Assert(err, IsNil)
   697  
   698  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   699  		return info, emptyContainer(c), nil
   700  	}
   701  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   702  	defer restore()
   703  
   704  	st.Unlock()
   705  	err = snapstate.CheckSnap(st, "snap-path", "use-base-none", nil, nil, snapstate.Flags{}, nil)
   706  	st.Lock()
   707  	c.Check(err, IsNil)
   708  }
   709  
   710  func (s *checkSnapSuite) TestCheckSnapBasesHappy(c *C) {
   711  	st := state.New(nil)
   712  	st.Lock()
   713  	defer st.Unlock()
   714  
   715  	si := &snap.SideInfo{RealName: "some-base", Revision: snap.R(1), SnapID: "some-base-id"}
   716  	snaptest.MockSnap(c, `
   717  name: some-base
   718  type: base
   719  version: 1
   720  `, si)
   721  	snapstate.Set(st, "some-base", &snapstate.SnapState{
   722  		SnapType: "base",
   723  		Active:   true,
   724  		Sequence: []*snap.SideInfo{si},
   725  		Current:  si.Revision,
   726  	})
   727  
   728  	const yaml = `name: requires-base
   729  version: 1
   730  base: some-base
   731  `
   732  
   733  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   734  	c.Assert(err, IsNil)
   735  
   736  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   737  		return info, emptyContainer(c), nil
   738  	}
   739  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   740  	defer restore()
   741  
   742  	st.Unlock()
   743  	err = snapstate.CheckSnap(st, "snap-path", "requires-base", nil, nil, snapstate.Flags{}, nil)
   744  	st.Lock()
   745  	c.Check(err, IsNil)
   746  }
   747  
   748  // emptyContainer returns a minimal container that passes
   749  // ValidateContainer: / and /meta exist and are 0755, and
   750  // /meta/snap.yaml is a regular world-readable file.
   751  func emptyContainer(c *C) *snapdir.SnapDir {
   752  	d := c.MkDir()
   753  	c.Assert(os.Chmod(d, 0755), IsNil)
   754  	c.Assert(os.Mkdir(filepath.Join(d, "meta"), 0755), IsNil)
   755  	c.Assert(ioutil.WriteFile(filepath.Join(d, "meta", "snap.yaml"), nil, 0444), IsNil)
   756  	return snapdir.New(d)
   757  }
   758  
   759  func (s *checkSnapSuite) TestCheckSnapInstanceName(c *C) {
   760  	st := state.New(nil)
   761  	st.Lock()
   762  	defer st.Unlock()
   763  
   764  	si := &snap.SideInfo{RealName: "foo", Revision: snap.R(1), SnapID: "some-base-id"}
   765  	info := snaptest.MockSnap(c, `
   766  name: foo
   767  version: 1
   768  `, si)
   769  	snapstate.Set(st, "foo", &snapstate.SnapState{
   770  		Active:   true,
   771  		Sequence: []*snap.SideInfo{si},
   772  		Current:  si.Revision,
   773  	})
   774  
   775  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   776  		return info, emptyContainer(c), nil
   777  	}
   778  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   779  	defer restore()
   780  
   781  	st.Unlock()
   782  	err := snapstate.CheckSnap(st, "snap-path", "foo_instance", nil, nil, snapstate.Flags{}, nil)
   783  	st.Lock()
   784  	c.Check(err, IsNil)
   785  
   786  	st.Unlock()
   787  	err = snapstate.CheckSnap(st, "snap-path", "bar_instance", nil, nil, snapstate.Flags{}, nil)
   788  	st.Lock()
   789  	c.Check(err, ErrorMatches, `cannot install snap "foo" using instance name "bar_instance"`)
   790  
   791  	st.Unlock()
   792  	err = snapstate.CheckSnap(st, "snap-path", "other-name", nil, nil, snapstate.Flags{}, nil)
   793  	st.Lock()
   794  	c.Check(err, ErrorMatches, `cannot install snap "foo" using instance name "other-name"`)
   795  }
   796  
   797  func (s *checkSnapSuite) TestCheckSnapCheckCallInstanceKeySet(c *C) {
   798  	const yaml = `name: foo
   799  version: 1.0`
   800  
   801  	si := &snap.SideInfo{
   802  		SnapID: "snap-id",
   803  	}
   804  
   805  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   806  		info := snaptest.MockInfo(c, yaml, si)
   807  		return info, emptyContainer(c), nil
   808  	}
   809  	r1 := snapstate.MockOpenSnapFile(openSnapFile)
   810  	defer r1()
   811  
   812  	checkCbCalled := false
   813  	checkCb := func(st *state.State, s, cur *snap.Info, flags snapstate.Flags, deviceCtx snapstate.DeviceContext) error {
   814  		c.Assert(s.InstanceName(), Equals, "foo_instance")
   815  		c.Assert(s.SnapName(), Equals, "foo")
   816  		c.Assert(s.SnapID, Equals, "snap-id")
   817  		checkCbCalled = true
   818  		return nil
   819  	}
   820  	r2 := snapstate.MockCheckSnapCallbacks([]snapstate.CheckSnapCallback{checkCb})
   821  	defer r2()
   822  
   823  	err := snapstate.CheckSnap(s.st, "snap-path", "foo_instance", si, nil, snapstate.Flags{}, nil)
   824  	c.Check(err, IsNil)
   825  
   826  	c.Check(checkCbCalled, Equals, true)
   827  }
   828  
   829  func (s *checkSnapSuite) TestCheckSnapCheckEpochLocal(c *C) {
   830  	si := &snap.SideInfo{
   831  		SnapID: "snap-id",
   832  	}
   833  
   834  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   835  		info := snaptest.MockInfo(c, "{name: foo, version: 1.0, epoch: 13}", si)
   836  		return info, emptyContainer(c), nil
   837  	}
   838  	r1 := snapstate.MockOpenSnapFile(openSnapFile)
   839  	defer r1()
   840  
   841  	err := snapstate.CheckSnap(s.st, "snap-path", "foo", si, &snap.Info{}, snapstate.Flags{}, nil)
   842  	c.Check(err, ErrorMatches, `cannot refresh "foo" to local snap with epoch 13, because it can't read the current epoch of 0`)
   843  }
   844  
   845  func (s *checkSnapSuite) TestCheckSnapCheckEpochNonLocal(c *C) {
   846  	si := &snap.SideInfo{
   847  		SnapID:   "snap-id",
   848  		Revision: snap.R(42),
   849  	}
   850  
   851  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   852  		info := snaptest.MockInfo(c, "{name: foo, version: 1.0, epoch: 13}", si)
   853  		return info, emptyContainer(c), nil
   854  	}
   855  	r1 := snapstate.MockOpenSnapFile(openSnapFile)
   856  	defer r1()
   857  
   858  	err := snapstate.CheckSnap(s.st, "snap-path", "foo", si, &snap.Info{}, snapstate.Flags{}, nil)
   859  	c.Check(err, ErrorMatches, `cannot refresh "foo" to new revision 42 with epoch 13, because it can't read the current epoch of 0`)
   860  }
   861  
   862  func (s *checkSnapSuite) TestCheckSnapBasesCoreCanBeUsedAsCore16(c *C) {
   863  	st := state.New(nil)
   864  	st.Lock()
   865  	defer st.Unlock()
   866  
   867  	si := &snap.SideInfo{RealName: "core", Revision: snap.R(1), SnapID: "core-id"}
   868  	snaptest.MockSnap(c, `
   869  name: core
   870  type: os
   871  version: 1
   872  `, si)
   873  	snapstate.Set(st, "core", &snapstate.SnapState{
   874  		SnapType: "os",
   875  		Active:   true,
   876  		Sequence: []*snap.SideInfo{si},
   877  		Current:  si.Revision,
   878  	})
   879  
   880  	const yaml = `name: requires-core16
   881  version: 1
   882  base: core16
   883  `
   884  
   885  	info, err := snap.InfoFromSnapYaml([]byte(yaml))
   886  	c.Assert(err, IsNil)
   887  
   888  	var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   889  		return info, emptyContainer(c), nil
   890  	}
   891  	restore := snapstate.MockOpenSnapFile(openSnapFile)
   892  	defer restore()
   893  
   894  	st.Unlock()
   895  	err = snapstate.CheckSnap(st, "snap-path", "requires-core16", nil, nil, snapstate.Flags{}, nil)
   896  	st.Lock()
   897  	c.Check(err, IsNil)
   898  }
   899  
   900  func (s *checkSnapSuite) TestCheckSnapdHappy(c *C) {
   901  	st := state.New(nil)
   902  	st.Lock()
   903  	defer st.Unlock()
   904  
   905  	for _, t := range []struct {
   906  		yaml   string
   907  		errStr string
   908  	}{
   909  		{"name: snapd\nversion: 1\ntype: snapd", ""},
   910  		{"name: some-snap\nversion: 1\ntype: snapd", `cannot install snap "some-snap" of type "snapd" with a name other than "snapd"`},
   911  		{"name: snapd_instance\nversion: 1\ntype: snapd", `cannot install snap "snapd_instance" of type "snapd" with a name other than "snapd"`},
   912  	} {
   913  		info, err := snap.InfoFromSnapYaml([]byte(t.yaml))
   914  		c.Assert(err, IsNil)
   915  
   916  		var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
   917  			return info, emptyContainer(c), nil
   918  		}
   919  		restore := snapstate.MockOpenSnapFile(openSnapFile)
   920  		defer restore()
   921  
   922  		st.Unlock()
   923  		err = snapstate.CheckSnap(st, "snap-path", "snapd", nil, nil, snapstate.Flags{}, nil)
   924  		st.Lock()
   925  		if t.errStr == "" {
   926  			c.Check(err, IsNil)
   927  		} else {
   928  			c.Check(err, ErrorMatches, t.errStr)
   929  		}
   930  	}
   931  }
   932  
   933  // Note, invalid usernames checked in snap/info_snap_yaml.go
   934  var systemUsernamesTests = []struct {
   935  	sysIDs      string
   936  	classic     bool
   937  	noRangeUser bool
   938  	noUser      bool
   939  	scVer       string
   940  	error       string
   941  }{{
   942  	sysIDs: "snap_daemon: shared",
   943  	scVer:  "dead 2.4.1 deadbeef bpf-actlog",
   944  }, {
   945  	sysIDs: "snap_daemon:\n    scope: shared",
   946  	scVer:  "dead 2.4.1 deadbeef bpf-actlog",
   947  }, {
   948  	sysIDs: "snap_daemon:\n    scope: private",
   949  	scVer:  "dead 2.4.1 deadbeef bpf-actlog",
   950  	error:  `snap "foo" requires unsupported user scope "private" for this version of snapd`,
   951  }, {
   952  	sysIDs: "snap_daemon:\n    scope: external",
   953  	scVer:  "dead 2.4.1 deadbeef bpf-actlog",
   954  	error:  `snap "foo" requires unsupported user scope "external" for this version of snapd`,
   955  }, {
   956  	sysIDs: "snap_daemon:\n    scope: other",
   957  	scVer:  "dead 2.4.1 deadbeef bpf-actlog",
   958  	error:  `snap "foo" requires unsupported user scope "other"`,
   959  }, {
   960  	sysIDs:  "snap_daemon: shared",
   961  	scVer:   "dead 2.4.1 deadbeef bpf-actlog",
   962  	classic: true,
   963  }, {
   964  	sysIDs:  "snap_daemon:\n    scope: shared",
   965  	scVer:   "dead 2.4.1 deadbeef bpf-actlog",
   966  	classic: true,
   967  }, {
   968  	sysIDs:  "snap_daemon:\n    scope: private",
   969  	scVer:   "dead 2.4.1 deadbeef bpf-actlog",
   970  	classic: true,
   971  	error:   `snap "foo" requires unsupported user scope "private" for this version of snapd`,
   972  }, {
   973  	sysIDs:  "snap_daemon:\n    scope: external",
   974  	scVer:   "dead 2.4.1 deadbeef bpf-actlog",
   975  	classic: true,
   976  	error:   `snap "foo" requires unsupported user scope "external" for this version of snapd`,
   977  }, {
   978  	sysIDs:  "snap_daemon:\n    scope: other",
   979  	scVer:   "dead 2.4.1 deadbeef bpf-actlog",
   980  	classic: true,
   981  	error:   `snap "foo" requires unsupported user scope "other"`,
   982  }, {
   983  	sysIDs: "snap_daemon: shared\n  allowed-not: shared",
   984  	scVer:  "dead 2.4.1 deadbeef bpf-actlog",
   985  	error:  `snap "foo" requires unsupported system username "allowed-not"`,
   986  }, {
   987  	sysIDs:  "allowed-not: shared\n  snap_daemon: shared",
   988  	scVer:   "dead 2.4.1 deadbeef bpf-actlog",
   989  	classic: true,
   990  	error:   `snap "foo" requires unsupported system username "allowed-not"`,
   991  }, {
   992  	sysIDs: "snap_daemon: shared",
   993  	noUser: true,
   994  	scVer:  "dead 2.4.1 deadbeef bpf-actlog",
   995  	error:  `cannot ensure users for snap "foo" required system username "snap_daemon": cannot add user/group "snap_daemon", group exists and user does not`,
   996  }, {
   997  	sysIDs:  "snap_daemon: shared",
   998  	classic: true,
   999  	noUser:  true,
  1000  	scVer:   "dead 2.4.1 deadbeef bpf-actlog",
  1001  	error:   `cannot ensure users for snap "foo" required system username "snap_daemon": cannot add user/group "snap_daemon", group exists and user does not`,
  1002  }, {
  1003  	sysIDs: "snap_daemon: shared",
  1004  	scVer:  "dead 2.3.3 deadbeef bpf-actlog",
  1005  	error:  `snap "foo" system usernames require a snapd built against libseccomp >= 2.4`,
  1006  }, {
  1007  	sysIDs:  "snap_daemon: shared",
  1008  	classic: true,
  1009  	scVer:   "dead 2.3.3 deadbeef bpf-actlog",
  1010  	error:   `snap "foo" system usernames require a snapd built against libseccomp >= 2.4`,
  1011  }, {
  1012  	sysIDs: "snap_daemon: shared",
  1013  	scVer:  "dead 3.0.0 deadbeef bpf-actlog",
  1014  }, {
  1015  	sysIDs:  "snap_daemon: shared",
  1016  	classic: true,
  1017  	scVer:   "dead 3.0.0 deadbeef bpf-actlog",
  1018  }, {
  1019  	sysIDs: "snap_daemon: shared",
  1020  	scVer:  "dead 2.4.1 deadbeef -",
  1021  	error:  `snap "foo" system usernames require a snapd built against golang-seccomp >= 0.9.1`,
  1022  }, {
  1023  	sysIDs:  "snap_daemon: shared",
  1024  	classic: true,
  1025  	scVer:   "dead 2.4.1 deadbeef -",
  1026  	error:   `snap "foo" system usernames require a snapd built against golang-seccomp >= 0.9.1`,
  1027  }, {
  1028  	sysIDs:      "snap_daemon: shared",
  1029  	noRangeUser: true,
  1030  	scVer:       "dead 2.4.1 deadbeef bpf-actlog",
  1031  	error:       `cannot ensure users for snap "foo" required system username "snap_daemon": cannot add user/group "snapd-range-524288-root", group exists and user does not`,
  1032  }, {
  1033  	sysIDs:      "snap_daemon: shared",
  1034  	classic:     true,
  1035  	noRangeUser: true,
  1036  	scVer:       "dead 2.4.1 deadbeef bpf-actlog",
  1037  	error:       `cannot ensure users for snap "foo" required system username "snap_daemon": cannot add user/group "snapd-range-524288-root", group exists and user does not`,
  1038  }, {
  1039  	sysIDs:  "snap_daemon: shared\n  daemon: shared",
  1040  	classic: true,
  1041  	scVer:   "dead 2.4.1 deadbeef bpf-actlog",
  1042  	error:   `snap "foo" requires unsupported system username "daemon"`,
  1043  },
  1044  }
  1045  
  1046  func (s *checkSnapSuite) TestCheckSnapSystemUsernames(c *C) {
  1047  	for _, test := range systemUsernamesTests {
  1048  		restore := seccomp_compiler.MockCompilerVersionInfo(test.scVer)
  1049  		defer restore()
  1050  
  1051  		restore = release.MockOnClassic(test.classic)
  1052  		defer restore()
  1053  
  1054  		var osutilEnsureUserGroupCalls int
  1055  		if test.noRangeUser {
  1056  			restore = snapstate.MockOsutilEnsureUserGroup(func(name string, id uint32, extraUsers bool) error {
  1057  				return fmt.Errorf(`cannot add user/group "%s", group exists and user does not`, name)
  1058  			})
  1059  		} else if test.noUser {
  1060  			restore = snapstate.MockOsutilEnsureUserGroup(func(name string, id uint32, extraUsers bool) error {
  1061  				if name == "snapd-range-524288-root" {
  1062  					return nil
  1063  				}
  1064  				return fmt.Errorf(`cannot add user/group "%s", group exists and user does not`, name)
  1065  			})
  1066  		} else {
  1067  			restore = snapstate.MockOsutilEnsureUserGroup(func(name string, id uint32, extraUsers bool) error {
  1068  				osutilEnsureUserGroupCalls++
  1069  				return nil
  1070  			})
  1071  		}
  1072  		defer restore()
  1073  
  1074  		yaml := fmt.Sprintf("name: foo\nsystem-usernames:\n  %s\n", test.sysIDs)
  1075  
  1076  		info, err := snap.InfoFromSnapYaml([]byte(yaml))
  1077  		c.Assert(err, IsNil)
  1078  
  1079  		var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
  1080  			return info, emptyContainer(c), nil
  1081  		}
  1082  		restore = snapstate.MockOpenSnapFile(openSnapFile)
  1083  		defer restore()
  1084  		err = snapstate.CheckSnap(s.st, "snap-path", "foo", nil, nil, snapstate.Flags{}, nil)
  1085  		if test.error != "" {
  1086  			c.Check(err, ErrorMatches, test.error)
  1087  			c.Check(osutilEnsureUserGroupCalls, Equals, 0)
  1088  		} else {
  1089  			c.Assert(err, IsNil)
  1090  			// one call for the range user, one for the system user
  1091  			c.Check(osutilEnsureUserGroupCalls, Equals, 2)
  1092  		}
  1093  	}
  1094  }
  1095  
  1096  func (s *checkSnapSuite) TestCheckSnapSystemUsernamesCalls(c *C) {
  1097  	falsePath := osutil.LookPathDefault("false", "/bin/false")
  1098  	for _, classic := range []bool{false, true} {
  1099  		restore := release.MockOnClassic(classic)
  1100  		defer restore()
  1101  
  1102  		restore = seccomp_compiler.MockCompilerVersionInfo("dead 2.4.1 deadbeef bpf-actlog")
  1103  		defer restore()
  1104  
  1105  		const yaml = `name: foo
  1106  version: 1.0
  1107  system-usernames:
  1108    snap_daemon: shared`
  1109  
  1110  		info, err := snap.InfoFromSnapYaml([]byte(yaml))
  1111  		c.Assert(err, IsNil)
  1112  
  1113  		var openSnapFile = func(path string, si *snap.SideInfo) (*snap.Info, snap.Container, error) {
  1114  			return info, emptyContainer(c), nil
  1115  		}
  1116  		restore = snapstate.MockOpenSnapFile(openSnapFile)
  1117  		defer restore()
  1118  
  1119  		mockGroupAdd := testutil.MockCommand(c, "groupadd", "")
  1120  		defer mockGroupAdd.Restore()
  1121  
  1122  		mockUserAdd := testutil.MockCommand(c, "useradd", "")
  1123  		defer mockUserAdd.Restore()
  1124  
  1125  		err = snapstate.CheckSnap(s.st, "snap-path", "foo", nil, nil, snapstate.Flags{}, nil)
  1126  		c.Assert(err, IsNil)
  1127  		if classic {
  1128  			c.Check(mockGroupAdd.Calls(), DeepEquals, [][]string{
  1129  				{"groupadd", "--system", "--gid", "524288", "snapd-range-524288-root"},
  1130  				{"groupadd", "--system", "--gid", "584788", "snap_daemon"},
  1131  			})
  1132  			c.Check(mockUserAdd.Calls(), DeepEquals, [][]string{
  1133  				{"useradd", "--system", "--home-dir", "/nonexistent", "--no-create-home", "--shell", falsePath, "--gid", "524288", "--no-user-group", "--uid", "524288", "snapd-range-524288-root"},
  1134  				{"useradd", "--system", "--home-dir", "/nonexistent", "--no-create-home", "--shell", falsePath, "--gid", "584788", "--no-user-group", "--uid", "584788", "snap_daemon"},
  1135  			})
  1136  		} else {
  1137  			c.Check(mockGroupAdd.Calls(), DeepEquals, [][]string{
  1138  				{"groupadd", "--system", "--gid", "524288", "--extrausers", "snapd-range-524288-root"},
  1139  				{"groupadd", "--system", "--gid", "584788", "--extrausers", "snap_daemon"},
  1140  			})
  1141  			c.Check(mockUserAdd.Calls(), DeepEquals, [][]string{
  1142  				{"useradd", "--system", "--home-dir", "/nonexistent", "--no-create-home", "--shell", falsePath, "--gid", "524288", "--no-user-group", "--uid", "524288", "--extrausers", "snapd-range-524288-root"},
  1143  				{"useradd", "--system", "--home-dir", "/nonexistent", "--no-create-home", "--shell", falsePath, "--gid", "584788", "--no-user-group", "--uid", "584788", "--extrausers", "snap_daemon"},
  1144  			})
  1145  
  1146  		}
  1147  	}
  1148  }