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