gitee.com/mysnapcore/mysnapd@v0.1.0/interfaces/builtin/netlink_driver_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2021 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 "gitee.com/mysnapcore/mysnapd/snap" 30 "gitee.com/mysnapcore/mysnapd/snap/snaptest" 31 "gitee.com/mysnapcore/mysnapd/testutil" 32 ) 33 34 type NetlinkDriverInterfaceSuite struct { 35 testutil.BaseTest 36 37 iface interfaces.Interface 38 39 // slots from gadget 40 gadgetNetlinkSlotInfo *snap.SlotInfo 41 gadgetNetlinkSlot *interfaces.ConnectedSlot 42 gadgetMissingNumberSlotInfo *snap.SlotInfo 43 gadgetMissingNumberSlot *interfaces.ConnectedSlot 44 gadgetMissingNameSlotInfo *snap.SlotInfo 45 gadgetMissingNameSlot *interfaces.ConnectedSlot 46 gadgetBadNumberSlotInfo *snap.SlotInfo 47 gadgetBadNumberSlot *interfaces.ConnectedSlot 48 gadgetBadNameSlotInfo *snap.SlotInfo 49 gadgetBadNameSlot *interfaces.ConnectedSlot 50 gadgetBadNameStringSlotInfo *snap.SlotInfo 51 gadgetBadNameStringSlot *interfaces.ConnectedSlot 52 53 // slot from core 54 osNetlinkSlotInfo *snap.SlotInfo 55 osNetlinkSlot *interfaces.ConnectedSlot 56 57 // plugs from app 58 appToGadgetPlugDriverInfo *snap.PlugInfo 59 appToGadgetPlugDriver *interfaces.ConnectedPlug 60 appToCorePlugDriverInfo *snap.PlugInfo 61 appToCorePlugDriver *interfaces.ConnectedPlug 62 appMissingFamilyNamePlugDriverInfo *snap.PlugInfo 63 appMissingFamilyNamePlugDriver *interfaces.ConnectedPlug 64 appBadFamilyNamePlugDriverInfo *snap.PlugInfo 65 appBadFamilyNamePlugDriver *interfaces.ConnectedPlug 66 appBadFamilyNameStringPlugDriverInfo *snap.PlugInfo 67 appBadFamilyNameStringPlugDriver *interfaces.ConnectedPlug 68 } 69 70 var _ = Suite(&NetlinkDriverInterfaceSuite{ 71 iface: builtin.MustInterface("netlink-driver"), 72 }) 73 74 func (s *NetlinkDriverInterfaceSuite) SetUpTest(c *C) { 75 gadgetInfo := snaptest.MockInfo(c, ` 76 name: my-device 77 version: 0 78 type: gadget 79 slots: 80 my-driver: 81 interface: netlink-driver 82 family: 100 83 family-name: foo-driver 84 missing-number: 85 interface: netlink-driver 86 family-name: missing-number 87 missing-name: 88 interface: netlink-driver 89 family: 400 90 bad-number: 91 interface: netlink-driver 92 family: one-hundred 93 family-name: foo-driver 94 bad-family-name: 95 interface: netlink-driver 96 family: 100 97 family-name: foo--------- 98 bad-family-name-string: 99 interface: netlink-driver 100 family: 100 101 family-name: 12123323443432 102 `, nil) 103 s.gadgetNetlinkSlotInfo = gadgetInfo.Slots["my-driver"] 104 s.gadgetNetlinkSlot = interfaces.NewConnectedSlot(s.gadgetNetlinkSlotInfo, nil, nil) 105 s.gadgetMissingNumberSlotInfo = gadgetInfo.Slots["missing-number"] 106 s.gadgetMissingNumberSlot = interfaces.NewConnectedSlot(s.gadgetMissingNumberSlotInfo, nil, nil) 107 s.gadgetMissingNameSlotInfo = gadgetInfo.Slots["missing-name"] 108 s.gadgetMissingNameSlot = interfaces.NewConnectedSlot(s.gadgetMissingNameSlotInfo, nil, nil) 109 s.gadgetBadNumberSlotInfo = gadgetInfo.Slots["bad-number"] 110 s.gadgetBadNumberSlot = interfaces.NewConnectedSlot(s.gadgetBadNumberSlotInfo, nil, nil) 111 s.gadgetBadNameSlotInfo = gadgetInfo.Slots["bad-family-name"] 112 s.gadgetBadNameSlot = interfaces.NewConnectedSlot(s.gadgetBadNameSlotInfo, nil, nil) 113 s.gadgetBadNameStringSlotInfo = gadgetInfo.Slots["bad-family-name-string"] 114 s.gadgetBadNameStringSlot = interfaces.NewConnectedSlot(s.gadgetBadNameStringSlotInfo, nil, nil) 115 116 osInfo := snaptest.MockInfo(c, ` 117 name: my-core 118 version: 0 119 type: os 120 slots: 121 my-driver: 122 interface: netlink-driver 123 family: 777 124 family-name: seven-7-seven 125 `, nil) 126 s.osNetlinkSlotInfo = osInfo.Slots["my-driver"] 127 s.osNetlinkSlot = interfaces.NewConnectedSlot(s.osNetlinkSlotInfo, nil, nil) 128 129 // Snap Consumers 130 consumingSnapInfo := snaptest.MockInfo(c, ` 131 name: client-snap 132 version: 0 133 plugs: 134 plug-for-netlink-driver-777: 135 interface: netlink-driver 136 family-name: seven-7-seven 137 plug-for-netlink-driver-foo: 138 interface: netlink-driver 139 family-name: foo-driver 140 missing-family-name: 141 interface: netlink-driver 142 invalid-family-name: 143 interface: netlink-driver 144 family-name: ---foo----- 145 invalid-family-name-string: 146 interface: netlink-driver 147 family-name: 1213123 148 apps: 149 netlink-test: 150 command: bin/foo.sh 151 plugs: 152 - plug-for-netlink-driver-777 153 - plug-for-netlink-driver-foo 154 `, nil) 155 s.appToCorePlugDriverInfo = consumingSnapInfo.Plugs["plug-for-netlink-driver-777"] 156 s.appToCorePlugDriver = interfaces.NewConnectedPlug(s.appToCorePlugDriverInfo, nil, nil) 157 158 s.appToGadgetPlugDriverInfo = consumingSnapInfo.Plugs["plug-for-netlink-driver-foo"] 159 s.appToGadgetPlugDriver = interfaces.NewConnectedPlug(s.appToCorePlugDriverInfo, nil, nil) 160 161 s.appBadFamilyNamePlugDriverInfo = consumingSnapInfo.Plugs["invalid-family-name"] 162 s.appBadFamilyNamePlugDriver = interfaces.NewConnectedPlug(s.appBadFamilyNamePlugDriverInfo, nil, nil) 163 164 s.appBadFamilyNameStringPlugDriverInfo = consumingSnapInfo.Plugs["invalid-family-name-string"] 165 s.appBadFamilyNameStringPlugDriver = interfaces.NewConnectedPlug(s.appBadFamilyNameStringPlugDriverInfo, nil, nil) 166 167 s.appMissingFamilyNamePlugDriverInfo = consumingSnapInfo.Plugs["missing-family-name"] 168 s.appMissingFamilyNamePlugDriver = interfaces.NewConnectedPlug(s.appMissingFamilyNamePlugDriverInfo, nil, nil) 169 } 170 171 func (s *NetlinkDriverInterfaceSuite) TestStaticInfo(c *C) { 172 si := interfaces.StaticInfoOf(s.iface) 173 c.Assert(si.ImplicitOnCore, Equals, false) 174 c.Assert(si.ImplicitOnClassic, Equals, false) 175 c.Assert(si.Summary, Equals, "allows operating a kernel driver module exposing itself via a netlink protocol family") 176 c.Assert(si.BaseDeclarationSlots, testutil.Contains, "netlink-driver") 177 } 178 179 func (s *NetlinkDriverInterfaceSuite) TestAutoConnect(c *C) { 180 // ensure the plug definitions in the YAML didn't change 181 c.Check(s.appToCorePlugDriverInfo.Attrs["family-name"], Equals, "seven-7-seven") 182 c.Check(s.osNetlinkSlotInfo.Attrs["family-name"], Equals, "seven-7-seven") 183 184 // ensure the plug definitions in the YAML didn't change 185 c.Check(s.appToGadgetPlugDriverInfo.Attrs["family-name"], Equals, "foo-driver") 186 c.Check(s.gadgetNetlinkSlotInfo.Attrs["family-name"], Equals, "foo-driver") 187 188 // with matching family-name attributes, it works 189 c.Check(s.iface.AutoConnect(s.appToCorePlugDriverInfo, s.osNetlinkSlotInfo), Equals, true) 190 c.Check(s.iface.AutoConnect(s.appToGadgetPlugDriverInfo, s.gadgetNetlinkSlotInfo), Equals, true) 191 192 // with different family-name attributes, it doesn't 193 c.Check(s.iface.AutoConnect(s.appToCorePlugDriverInfo, s.gadgetNetlinkSlotInfo), Equals, false) 194 c.Check(s.iface.AutoConnect(s.appToGadgetPlugDriverInfo, s.osNetlinkSlotInfo), Equals, false) 195 } 196 197 func (s *NetlinkDriverInterfaceSuite) TestInterfaces(c *C) { 198 c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface) 199 } 200 201 func (s *NetlinkDriverInterfaceSuite) TestSanitizeSlotGadgetSnap(c *C) { 202 // netlink slot on gadget accepted 203 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.gadgetNetlinkSlotInfo), IsNil) 204 205 // slots without number attribute are rejected 206 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.gadgetMissingNumberSlotInfo), ErrorMatches, 207 "netlink-driver slot must have a family number attribute") 208 209 // slots with number attribute that isnt a number 210 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.gadgetBadNumberSlotInfo), ErrorMatches, 211 "netlink-driver slot family number attribute must be an int") 212 213 // slots without family-name 214 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.gadgetMissingNameSlotInfo), ErrorMatches, 215 "netlink-driver slot must have a family-name attribute") 216 217 // slots with family-name attribute that isn't a string 218 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.gadgetBadNameStringSlotInfo), ErrorMatches, 219 `netlink-driver slot family-name attribute must be a string`) 220 221 // slots with bad family-name 222 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.gadgetBadNameSlotInfo), ErrorMatches, 223 `netlink-driver slot family-name "foo---------" is invalid`) 224 } 225 226 func (s *NetlinkDriverInterfaceSuite) TestSanitizePlugAppSnap(c *C) { 227 // netlink plug on app accepted 228 c.Assert(interfaces.BeforePreparePlug(s.iface, s.appToCorePlugDriverInfo), IsNil) 229 230 // plugs without family-name are rejected 231 c.Assert(interfaces.BeforePreparePlug(s.iface, s.appMissingFamilyNamePlugDriverInfo), ErrorMatches, 232 "netlink-driver plug must have a family-name attribute") 233 234 // slots with family-name attribute that isn't a string 235 c.Assert(interfaces.BeforePreparePlug(s.iface, s.appBadFamilyNameStringPlugDriverInfo), ErrorMatches, 236 `netlink-driver plug family-name attribute must be a string`) 237 238 // slots with bad family-name 239 c.Assert(interfaces.BeforePreparePlug(s.iface, s.appBadFamilyNamePlugDriverInfo), ErrorMatches, 240 `netlink-driver plug family-name "---foo-----" is invalid`) 241 } 242 243 func (s *NetlinkDriverInterfaceSuite) TestSanitizeSlotOsSnap(c *C) { 244 // netlink slot on OS accepted 245 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.osNetlinkSlotInfo), IsNil) 246 } 247 248 func (s *NetlinkDriverInterfaceSuite) TestSanitizePlug(c *C) { 249 c.Assert(interfaces.BeforePreparePlug(s.iface, s.appToCorePlugDriverInfo), IsNil) 250 c.Assert(interfaces.BeforePreparePlug(s.iface, s.appToGadgetPlugDriverInfo), IsNil) 251 } 252 253 func (s *NetlinkDriverInterfaceSuite) TestApparmorConnectedPlug(c *C) { 254 spec := &apparmor.Specification{} 255 c.Assert(spec.AddConnectedPlug(s.iface, s.appToCorePlugDriver, s.gadgetNetlinkSlot), IsNil) 256 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.client-snap.netlink-test"}) 257 c.Assert(spec.SnippetForTag("snap.client-snap.netlink-test"), testutil.Contains, `network netlink,`) 258 } 259 260 func (s *NetlinkDriverInterfaceSuite) TestSecCompConnectedPlug(c *C) { 261 spec := &seccomp.Specification{} 262 c.Assert(spec.AddConnectedPlug(s.iface, s.appToCorePlugDriver, s.osNetlinkSlot), IsNil) 263 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.client-snap.netlink-test"}) 264 c.Assert(spec.SnippetForTag("snap.client-snap.netlink-test"), testutil.Contains, `socket AF_NETLINK - 777`) 265 266 spec2 := &seccomp.Specification{} 267 c.Assert(spec2.AddConnectedPlug(s.iface, s.appToGadgetPlugDriver, s.gadgetNetlinkSlot), IsNil) 268 c.Assert(spec2.SecurityTags(), DeepEquals, []string{"snap.client-snap.netlink-test"}) 269 c.Assert(spec2.SnippetForTag("snap.client-snap.netlink-test"), testutil.Contains, `socket AF_NETLINK - 100`) 270 }