github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/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 baseDeclarationPlugs string 53 baseDeclarationSlots string 54 55 connectedPlugAppArmor string 56 connectedPlugSecComp string 57 connectedPlugUDev []string 58 rejectAutoConnectPairs bool 59 60 connectedPlugUpdateNSAppArmor string 61 connectedPlugMount []osutil.MountEntry 62 63 connectedPlugKModModules []string 64 connectedSlotKModModules []string 65 permanentPlugKModModules []string 66 permanentSlotKModModules []string 67 68 usesPtraceTrace bool 69 suppressPtraceTrace bool 70 suppressHomeIx bool 71 controlsDeviceCgroup bool 72 73 serviceSnippets []string 74 } 75 76 // Name returns the interface name. 77 func (iface *commonInterface) Name() string { 78 return iface.name 79 } 80 81 // StaticInfo returns various meta-data about this interface. 82 func (iface *commonInterface) StaticInfo() interfaces.StaticInfo { 83 return interfaces.StaticInfo{ 84 Summary: iface.summary, 85 DocURL: iface.docURL, 86 ImplicitOnCore: iface.implicitOnCore, 87 ImplicitOnClassic: iface.implicitOnClassic, 88 BaseDeclarationPlugs: iface.baseDeclarationPlugs, 89 BaseDeclarationSlots: iface.baseDeclarationSlots, 90 } 91 } 92 93 func (iface *commonInterface) ServicePermanentPlug(plug *snap.PlugInfo) []string { 94 return iface.serviceSnippets 95 } 96 97 func (iface *commonInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 98 if iface.usesPtraceTrace { 99 spec.SetUsesPtraceTrace() 100 } else if iface.suppressPtraceTrace { 101 spec.SetSuppressPtraceTrace() 102 } 103 if iface.suppressHomeIx { 104 spec.SetSuppressHomeIx() 105 } 106 if snippet := iface.connectedPlugAppArmor; snippet != "" { 107 spec.AddSnippet(snippet) 108 } 109 if snippet := iface.connectedPlugUpdateNSAppArmor; snippet != "" { 110 spec.AddUpdateNS(snippet) 111 } 112 return nil 113 } 114 115 // AutoConnect returns whether plug and slot should be implicitly 116 // auto-connected assuming they will be an unambiguous connection 117 // candidate and declaration-based checks allow. 118 // 119 // By default we allow what declarations allowed. 120 func (iface *commonInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 121 return !iface.rejectAutoConnectPairs 122 } 123 124 func (iface *commonInterface) KModConnectedPlug(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 125 for _, m := range iface.connectedPlugKModModules { 126 if err := spec.AddModule(m); err != nil { 127 return err 128 } 129 } 130 return nil 131 } 132 133 func (iface *commonInterface) KModConnectedSlot(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 134 for _, m := range iface.connectedSlotKModModules { 135 if err := spec.AddModule(m); err != nil { 136 return err 137 } 138 } 139 return nil 140 } 141 142 func (iface *commonInterface) MountConnectedPlug(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 143 for _, entry := range iface.connectedPlugMount { 144 if err := spec.AddMountEntry(entry); err != nil { 145 return err 146 } 147 } 148 return nil 149 } 150 151 func (iface *commonInterface) KModPermanentPlug(spec *kmod.Specification, plug *snap.PlugInfo) error { 152 for _, m := range iface.permanentPlugKModModules { 153 if err := spec.AddModule(m); err != nil { 154 return err 155 } 156 } 157 return nil 158 } 159 160 func (iface *commonInterface) KModPermanentSlot(spec *kmod.Specification, slot *snap.SlotInfo) error { 161 for _, m := range iface.permanentSlotKModModules { 162 if err := spec.AddModule(m); err != nil { 163 return err 164 } 165 } 166 return nil 167 } 168 169 func (iface *commonInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 170 if iface.connectedPlugSecComp != "" { 171 spec.AddSnippet(iface.connectedPlugSecComp) 172 } 173 return nil 174 } 175 176 func (iface *commonInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 177 // don't tag devices if the interface controls it's own device cgroup 178 if iface.controlsDeviceCgroup { 179 spec.SetControlsDeviceCgroup() 180 } else { 181 for _, rule := range iface.connectedPlugUDev { 182 spec.TagDevice(rule) 183 } 184 } 185 186 return nil 187 }