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