github.com/ubuntu-core/snappy@v0.0.0-20210827154228-9e584df982bb/interfaces/builtin/common.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2018 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 21 22 import ( 23 "io/ioutil" 24 "path/filepath" 25 26 "github.com/snapcore/snapd/interfaces" 27 "github.com/snapcore/snapd/interfaces/apparmor" 28 "github.com/snapcore/snapd/interfaces/kmod" 29 "github.com/snapcore/snapd/interfaces/mount" 30 "github.com/snapcore/snapd/interfaces/seccomp" 31 "github.com/snapcore/snapd/interfaces/udev" 32 "github.com/snapcore/snapd/osutil" 33 "github.com/snapcore/snapd/snap" 34 ) 35 36 // evalSymlinks is either filepath.EvalSymlinks or a mocked function for 37 // applicable for testing. 38 var evalSymlinks = filepath.EvalSymlinks 39 40 // readDir is either ioutil.ReadDir or a mocked function for applicable for 41 // testing. 42 var readDir = ioutil.ReadDir 43 44 type commonInterface struct { 45 name string 46 summary string 47 docURL string 48 49 implicitOnCore bool 50 implicitOnClassic bool 51 52 affectsPlugOnRefresh bool 53 54 baseDeclarationPlugs string 55 baseDeclarationSlots string 56 57 connectedPlugAppArmor string 58 connectedPlugSecComp string 59 connectedPlugUDev []string 60 rejectAutoConnectPairs bool 61 62 connectedPlugUpdateNSAppArmor string 63 connectedPlugMount []osutil.MountEntry 64 65 connectedPlugKModModules []string 66 connectedSlotKModModules []string 67 permanentPlugKModModules []string 68 permanentSlotKModModules []string 69 70 usesPtraceTrace bool 71 suppressPtraceTrace bool 72 suppressHomeIx bool 73 controlsDeviceCgroup bool 74 75 serviceSnippets []string 76 } 77 78 // Name returns the interface name. 79 func (iface *commonInterface) Name() string { 80 return iface.name 81 } 82 83 // StaticInfo returns various meta-data about this interface. 84 func (iface *commonInterface) StaticInfo() interfaces.StaticInfo { 85 return interfaces.StaticInfo{ 86 Summary: iface.summary, 87 DocURL: iface.docURL, 88 ImplicitOnCore: iface.implicitOnCore, 89 ImplicitOnClassic: iface.implicitOnClassic, 90 BaseDeclarationPlugs: iface.baseDeclarationPlugs, 91 BaseDeclarationSlots: iface.baseDeclarationSlots, 92 // affects the plug snap because of mount backend 93 AffectsPlugOnRefresh: iface.affectsPlugOnRefresh, 94 } 95 } 96 97 func (iface *commonInterface) ServicePermanentPlug(plug *snap.PlugInfo) []string { 98 return iface.serviceSnippets 99 } 100 101 func (iface *commonInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 102 if iface.usesPtraceTrace { 103 spec.SetUsesPtraceTrace() 104 } else if iface.suppressPtraceTrace { 105 spec.SetSuppressPtraceTrace() 106 } 107 if iface.suppressHomeIx { 108 spec.SetSuppressHomeIx() 109 } 110 if snippet := iface.connectedPlugAppArmor; snippet != "" { 111 spec.AddSnippet(snippet) 112 } 113 if snippet := iface.connectedPlugUpdateNSAppArmor; snippet != "" { 114 spec.AddUpdateNS(snippet) 115 } 116 return nil 117 } 118 119 // AutoConnect returns whether plug and slot should be implicitly 120 // auto-connected assuming they will be an unambiguous connection 121 // candidate and declaration-based checks allow. 122 // 123 // By default we allow what declarations allowed. 124 func (iface *commonInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 125 return !iface.rejectAutoConnectPairs 126 } 127 128 func (iface *commonInterface) KModConnectedPlug(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 129 for _, m := range iface.connectedPlugKModModules { 130 if err := spec.AddModule(m); err != nil { 131 return err 132 } 133 } 134 return nil 135 } 136 137 func (iface *commonInterface) KModConnectedSlot(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 138 for _, m := range iface.connectedSlotKModModules { 139 if err := spec.AddModule(m); err != nil { 140 return err 141 } 142 } 143 return nil 144 } 145 146 func (iface *commonInterface) MountConnectedPlug(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 147 for _, entry := range iface.connectedPlugMount { 148 if err := spec.AddMountEntry(entry); err != nil { 149 return err 150 } 151 } 152 return nil 153 } 154 155 func (iface *commonInterface) KModPermanentPlug(spec *kmod.Specification, plug *snap.PlugInfo) error { 156 for _, m := range iface.permanentPlugKModModules { 157 if err := spec.AddModule(m); err != nil { 158 return err 159 } 160 } 161 return nil 162 } 163 164 func (iface *commonInterface) KModPermanentSlot(spec *kmod.Specification, slot *snap.SlotInfo) error { 165 for _, m := range iface.permanentSlotKModModules { 166 if err := spec.AddModule(m); err != nil { 167 return err 168 } 169 } 170 return nil 171 } 172 173 func (iface *commonInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 174 if iface.connectedPlugSecComp != "" { 175 spec.AddSnippet(iface.connectedPlugSecComp) 176 } 177 return nil 178 } 179 180 func (iface *commonInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 181 // don't tag devices if the interface controls it's own device cgroup 182 if iface.controlsDeviceCgroup { 183 spec.SetControlsDeviceCgroup() 184 } else { 185 for _, rule := range iface.connectedPlugUDev { 186 spec.TagDevice(rule) 187 } 188 } 189 190 return nil 191 }