github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/interfaces/builtin/fwupd.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2017 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 "path/filepath" 24 "strings" 25 26 "github.com/snapcore/snapd/dirs" 27 "github.com/snapcore/snapd/interfaces" 28 "github.com/snapcore/snapd/interfaces/apparmor" 29 "github.com/snapcore/snapd/interfaces/dbus" 30 "github.com/snapcore/snapd/interfaces/mount" 31 "github.com/snapcore/snapd/interfaces/seccomp" 32 "github.com/snapcore/snapd/osutil" 33 "github.com/snapcore/snapd/snap" 34 ) 35 36 const fwupdSummary = `allows operating as the fwupd service` 37 38 const fwupdBaseDeclarationSlots = ` 39 fwupd: 40 allow-installation: 41 slot-snap-type: 42 - app 43 - core 44 deny-connection: true 45 deny-auto-connection: true 46 ` 47 48 const fwupdPermanentSlotAppArmor = ` 49 # Description: Allow operating as the fwupd service. This gives privileged 50 # access to the system. 51 52 # Allow read/write access for old efivars sysfs interface 53 capability sys_admin, 54 # Allow libfwup to access efivarfs with immutable flag 55 capability linux_immutable, 56 57 # For udev 58 network netlink raw, 59 60 # File accesses 61 # Allow access for EFI System Resource Table in the UEFI 2.5+ specification 62 /sys/firmware/efi/esrt/entries/ r, 63 /sys/firmware/efi/esrt/entries/** r, 64 65 # Allow fwupd to access system information 66 /sys/devices/virtual/dmi/id/product_name r, 67 /sys/devices/virtual/dmi/id/sys_vendor r, 68 69 # Allow read/write access for efivarfs filesystem 70 /sys/firmware/efi/efivars/ r, 71 /sys/firmware/efi/efivars/** rw, 72 73 # Allow write access for efi firmware updater 74 /boot/efi/{,**/} r, 75 /boot/efi/EFI/ubuntu/fwupd*.efi* rw, 76 /boot/efi/EFI/ubuntu/fw/** rw, 77 78 # Allow access from efivar library 79 owner @{PROC}/@{pid}/mounts r, 80 /sys/devices/{pci*,platform}/**/block/**/partition r, 81 # Introspect the block devices to get partition guid and size information 82 /run/udev/data/b[0-9]*:[0-9]* r, 83 84 # Allow access UEFI firmware platform size 85 /sys/firmware/efi/ r, 86 /sys/firmware/efi/fw_platform_size r, 87 88 # DBus accesses 89 #include <abstractions/dbus-strict> 90 dbus (send) 91 bus=system 92 path=/org/freedesktop/DBus 93 interface=org.freedesktop.DBus 94 member={Request,Release}Name 95 peer=(name=org.freedesktop.DBus), 96 97 dbus (send) 98 bus=system 99 path=/org/freedesktop/DBus 100 interface=org.freedesktop.DBus 101 member=GetConnectionUnixUser 102 peer=(label=unconfined), 103 104 # Allow binding the service to the requested connection name 105 dbus (bind) 106 bus=system 107 name="org.freedesktop.fwupd", 108 ` 109 110 const fwupdConnectedPlugAppArmor = ` 111 # Description: Allow using fwupd service. This gives # privileged access to the 112 # fwupd service. 113 114 #Can access the network 115 #include <abstractions/nameservice> 116 #include <abstractions/ssl_certs> 117 /run/systemd/resolve/stub-resolv.conf r, 118 119 # DBus accesses 120 #include <abstractions/dbus-strict> 121 122 # systemd-resolved (not yet included in nameservice abstraction) 123 # 124 # Allow access to the safe members of the systemd-resolved D-Bus API: 125 # 126 # https://www.freedesktop.org/wiki/Software/systemd/resolved/ 127 # 128 # This API may be used directly over the D-Bus system bus or it may be used 129 # indirectly via the nss-resolve plugin: 130 # 131 # https://www.freedesktop.org/software/systemd/man/nss-resolve.html 132 # 133 dbus send 134 bus=system 135 path="/org/freedesktop/resolve1" 136 interface="org.freedesktop.resolve1.Manager" 137 member="Resolve{Address,Hostname,Record,Service}" 138 peer=(name="org.freedesktop.resolve1"), 139 140 # Allow access to fwupd service 141 dbus (receive, send) 142 bus=system 143 path=/ 144 interface=org.freedesktop.fwupd 145 peer=(label=###SLOT_SECURITY_TAGS###), 146 147 dbus (receive, send) 148 bus=system 149 path=/ 150 interface=org.freedesktop.DBus.Properties 151 peer=(label=###SLOT_SECURITY_TAGS###), 152 153 # Allow clients to introspect the service on non-classic (due to the path, 154 # allowing on classic would reveal too much for unconfined) 155 dbus (send) 156 bus=system 157 path=/ 158 interface=org.freedesktop.DBus.Introspectable 159 member=Introspect 160 peer=(label=###SLOT_SECURITY_TAGS###), 161 ` 162 163 const fwupdConnectedSlotAppArmor = ` 164 # Description: Allow firmware update using fwupd service. This gives privileged 165 # access to the fwupd service. 166 167 # Allow traffic to/from org.freedesktop.DBus for fwupd service 168 dbus (receive, send) 169 bus=system 170 path=/ 171 interface=org.freedesktop.DBus.** 172 peer=(label=###PLUG_SECURITY_TAGS###), 173 174 dbus (receive, send) 175 bus=system 176 path=/org/freedesktop/fwupd{,/**} 177 interface=org.freedesktop.DBus.** 178 peer=(label=###PLUG_SECURITY_TAGS###), 179 180 # Allow traffic to/from fwupd interface with any method 181 dbus (receive, send) 182 bus=system 183 path=/ 184 interface=org.freedesktop.fwupd 185 peer=(label=###PLUG_SECURITY_TAGS###), 186 187 dbus (receive, send) 188 bus=system 189 path=/org/freedesktop/fwupd{,/**} 190 interface=org.freedesktop.fwupd 191 peer=(label=###PLUG_SECURITY_TAGS###), 192 ` 193 194 const fwupdPermanentSlotDBus = ` 195 <policy user="root"> 196 <allow own="org.freedesktop.fwupd"/> 197 <allow send_destination="org.freedesktop.fwupd" send_interface="org.freedesktop.fwupd"/> 198 <allow send_destination="org.freedesktop.fwupd" send_interface="org.freedesktop.DBus.Properties"/> 199 <allow send_destination="org.freedesktop.fwupd" send_interface="org.freedesktop.DBus.Introspectable"/> 200 <allow send_destination="org.freedesktop.fwupd" send_interface="org.freedesktop.DBus.Peer"/> 201 </policy> 202 <policy context="default"> 203 <deny own="org.freedesktop.fwupd"/> 204 <deny send_destination="org.freedesktop.fwupd" send_interface="org.freedesktop.fwupd"/> 205 </policy> 206 ` 207 208 const fwupdPermanentSlotSecComp = ` 209 # Description: Allow operating as the fwupd service. This gives privileged 210 # access to the system. 211 # Can communicate with DBus system service 212 bind 213 # for udev 214 socket AF_NETLINK - NETLINK_KOBJECT_UEVENT 215 ` 216 const fwupdConnectedPlugSecComp = ` 217 # Description: Allow using fwupd service. Reserved because this gives 218 # privileged access to the fwupd service. 219 bind 220 ` 221 222 // fwupdInterface type 223 type fwupdInterface struct{} 224 225 // Name of the fwupdInterface 226 func (iface *fwupdInterface) Name() string { 227 return "fwupd" 228 } 229 230 func (iface *fwupdInterface) StaticInfo() interfaces.StaticInfo { 231 return interfaces.StaticInfo{ 232 Summary: fwupdSummary, 233 ImplicitOnClassic: true, 234 BaseDeclarationSlots: fwupdBaseDeclarationSlots, 235 } 236 } 237 238 func (iface *fwupdInterface) DBusPermanentSlot(spec *dbus.Specification, slot *snap.SlotInfo) error { 239 if !implicitSystemPermanentSlot(slot) { 240 spec.AddSnippet(fwupdPermanentSlotDBus) 241 } 242 return nil 243 } 244 245 func (iface *fwupdInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 246 old := "###SLOT_SECURITY_TAGS###" 247 var new string 248 if implicitSystemConnectedSlot(slot) { 249 new = "unconfined" 250 } else { 251 new = slotAppLabelExpr(slot) 252 } 253 snippet := strings.Replace(fwupdConnectedPlugAppArmor, old, new, -1) 254 spec.AddSnippet(snippet) 255 return nil 256 } 257 258 func (iface *fwupdInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error { 259 // Only apply slot snippet when running as application snap on 260 // classic, slot side can be system or application 261 if !implicitSystemPermanentSlot(slot) { 262 spec.AddSnippet(fwupdPermanentSlotAppArmor) 263 264 // Allow mounting boot partition to snap-update-ns 265 emit := spec.AddUpdateNSf 266 target := "/boot" 267 source := "/var/lib/snapd/hostfs" + target 268 emit(" # Read-write access to %s\n", target) 269 emit(" mount options=(rbind) %s/ -> %s/,\n", source, target) 270 emit(" umount %s/,\n\n", target) 271 } 272 return nil 273 } 274 275 func (iface *fwupdInterface) MountPermanentSlot(spec *mount.Specification, slot *snap.SlotInfo) error { 276 if !implicitSystemPermanentSlot(slot) { 277 dir := filepath.Join(dirs.GlobalRootDir, "/boot") 278 if osutil.IsDirectory(dir) { 279 spec.AddMountEntry(osutil.MountEntry{ 280 Name: "/var/lib/snapd/hostfs" + dir, 281 Dir: dirs.StripRootDir(dir), 282 Options: []string{"rbind", "rw"}, 283 }) 284 } 285 } 286 return nil 287 } 288 289 func (iface *fwupdInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 290 if !implicitSystemConnectedSlot(slot) { 291 old := "###PLUG_SECURITY_TAGS###" 292 new := plugAppLabelExpr(plug) 293 snippet := strings.Replace(fwupdConnectedSlotAppArmor, old, new, -1) 294 spec.AddSnippet(snippet) 295 } 296 return nil 297 } 298 299 func (iface *fwupdInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 300 spec.AddSnippet(fwupdConnectedPlugSecComp) 301 return nil 302 } 303 304 func (iface *fwupdInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *snap.SlotInfo) error { 305 if !implicitSystemPermanentSlot(slot) { 306 spec.AddSnippet(fwupdPermanentSlotSecComp) 307 } 308 return nil 309 } 310 311 func (iface *fwupdInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 312 // allow what declarations allowed 313 return true 314 } 315 316 func init() { 317 registerIface(&fwupdInterface{}) 318 }