gitee.com/mysnapcore/mysnapd@v0.1.0/interfaces/builtin/posix_mq_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2022 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 builtin_test
    21  
    22  import (
    23  	. "gopkg.in/check.v1"
    24  
    25  	"gitee.com/mysnapcore/mysnapd/interfaces"
    26  	"gitee.com/mysnapcore/mysnapd/interfaces/apparmor"
    27  	"gitee.com/mysnapcore/mysnapd/interfaces/builtin"
    28  	"gitee.com/mysnapcore/mysnapd/interfaces/seccomp"
    29  	apparmor_sandbox "gitee.com/mysnapcore/mysnapd/sandbox/apparmor"
    30  	"gitee.com/mysnapcore/mysnapd/snap"
    31  	"gitee.com/mysnapcore/mysnapd/snap/snaptest"
    32  	"gitee.com/mysnapcore/mysnapd/testutil"
    33  )
    34  
    35  const slotSnapInfoYaml = `name: producer
    36  version: 1.0
    37  
    38  slots:
    39    test-rw:
    40      interface: posix-mq
    41      path: /test-rw
    42      permissions:
    43        - read
    44        - write
    45  
    46    test-default:
    47      interface: posix-mq
    48      path: /test-default
    49  
    50    test-ro:
    51      interface: posix-mq
    52      path: /test-ro
    53      permissions:
    54        - read
    55  
    56    test-all-perms:
    57      interface: posix-mq
    58      path: /test-all-perms
    59      permissions:
    60        - create
    61        - delete
    62        - read
    63        - write
    64  
    65    test-path-array:
    66      interface: posix-mq
    67      path:
    68        - /test-array-1
    69        - /test-array-2
    70        - /test-array-3
    71  
    72    test-empty-path-array:
    73      interface: posix-mq
    74      path: []
    75  
    76    test-one-empty-path-array:
    77      interface: posix-mq
    78      path:
    79        - /test-array-1
    80        - ""
    81  
    82    test-empty-path:
    83      interface: posix-mq
    84      path: ""
    85  
    86    test-invalid-path-1:
    87      interface: posix-mq
    88      path: ../../test-invalid
    89  
    90    test-invalid-path-2:
    91      interface: posix-mq
    92      path: /test-invalid-2"[
    93  
    94    test-invalid-path-3:
    95      interface: posix-mq
    96      path:
    97        this-is-not-a-valid-path: true
    98  
    99    test-invalid-path-4:
   100      interface: posix-mq
   101  
   102    test-invalid-path-5:
   103      interface: posix-mq
   104      path: /.
   105  
   106    test-invalid-perms-1:
   107      interface: posix-mq
   108      path: /test-invalid-perms-1
   109      permissions:
   110        - create
   111        - delete
   112        - break-everything
   113  
   114    test-invalid-perms-2:
   115        interface: posix-mq
   116        path: /test-invalid-perms-2
   117        permissions: not-a-list
   118  
   119    test-invalid-perms-3:
   120      interface: posix-mq
   121      path: /test-invalid-perms-3
   122      permissions:
   123        - create
   124        - [not-a-string]
   125  
   126    test-label:
   127        interface: posix-mq
   128        posix-mq: this-is-a-test-label
   129        path: /test-label
   130  
   131    test-broken-label:
   132      interface: posix-mq
   133      posix-mq:
   134        - broken
   135      path: /test-default
   136  
   137  apps:
   138    app:
   139      command: foo
   140      slots:
   141        - test-default-rw
   142        - test-rw
   143        - test-ro
   144        - test-all-perms
   145        - test-invalid-path-1
   146        - test-invalid-path-2
   147  `
   148  
   149  const defaultRWPlugSnapInfoYaml = `name: consumer
   150  version: 1.0
   151  
   152  plugs:
   153    test-default:
   154      interface: posix-mq
   155  
   156  apps:
   157    app:
   158      command: foo
   159      plugs: [test-default]
   160  `
   161  
   162  const rwPlugSnapInfoYaml = `name: consumer
   163  version: 1.0
   164  
   165  plugs:
   166    test-rw:
   167      interface: posix-mq
   168  
   169  apps:
   170    app:
   171      command: foo
   172      plugs: [test-rw]
   173  `
   174  
   175  const roPlugSnapInfoYaml = `name: consumer
   176  version: 1.0
   177  
   178  plugs:
   179    test-ro:
   180      interface: posix-mq
   181  
   182  apps:
   183    app:
   184      command: foo
   185      plugs: [test-ro]
   186  `
   187  
   188  const allPermsPlugSnapInfoYaml = `name: consumer
   189  version: 1.0
   190  
   191  plugs:
   192    test-all-perms:
   193      interface: posix-mq
   194  
   195  apps:
   196    app:
   197      command: foo
   198      plugs: [test-all-perms]
   199  `
   200  
   201  const pathArrayPlugSnapInfoYaml = `name: consumer
   202  version: 1.0
   203  
   204  plugs:
   205    test-path-array:
   206      interface: posix-mq
   207  
   208  apps:
   209    app:
   210      command: foo
   211      plugs: [test-path-array]
   212  `
   213  
   214  const invalidPerms1PlugSnapInfoYaml = `name: consumer
   215  version: 1.0
   216  
   217  plugs:
   218    test-invalid-perms-1:
   219      interface: posix-mq
   220  
   221  apps:
   222    app:
   223      command: foo
   224      plugs: [test-invalid-perms-1]
   225  `
   226  
   227  const testLabelPlugSnapInfoYaml = `name: consumer
   228  version: 1.0
   229  
   230  plugs:
   231    test-label:
   232      interface: posix-mq
   233      posix-mq: this-is-a-test-label
   234  
   235  apps:
   236    app:
   237      command: foo
   238      plugs: [test-label]
   239  `
   240  
   241  const invalidPerms3PlugSnapInfoYaml = `name: consumer
   242  version: 1.0
   243  
   244  plugs:
   245    test-invalid-perms-3:
   246      interface: posix-mq
   247  
   248  apps:
   249    app:
   250      command: foo
   251      plugs: [test-invalid-perms-3]
   252  `
   253  
   254  const testInvalidLabelPlugSnapInfoYaml = `name: consumer
   255  version: 1.0
   256  
   257  plugs:
   258    test-invalid-label:
   259      interface: posix-mq
   260      posix-mq:
   261        - this-is-a-broken-test-label
   262  
   263  apps:
   264    app:
   265      command: foo
   266      plugs: [test-invalid-label]
   267  `
   268  
   269  type PosixMQInterfaceSuite struct {
   270  	testutil.BaseTest
   271  
   272  	iface interfaces.Interface
   273  
   274  	testReadWriteSlotInfo *snap.SlotInfo
   275  	testReadWriteSlot     *interfaces.ConnectedSlot
   276  	testReadWritePlugInfo *snap.PlugInfo
   277  	testReadWritePlug     *interfaces.ConnectedPlug
   278  
   279  	testDefaultPermsSlotInfo *snap.SlotInfo
   280  	testDefaultPermsSlot     *interfaces.ConnectedSlot
   281  	testDefaultPermsPlugInfo *snap.PlugInfo
   282  	testDefaultPermsPlug     *interfaces.ConnectedPlug
   283  
   284  	testReadOnlySlotInfo *snap.SlotInfo
   285  	testReadOnlySlot     *interfaces.ConnectedSlot
   286  	testReadOnlyPlugInfo *snap.PlugInfo
   287  	testReadOnlyPlug     *interfaces.ConnectedPlug
   288  
   289  	testAllPermsSlotInfo *snap.SlotInfo
   290  	testAllPermsSlot     *interfaces.ConnectedSlot
   291  	testAllPermsPlugInfo *snap.PlugInfo
   292  	testAllPermsPlug     *interfaces.ConnectedPlug
   293  
   294  	testPathArraySlotInfo *snap.SlotInfo
   295  	testPathArraySlot     *interfaces.ConnectedSlot
   296  	testPathArrayPlugInfo *snap.PlugInfo
   297  	testPathArrayPlug     *interfaces.ConnectedPlug
   298  
   299  	testEmptyPathArraySlotInfo *snap.SlotInfo
   300  	testEmptyPathArraySlot     *interfaces.ConnectedSlot
   301  
   302  	testOneEmptyPathArraySlotInfo *snap.SlotInfo
   303  	testOneEmptyPathArraySlot     *interfaces.ConnectedSlot
   304  
   305  	testEmptyPathSlotInfo *snap.SlotInfo
   306  	testEmptyPathSlot     *interfaces.ConnectedSlot
   307  
   308  	testInvalidPath1SlotInfo *snap.SlotInfo
   309  	testInvalidPath1Slot     *interfaces.ConnectedSlot
   310  
   311  	testInvalidPath2SlotInfo *snap.SlotInfo
   312  	testInvalidPath2Slot     *interfaces.ConnectedSlot
   313  
   314  	testInvalidPath3SlotInfo *snap.SlotInfo
   315  	testInvalidPath3Slot     *interfaces.ConnectedSlot
   316  
   317  	testInvalidPath4SlotInfo *snap.SlotInfo
   318  	testInvalidPath4Slot     *interfaces.ConnectedSlot
   319  
   320  	testInvalidPath5SlotInfo *snap.SlotInfo
   321  	testInvalidPath5Slot     *interfaces.ConnectedSlot
   322  
   323  	testInvalidPerms1SlotInfo *snap.SlotInfo
   324  	testInvalidPerms1Slot     *interfaces.ConnectedSlot
   325  	testInvalidPerms1PlugInfo *snap.PlugInfo
   326  	testInvalidPerms1Plug     *interfaces.ConnectedPlug
   327  
   328  	testInvalidPerms2SlotInfo *snap.SlotInfo
   329  	testInvalidPerms2Slot     *interfaces.ConnectedSlot
   330  
   331  	testInvalidPerms3SlotInfo *snap.SlotInfo
   332  	testInvalidPerms3Slot     *interfaces.ConnectedSlot
   333  	testInvalidPerms3PlugInfo *snap.PlugInfo
   334  	testInvalidPerms3Plug     *interfaces.ConnectedPlug
   335  
   336  	testLabelSlotInfo *snap.SlotInfo
   337  	testLabelSlot     *interfaces.ConnectedSlot
   338  	testLabelPlugInfo *snap.PlugInfo
   339  	testLabelPlug     *interfaces.ConnectedPlug
   340  
   341  	testInvalidLabelSlotInfo *snap.SlotInfo
   342  	testInvalidLabelSlot     *interfaces.ConnectedSlot
   343  	testInvalidLabelPlugInfo *snap.PlugInfo
   344  	testInvalidLabelPlug     *interfaces.ConnectedPlug
   345  }
   346  
   347  var _ = Suite(&PosixMQInterfaceSuite{
   348  	iface: builtin.MustInterface("posix-mq"),
   349  })
   350  
   351  func (s *PosixMQInterfaceSuite) SetUpTest(c *C) {
   352  	s.BaseTest.SetUpTest(c)
   353  
   354  	slotSnap := snaptest.MockInfo(c, slotSnapInfoYaml, nil)
   355  
   356  	s.testReadWriteSlotInfo = slotSnap.Slots["test-rw"]
   357  	s.testReadWriteSlot = interfaces.NewConnectedSlot(s.testReadWriteSlotInfo, nil, nil)
   358  
   359  	s.testDefaultPermsSlotInfo = slotSnap.Slots["test-default"]
   360  	s.testDefaultPermsSlot = interfaces.NewConnectedSlot(s.testDefaultPermsSlotInfo, nil, nil)
   361  
   362  	s.testReadOnlySlotInfo = slotSnap.Slots["test-ro"]
   363  	s.testReadOnlySlot = interfaces.NewConnectedSlot(s.testReadOnlySlotInfo, nil, nil)
   364  
   365  	s.testAllPermsSlotInfo = slotSnap.Slots["test-all-perms"]
   366  	s.testAllPermsSlot = interfaces.NewConnectedSlot(s.testAllPermsSlotInfo, nil, nil)
   367  
   368  	s.testPathArraySlotInfo = slotSnap.Slots["test-path-array"]
   369  	s.testPathArraySlot = interfaces.NewConnectedSlot(s.testPathArraySlotInfo, nil, nil)
   370  
   371  	s.testEmptyPathArraySlotInfo = slotSnap.Slots["test-empty-path-array"]
   372  	s.testEmptyPathArraySlot = interfaces.NewConnectedSlot(s.testEmptyPathArraySlotInfo, nil, nil)
   373  
   374  	s.testOneEmptyPathArraySlotInfo = slotSnap.Slots["test-one-empty-path-array"]
   375  	s.testOneEmptyPathArraySlot = interfaces.NewConnectedSlot(s.testOneEmptyPathArraySlotInfo, nil, nil)
   376  
   377  	s.testEmptyPathSlotInfo = slotSnap.Slots["test-empty-path"]
   378  	s.testEmptyPathSlot = interfaces.NewConnectedSlot(s.testEmptyPathSlotInfo, nil, nil)
   379  
   380  	s.testInvalidPath1SlotInfo = slotSnap.Slots["test-invalid-path-1"]
   381  	s.testInvalidPath1Slot = interfaces.NewConnectedSlot(s.testInvalidPath1SlotInfo, nil, nil)
   382  
   383  	s.testInvalidPath2SlotInfo = slotSnap.Slots["test-invalid-path-2"]
   384  	s.testInvalidPath2Slot = interfaces.NewConnectedSlot(s.testInvalidPath2SlotInfo, nil, nil)
   385  
   386  	s.testInvalidPath3SlotInfo = slotSnap.Slots["test-invalid-path-3"]
   387  	s.testInvalidPath3Slot = interfaces.NewConnectedSlot(s.testInvalidPath3SlotInfo, nil, nil)
   388  
   389  	s.testInvalidPath4SlotInfo = slotSnap.Slots["test-invalid-path-4"]
   390  	s.testInvalidPath4Slot = interfaces.NewConnectedSlot(s.testInvalidPath4SlotInfo, nil, nil)
   391  
   392  	s.testInvalidPath5SlotInfo = slotSnap.Slots["test-invalid-path-5"]
   393  	s.testInvalidPath5Slot = interfaces.NewConnectedSlot(s.testInvalidPath5SlotInfo, nil, nil)
   394  
   395  	s.testInvalidPerms1SlotInfo = slotSnap.Slots["test-invalid-perms-1"]
   396  	s.testInvalidPerms1Slot = interfaces.NewConnectedSlot(s.testInvalidPerms1SlotInfo, nil, nil)
   397  
   398  	s.testInvalidPerms2SlotInfo = slotSnap.Slots["test-invalid-perms-2"]
   399  	s.testInvalidPerms2Slot = interfaces.NewConnectedSlot(s.testInvalidPerms2SlotInfo, nil, nil)
   400  
   401  	s.testInvalidPerms3SlotInfo = slotSnap.Slots["test-invalid-perms-3"]
   402  	s.testInvalidPerms3Slot = interfaces.NewConnectedSlot(s.testInvalidPerms3SlotInfo, nil, nil)
   403  
   404  	s.testLabelSlotInfo = slotSnap.Slots["test-label"]
   405  	s.testLabelSlot = interfaces.NewConnectedSlot(s.testLabelSlotInfo, nil, nil)
   406  
   407  	s.testInvalidLabelSlotInfo = slotSnap.Slots["test-broken-label"]
   408  	s.testInvalidLabelSlot = interfaces.NewConnectedSlot(s.testInvalidLabelSlotInfo, nil, nil)
   409  
   410  	plugSnap0 := snaptest.MockInfo(c, rwPlugSnapInfoYaml, nil)
   411  	s.testReadWritePlugInfo = plugSnap0.Plugs["test-rw"]
   412  	s.testReadWritePlug = interfaces.NewConnectedPlug(s.testReadWritePlugInfo, nil, nil)
   413  
   414  	plugSnap1 := snaptest.MockInfo(c, defaultRWPlugSnapInfoYaml, nil)
   415  	s.testDefaultPermsPlugInfo = plugSnap1.Plugs["test-default"]
   416  	s.testDefaultPermsPlug = interfaces.NewConnectedPlug(s.testDefaultPermsPlugInfo, nil, nil)
   417  
   418  	plugSnap2 := snaptest.MockInfo(c, roPlugSnapInfoYaml, nil)
   419  	s.testReadOnlyPlugInfo = plugSnap2.Plugs["test-ro"]
   420  	s.testReadOnlyPlug = interfaces.NewConnectedPlug(s.testReadOnlyPlugInfo, nil, nil)
   421  
   422  	plugSnap3 := snaptest.MockInfo(c, allPermsPlugSnapInfoYaml, nil)
   423  	s.testAllPermsPlugInfo = plugSnap3.Plugs["test-all-perms"]
   424  	s.testAllPermsPlug = interfaces.NewConnectedPlug(s.testAllPermsPlugInfo, nil, nil)
   425  
   426  	plugSnap4 := snaptest.MockInfo(c, invalidPerms1PlugSnapInfoYaml, nil)
   427  	s.testInvalidPerms1PlugInfo = plugSnap4.Plugs["test-invalid-perms-1"]
   428  	s.testInvalidPerms1Plug = interfaces.NewConnectedPlug(s.testInvalidPerms1PlugInfo, nil, nil)
   429  
   430  	plugSnap5 := snaptest.MockInfo(c, testLabelPlugSnapInfoYaml, nil)
   431  	s.testLabelPlugInfo = plugSnap5.Plugs["test-label"]
   432  	s.testLabelPlug = interfaces.NewConnectedPlug(s.testLabelPlugInfo, nil, nil)
   433  
   434  	plugSnap6 := snaptest.MockInfo(c, testInvalidLabelPlugSnapInfoYaml, nil)
   435  	s.testInvalidLabelPlugInfo = plugSnap6.Plugs["test-invalid-label"]
   436  	s.testInvalidLabelPlug = interfaces.NewConnectedPlug(s.testInvalidLabelPlugInfo, nil, nil)
   437  
   438  	plugSnap7 := snaptest.MockInfo(c, invalidPerms3PlugSnapInfoYaml, nil)
   439  	s.testInvalidPerms3PlugInfo = plugSnap7.Plugs["test-invalid-perms-3"]
   440  	s.testInvalidPerms3Plug = interfaces.NewConnectedPlug(s.testInvalidPerms3PlugInfo, nil, nil)
   441  
   442  	plugSnap8 := snaptest.MockInfo(c, pathArrayPlugSnapInfoYaml, nil)
   443  	s.testPathArrayPlugInfo = plugSnap8.Plugs["test-path-array"]
   444  	s.testPathArrayPlug = interfaces.NewConnectedPlug(s.testPathArrayPlugInfo, nil, nil)
   445  }
   446  
   447  func (s *PosixMQInterfaceSuite) checkSlotSeccompSnippet(c *C, spec *seccomp.Specification) {
   448  	slotSnippet := spec.SnippetForTag("snap.producer.app")
   449  	c.Check(slotSnippet, testutil.Contains, "mq_open")
   450  	c.Check(slotSnippet, testutil.Contains, "mq_unlink")
   451  	c.Check(slotSnippet, testutil.Contains, "mq_getsetattr")
   452  	c.Check(slotSnippet, testutil.Contains, "mq_notify")
   453  	c.Check(slotSnippet, testutil.Contains, "mq_timedreceive")
   454  	c.Check(slotSnippet, testutil.Contains, "mq_timedsend")
   455  }
   456  
   457  func (s *PosixMQInterfaceSuite) TestReadWriteMQAppArmor(c *C) {
   458  	spec := &apparmor.Specification{}
   459  	err := spec.AddPermanentSlot(s.iface, s.testReadWriteSlotInfo)
   460  	c.Assert(err, IsNil)
   461  	err = spec.AddConnectedPlug(s.iface, s.testReadWritePlug, s.testReadWriteSlot)
   462  	c.Assert(err, IsNil)
   463  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   464  
   465  	slotSnippet := spec.SnippetForTag("snap.producer.app")
   466  	c.Check(slotSnippet, testutil.Contains, `# POSIX Message Queue slot: test-rw`)
   467  	c.Check(slotSnippet, testutil.Contains, `mqueue (open read write create delete) "/test-rw",`)
   468  
   469  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   470  	c.Check(plugSnippet, testutil.Contains, `# POSIX Message Queue plug: test-rw`)
   471  	c.Check(plugSnippet, testutil.Contains, `mqueue (read write open) "/test-rw",`)
   472  }
   473  
   474  func (s *PosixMQInterfaceSuite) TestReadWriteMQSeccomp(c *C) {
   475  	spec := &seccomp.Specification{}
   476  	err := spec.AddPermanentSlot(s.iface, s.testReadWriteSlotInfo)
   477  	c.Assert(err, IsNil)
   478  	err = spec.AddConnectedPlug(s.iface, s.testReadWritePlug, s.testReadWriteSlot)
   479  	c.Assert(err, IsNil)
   480  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   481  
   482  	s.checkSlotSeccompSnippet(c, spec)
   483  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   484  	c.Check(plugSnippet, testutil.Contains, "mq_open")
   485  	c.Check(plugSnippet, testutil.Contains, "mq_notify")
   486  	c.Check(plugSnippet, testutil.Contains, "mq_timedreceive")
   487  	c.Check(plugSnippet, testutil.Contains, "mq_timedsend")
   488  	c.Check(plugSnippet, testutil.Contains, "mq_getsetattr")
   489  	c.Check(plugSnippet, Not(testutil.Contains), "mq_unlink")
   490  }
   491  
   492  func (s *PosixMQInterfaceSuite) TestDefaultReadWriteMQAppArmor(c *C) {
   493  	spec := &apparmor.Specification{}
   494  	err := spec.AddPermanentSlot(s.iface, s.testDefaultPermsSlotInfo)
   495  	c.Assert(err, IsNil)
   496  	err = spec.AddConnectedPlug(s.iface, s.testDefaultPermsPlug, s.testDefaultPermsSlot)
   497  	c.Assert(err, IsNil)
   498  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   499  
   500  	slotSnippet := spec.SnippetForTag("snap.producer.app")
   501  	c.Check(slotSnippet, testutil.Contains, `# POSIX Message Queue slot: test-default`)
   502  	c.Check(slotSnippet, testutil.Contains, `mqueue (open read write create delete) "/test-default",`)
   503  
   504  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   505  	c.Check(plugSnippet, testutil.Contains, `# POSIX Message Queue plug: test-default`)
   506  	c.Check(plugSnippet, testutil.Contains, `mqueue (read write open) "/test-default",`)
   507  }
   508  
   509  func (s *PosixMQInterfaceSuite) TestDefaultReadWriteMQSeccomp(c *C) {
   510  	spec := &seccomp.Specification{}
   511  	err := spec.AddPermanentSlot(s.iface, s.testDefaultPermsSlotInfo)
   512  	c.Assert(err, IsNil)
   513  	err = spec.AddConnectedPlug(s.iface, s.testDefaultPermsPlug, s.testDefaultPermsSlot)
   514  	c.Assert(err, IsNil)
   515  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   516  
   517  	s.checkSlotSeccompSnippet(c, spec)
   518  
   519  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   520  	c.Check(plugSnippet, testutil.Contains, "mq_open")
   521  	c.Check(plugSnippet, testutil.Contains, "mq_notify")
   522  	c.Check(plugSnippet, testutil.Contains, "mq_timedreceive")
   523  	c.Check(plugSnippet, testutil.Contains, "mq_timedsend")
   524  	c.Check(plugSnippet, testutil.Contains, "mq_getsetattr")
   525  	c.Check(plugSnippet, Not(testutil.Contains), "mq_unlink")
   526  }
   527  
   528  func (s *PosixMQInterfaceSuite) TestReadOnlyMQAppArmor(c *C) {
   529  	spec := &apparmor.Specification{}
   530  	err := spec.AddPermanentSlot(s.iface, s.testReadOnlySlotInfo)
   531  	c.Assert(err, IsNil)
   532  	err = spec.AddConnectedPlug(s.iface, s.testReadOnlyPlug, s.testReadOnlySlot)
   533  	c.Assert(err, IsNil)
   534  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   535  
   536  	slotSnippet := spec.SnippetForTag("snap.producer.app")
   537  	c.Check(slotSnippet, testutil.Contains, `mqueue (open read write create delete) "/test-ro",`)
   538  
   539  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   540  	c.Check(plugSnippet, testutil.Contains, `mqueue (read open) "/test-ro",`)
   541  }
   542  
   543  func (s *PosixMQInterfaceSuite) TestReadOnlyMQSeccomp(c *C) {
   544  	spec := &seccomp.Specification{}
   545  	err := spec.AddPermanentSlot(s.iface, s.testReadOnlySlotInfo)
   546  	c.Assert(err, IsNil)
   547  	err = spec.AddConnectedPlug(s.iface, s.testReadOnlyPlug, s.testReadOnlySlot)
   548  	c.Assert(err, IsNil)
   549  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   550  
   551  	s.checkSlotSeccompSnippet(c, spec)
   552  
   553  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   554  	c.Check(plugSnippet, testutil.Contains, "mq_open")
   555  	c.Check(plugSnippet, testutil.Contains, "mq_notify")
   556  	c.Check(plugSnippet, testutil.Contains, "mq_timedreceive")
   557  	c.Check(plugSnippet, testutil.Contains, "mq_getsetattr")
   558  	c.Check(plugSnippet, Not(testutil.Contains), "mq_timedsend")
   559  	c.Check(plugSnippet, Not(testutil.Contains), "mq_unlink")
   560  }
   561  
   562  func (s *PosixMQInterfaceSuite) TestPathArrayMQAppArmor(c *C) {
   563  	spec := &apparmor.Specification{}
   564  	err := spec.AddPermanentSlot(s.iface, s.testPathArraySlotInfo)
   565  	c.Assert(err, IsNil)
   566  	err = spec.AddConnectedPlug(s.iface, s.testPathArrayPlug, s.testPathArraySlot)
   567  	c.Assert(err, IsNil)
   568  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   569  
   570  	slotSnippet := spec.SnippetForTag("snap.producer.app")
   571  	c.Check(slotSnippet, testutil.Contains, `  mqueue (open read write create delete) "/test-array-1",
   572    mqueue (open read write create delete) "/test-array-2",
   573    mqueue (open read write create delete) "/test-array-3",
   574  `)
   575  
   576  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   577  	c.Check(plugSnippet, testutil.Contains, `  mqueue (read write open) "/test-array-1",
   578    mqueue (read write open) "/test-array-2",
   579    mqueue (read write open) "/test-array-3",
   580  `)
   581  }
   582  
   583  func (s *PosixMQInterfaceSuite) TestPathArrayMQSeccomp(c *C) {
   584  	spec := &seccomp.Specification{}
   585  	err := spec.AddPermanentSlot(s.iface, s.testPathArraySlotInfo)
   586  	c.Assert(err, IsNil)
   587  	err = spec.AddConnectedPlug(s.iface, s.testPathArrayPlug, s.testPathArraySlot)
   588  	c.Assert(err, IsNil)
   589  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   590  
   591  	s.checkSlotSeccompSnippet(c, spec)
   592  
   593  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   594  	c.Check(plugSnippet, testutil.Contains, "mq_open")
   595  	c.Check(plugSnippet, testutil.Contains, "mq_notify")
   596  	c.Check(plugSnippet, testutil.Contains, "mq_timedreceive")
   597  	c.Check(plugSnippet, testutil.Contains, "mq_timedsend")
   598  	c.Check(plugSnippet, testutil.Contains, "mq_getsetattr")
   599  	c.Check(plugSnippet, Not(testutil.Contains), "mq_unlink")
   600  }
   601  
   602  func (s *PosixMQInterfaceSuite) TestAllPermsMQAppArmor(c *C) {
   603  	spec := &apparmor.Specification{}
   604  	err := spec.AddPermanentSlot(s.iface, s.testAllPermsSlotInfo)
   605  	c.Assert(err, IsNil)
   606  	err = spec.AddConnectedPlug(s.iface, s.testAllPermsPlug, s.testAllPermsSlot)
   607  	c.Assert(err, IsNil)
   608  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   609  
   610  	slotSnippet := spec.SnippetForTag("snap.producer.app")
   611  	c.Check(slotSnippet, testutil.Contains, `mqueue (open read write create delete) "/test-all-perms",`)
   612  
   613  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   614  	c.Check(plugSnippet, testutil.Contains, `mqueue (create delete read write open) "/test-all-perms",`)
   615  }
   616  
   617  func (s *PosixMQInterfaceSuite) TestAllPermsMQSeccomp(c *C) {
   618  	spec := &seccomp.Specification{}
   619  	err := spec.AddPermanentSlot(s.iface, s.testAllPermsSlotInfo)
   620  	c.Assert(err, IsNil)
   621  	err = spec.AddConnectedPlug(s.iface, s.testAllPermsPlug, s.testAllPermsSlot)
   622  	c.Assert(err, IsNil)
   623  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"})
   624  
   625  	s.checkSlotSeccompSnippet(c, spec)
   626  
   627  	plugSnippet := spec.SnippetForTag("snap.consumer.app")
   628  	c.Check(plugSnippet, testutil.Contains, "mq_open")
   629  	c.Check(plugSnippet, testutil.Contains, "mq_unlink")
   630  	c.Check(plugSnippet, testutil.Contains, "mq_getsetattr")
   631  	c.Check(plugSnippet, testutil.Contains, "mq_notify")
   632  	c.Check(plugSnippet, testutil.Contains, "mq_timedreceive")
   633  	c.Check(plugSnippet, testutil.Contains, "mq_timedsend")
   634  }
   635  
   636  func (s *PosixMQInterfaceSuite) TestPathValidationPosixMQ(c *C) {
   637  	spec := &apparmor.Specification{}
   638  	err := spec.AddPermanentSlot(s.iface, s.testInvalidPath1SlotInfo)
   639  	c.Check(err, ErrorMatches,
   640  		`posix-mq "path" attribute must conform to the POSIX message queue name specifications \(see "man mq_overview"\): /../../test-invalid`)
   641  }
   642  
   643  func (s *PosixMQInterfaceSuite) TestPathValidationAppArmorRegex(c *C) {
   644  	spec := &apparmor.Specification{}
   645  	err := spec.AddPermanentSlot(s.iface, s.testInvalidPath2SlotInfo)
   646  	c.Check(err, ErrorMatches, `posix-mq "path" attribute is invalid: /test-invalid-2"\["`)
   647  }
   648  
   649  func (s *PosixMQInterfaceSuite) TestPathStringValidation(c *C) {
   650  	spec := &apparmor.Specification{}
   651  	err := spec.AddPermanentSlot(s.iface, s.testInvalidPath3SlotInfo)
   652  	c.Check(err, ErrorMatches, `snap "producer" has interface "posix-mq" with invalid value type map\[string\]interface {} for "path" attribute: \*\[\]string`)
   653  }
   654  
   655  func (s *PosixMQInterfaceSuite) TestInvalidPerms1(c *C) {
   656  	spec := &apparmor.Specification{}
   657  	// The slot should function correctly here as it receives the full list
   658  	// of built-in permissions, not what's listed in the configuration
   659  	err := spec.AddPermanentSlot(s.iface, s.testInvalidPerms1SlotInfo)
   660  	c.Assert(err, IsNil)
   661  	// The plug should fail to connect as it receives the given list of
   662  	// invalid permissions
   663  	err = spec.AddConnectedPlug(s.iface, s.testInvalidPerms1Plug, s.testInvalidPerms1Slot)
   664  	c.Check(err, ErrorMatches,
   665  		`posix-mq slot permission "break-everything" not valid, must be one of \[open read write create delete\]`)
   666  }
   667  
   668  func (s *PosixMQInterfaceSuite) TestInvalidPerms3(c *C) {
   669  	spec := &apparmor.Specification{}
   670  	err := spec.AddPermanentSlot(s.iface, s.testInvalidPerms3SlotInfo)
   671  	c.Assert(err, IsNil)
   672  	err = spec.AddConnectedPlug(s.iface, s.testInvalidPerms3Plug, s.testInvalidPerms3Slot)
   673  	c.Check(err, ErrorMatches,
   674  		`snap "producer" has interface "posix-mq" with invalid value type \[\]interface {} for "permissions" attribute: \*\[\]string`)
   675  }
   676  
   677  func (s *PosixMQInterfaceSuite) TestName(c *C) {
   678  	c.Assert(s.iface.Name(), Equals, "posix-mq")
   679  }
   680  
   681  func (s *PosixMQInterfaceSuite) TestNoAppArmor(c *C) {
   682  	// Ensure that the interface does not fail if AppArmor is unsupported
   683  	restore := apparmor_sandbox.MockLevel(apparmor_sandbox.Unsupported)
   684  	defer restore()
   685  
   686  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testReadWriteSlotInfo), IsNil)
   687  	c.Check(interfaces.BeforePreparePlug(s.iface, s.testReadWritePlugInfo), IsNil)
   688  }
   689  
   690  func (s *PosixMQInterfaceSuite) TestFeatureDetection(c *C) {
   691  	// Ensure that the interface fails if the mqueue feature is not present
   692  	restore := apparmor_sandbox.MockFeatures([]string{}, nil, []string{}, nil)
   693  	defer restore()
   694  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testReadWriteSlotInfo), ErrorMatches,
   695  		`AppArmor does not support POSIX message queues - cannot setup or connect interfaces`)
   696  }
   697  
   698  func (s *PosixMQInterfaceSuite) checkSlotPosixMQAttr(c *C, slot *snap.SlotInfo) {
   699  	c.Check(slot.Attrs["posix-mq"], Equals, slot.Name)
   700  }
   701  
   702  func (s *PosixMQInterfaceSuite) checkPlugPosixMQAttr(c *C, plug *snap.PlugInfo) {
   703  	c.Check(plug.Attrs["posix-mq"], Equals, plug.Name)
   704  }
   705  
   706  func (s *PosixMQInterfaceSuite) TestSanitizeSlot(c *C) {
   707  	// Ensure that the mqueue feature is detected
   708  	restore := apparmor_sandbox.MockFeatures([]string{}, nil, []string{"mqueue"}, nil)
   709  	defer restore()
   710  
   711  	c.Assert(interfaces.BeforePrepareSlot(s.iface, s.testReadWriteSlotInfo), IsNil)
   712  	s.checkSlotPosixMQAttr(c, s.testReadWriteSlotInfo)
   713  	c.Assert(interfaces.BeforePrepareSlot(s.iface, s.testDefaultPermsSlotInfo), IsNil)
   714  	s.checkSlotPosixMQAttr(c, s.testDefaultPermsSlotInfo)
   715  	c.Assert(interfaces.BeforePrepareSlot(s.iface, s.testReadOnlySlotInfo), IsNil)
   716  	s.checkSlotPosixMQAttr(c, s.testReadOnlySlotInfo)
   717  	c.Assert(interfaces.BeforePrepareSlot(s.iface, s.testAllPermsSlotInfo), IsNil)
   718  	s.checkSlotPosixMQAttr(c, s.testAllPermsSlotInfo)
   719  	c.Assert(interfaces.BeforePrepareSlot(s.iface, s.testPathArraySlotInfo), IsNil)
   720  	s.checkSlotPosixMQAttr(c, s.testPathArraySlotInfo)
   721  	c.Assert(interfaces.BeforePrepareSlot(s.iface, s.testLabelSlotInfo), IsNil)
   722  	c.Check(s.testLabelSlotInfo.Attrs["posix-mq"], Equals, "this-is-a-test-label")
   723  
   724  	// These should return errors due to invalid configuration
   725  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testInvalidPath1SlotInfo), ErrorMatches,
   726  		`posix-mq "path" attribute must conform to the POSIX message queue name specifications \(see "man mq_overview"\): /../../test-invalid`)
   727  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testInvalidPath2SlotInfo), ErrorMatches,
   728  		`posix-mq "path" attribute is invalid: /test-invalid-2"\["`)
   729  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testInvalidPath3SlotInfo), ErrorMatches,
   730  		`snap "producer" has interface "posix-mq" with invalid value type map\[string\]interface {} for "path" attribute: \*\[\]string`)
   731  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testInvalidPath4SlotInfo), ErrorMatches,
   732  		`posix-mq slot requires the "path" attribute`)
   733  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testInvalidPath5SlotInfo), ErrorMatches,
   734  		`posix-mq "path" attribute is not a clean path: "/."`)
   735  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testInvalidPerms1SlotInfo), ErrorMatches,
   736  		`posix-mq slot permission "break-everything" not valid, must be one of \[open read write create delete\]`)
   737  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testInvalidPerms2SlotInfo), ErrorMatches,
   738  		`snap "producer" has interface "posix-mq" with invalid value type string for "permissions" attribute: \*\[\]string`)
   739  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testInvalidLabelSlotInfo), ErrorMatches,
   740  		`posix-mq "posix-mq" attribute must be a string, not \[broken\]`)
   741  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testEmptyPathArraySlotInfo), ErrorMatches,
   742  		`posix-mq slot requires at least one value in the "path" attribute`)
   743  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testEmptyPathSlotInfo), ErrorMatches,
   744  		`posix-mq slot "path" attribute values cannot be empty`)
   745  	c.Check(interfaces.BeforePrepareSlot(s.iface, s.testOneEmptyPathArraySlotInfo), ErrorMatches,
   746  		`posix-mq slot "path" attribute values cannot be empty`)
   747  }
   748  
   749  func (s *PosixMQInterfaceSuite) TestSanitizePlug(c *C) {
   750  	// Ensure that the mqueue feature is detected
   751  	restore := apparmor_sandbox.MockFeatures([]string{}, nil, []string{"mqueue"}, nil)
   752  	defer restore()
   753  
   754  	c.Assert(interfaces.BeforePreparePlug(s.iface, s.testReadWritePlugInfo), IsNil)
   755  	s.checkPlugPosixMQAttr(c, s.testReadWritePlugInfo)
   756  	c.Assert(interfaces.BeforePreparePlug(s.iface, s.testDefaultPermsPlugInfo), IsNil)
   757  	s.checkPlugPosixMQAttr(c, s.testDefaultPermsPlugInfo)
   758  	c.Assert(interfaces.BeforePreparePlug(s.iface, s.testReadOnlyPlugInfo), IsNil)
   759  	s.checkPlugPosixMQAttr(c, s.testReadOnlyPlugInfo)
   760  	c.Assert(interfaces.BeforePreparePlug(s.iface, s.testAllPermsPlugInfo), IsNil)
   761  	s.checkPlugPosixMQAttr(c, s.testAllPermsPlugInfo)
   762  	c.Assert(interfaces.BeforePreparePlug(s.iface, s.testPathArrayPlugInfo), IsNil)
   763  	s.checkPlugPosixMQAttr(c, s.testPathArrayPlugInfo)
   764  	c.Assert(interfaces.BeforePreparePlug(s.iface, s.testInvalidPerms1PlugInfo), IsNil)
   765  	s.checkPlugPosixMQAttr(c, s.testInvalidPerms1PlugInfo)
   766  	c.Assert(interfaces.BeforePreparePlug(s.iface, s.testLabelPlugInfo), IsNil)
   767  	c.Check(s.testLabelPlugInfo.Attrs["posix-mq"], Equals, "this-is-a-test-label")
   768  
   769  	c.Check(interfaces.BeforePreparePlug(s.iface, s.testInvalidLabelPlugInfo), ErrorMatches,
   770  		`posix-mq "posix-mq" attribute must be a string, not \[this-is-a-broken-test-label\]`)
   771  }
   772  
   773  func (s *PosixMQInterfaceSuite) TestInterfaces(c *C) {
   774  	c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface)
   775  }
   776  
   777  func (s *PosixMQInterfaceSuite) TestAutoConnect(c *C) {
   778  	c.Assert(s.iface.AutoConnect(s.testReadWritePlugInfo, s.testReadWriteSlotInfo), Equals, true)
   779  }
   780  
   781  func (s *PosixMQInterfaceSuite) TestStaticInfo(c *C) {
   782  	si := interfaces.StaticInfoOf(s.iface)
   783  	c.Check(si.ImplicitOnCore, Equals, false)
   784  	c.Check(si.ImplicitOnClassic, Equals, false)
   785  	c.Check(si.Summary, Equals, `allows access to POSIX message queues`)
   786  }