github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/interfaces/builtin/browser_support.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 "fmt" 24 25 "github.com/snapcore/snapd/interfaces" 26 "github.com/snapcore/snapd/interfaces/apparmor" 27 "github.com/snapcore/snapd/interfaces/seccomp" 28 "github.com/snapcore/snapd/snap" 29 ) 30 31 const browserSupportSummary = `allows access to various APIs needed by modern web browsers` 32 33 const browserSupportBaseDeclarationSlots = ` 34 browser-support: 35 allow-installation: 36 slot-snap-type: 37 - core 38 deny-connection: 39 plug-attributes: 40 allow-sandbox: true 41 deny-auto-connection: 42 plug-attributes: 43 allow-sandbox: true 44 ` 45 46 const browserSupportConnectedPlugAppArmor = ` 47 # Description: Can access various APIs needed by modern browsers (eg, Google 48 # Chrome/Chromium and Mozilla) and file paths they expect. This interface is 49 # transitional and is only in place while upstream's work to change their paths 50 # and snappy is updated to properly mediate the APIs. 51 52 # This allows raising the OOM score of other processes owned by the user. 53 owner @{PROC}/@{pid}/oom_score_adj rw, 54 55 # Chrome/Chromium should be fixed to honor TMPDIR or the snap packaging 56 # adjusted to use LD_PRELOAD technique from LP: #1577514 57 /var/tmp/ r, 58 owner /var/tmp/etilqs_* rw, 59 60 # Chrome/Chromium should be modified to use snap.$SNAP_INSTANCE_NAME.* or 61 # the snap packaging adjusted to use LD_PRELOAD technique from LP: #1577514 62 owner /{dev,run}/shm/{,.}org.chromium.* mrw, 63 owner /{dev,run}/shm/{,.}com.google.Chrome.* mrw, 64 owner /{dev,run}/shm/.io.nwjs.* mrw, 65 66 # Chrome's Singleton API sometimes causes an ouid/fsuid mismatch denial, so 67 # for now, allow non-owner read on the singleton socket (LP: #1731012). See 68 # https://forum.snapcraft.io/t/electron-snap-killed-when-using-app-makesingleinstance-api/2667/20 69 # parallel-installs: $XDG_RUNTIME_DIR is not remapped, need to use SNAP_INSTANCE_NAME 70 /run/user/[0-9]*/snap.@{SNAP_INSTANCE_NAME}/{,.}org.chromium.*/SS r, 71 /run/user/[0-9]*/snap.@{SNAP_INSTANCE_NAME}/{,.}com.google.Chrome.*/SS r, 72 73 # Allow reading platform files 74 /run/udev/data/+platform:* r, 75 76 # miscellaneous accesses 77 @{PROC}/vmstat r, 78 79 # Chromium content api sometimes queries about huge pages. Allow status of 80 # hugepages and transparent_hugepage, but not the pages themselves. 81 /sys/kernel/mm/{hugepages,transparent_hugepage}/{,**} r, 82 83 # Chromium content api in gnome-shell reads this 84 /etc/opt/chrome/{,**} r, 85 /etc/chromium/{,**} r, 86 87 # Chrome/Chromium should be adjusted to not use gconf. It is only used with 88 # legacy systems that don't have snapd 89 deny dbus (send) 90 bus=session 91 interface="org.gnome.GConf.Server", 92 93 # webbrowser-app/webapp-container tries to read this file to determine if it is 94 # confined or not, so explicitly deny to avoid noise in the logs. 95 deny @{PROC}/@{pid}/attr/{,apparmor/}current r, 96 97 # This is an information leak but disallowing it leads to developer confusion 98 # when using the chromium content api file chooser due to a (harmless) glib 99 # warning and the noisy AppArmor denial. 100 owner @{PROC}/@{pid}/mounts r, 101 owner @{PROC}/@{pid}/mountinfo r, 102 103 # Since snapd still uses SECCOMP_RET_KILL, we have added a workaround rule to 104 # allow mknod on character devices since chromium unconditionally performs 105 # a mknod() to create the /dev/nvidiactl device, regardless of if it exists or 106 # not or if the process has CAP_MKNOD or not. Since we don't want to actually 107 # grant the ability to create character devices, explicitly deny the 108 # capability. When snapd uses SECCOMP_RET_ERRNO, we can remove this rule. 109 # https://forum.snapcraft.io/t/call-for-testing-chromium-62-0-3202-62/2569/46 110 deny capability mknod, 111 ` 112 113 const browserSupportConnectedPlugAppArmorWithSandbox = ` 114 # TODO: should this be somewhere else? 115 /etc/mailcap r, 116 117 # While /usr/share/applications comes from the base runtime of the snap, it 118 # has some things that snaps actually need, so allow access to those and deny 119 # access to the others. This is duplicated from desktop for compatibility with 120 # existing snaps. 121 /usr/share/applications/ r, 122 /usr/share/applications/mimeapps.list r, 123 /usr/share/applications/xdg-open.desktop r, 124 # silence noisy denials from desktop files in core* snaps that aren't usable by 125 # snaps 126 deny /usr/share/applications/python*.desktop r, 127 deny /usr/share/applications/vim.desktop r, 128 deny /usr/share/applications/snap-handle-link.desktop r, # core16 129 130 # Chromium content api unfortunately needs these for normal operation 131 owner @{PROC}/@{pid}/fd/[0-9]* w, 132 133 # Various files in /run/udev/data needed by Chrome Settings. Leaks device 134 # information. 135 # input 136 /run/udev/data/c1:[0-9]* r, # /dev/psaux 137 /run/udev/data/c10:[0-9]* r, # /dev/adbmouse 138 /run/udev/data/c13:[0-9]* r, # /dev/input/* 139 /run/udev/data/c180:[0-9]* r, # /dev/vrbuttons 140 /run/udev/data/c4:[0-9]* r, # /dev/tty*, /dev/ttyS* 141 /run/udev/data/c5:[0-9]* r, # /dev/tty, /dev/console, etc 142 /run/udev/data/c7:[0-9]* r, # /dev/vcs* 143 /run/udev/data/+hid:* r, 144 /run/udev/data/+input:input[0-9]* r, 145 146 # screen 147 /run/udev/data/c29:[0-9]* r, # /dev/fb* 148 /run/udev/data/+backlight:* r, 149 /run/udev/data/+leds:* r, 150 151 # sound 152 /run/udev/data/c116:[0-9]* r, # alsa 153 /run/udev/data/+sound:card[0-9]* r, 154 155 # miscellaneous 156 /run/udev/data/c108:[0-9]* r, # /dev/ppp 157 /run/udev/data/c189:[0-9]* r, # USB serial converters 158 /run/udev/data/c89:[0-9]* r, # /dev/i2c-* 159 /run/udev/data/c81:[0-9]* r, # video4linux (/dev/video*, etc) 160 /run/udev/data/c202:[0-9]* r, # /dev/cpu/*/msr 161 /run/udev/data/c203:[0-9]* r, # /dev/cuse 162 /run/udev/data/+acpi:* r, 163 /run/udev/data/+hwmon:hwmon[0-9]* r, 164 /run/udev/data/+i2c:* r, 165 /sys/devices/**/bConfigurationValue r, 166 /sys/devices/**/descriptors r, 167 /sys/devices/**/manufacturer r, 168 /sys/devices/**/product r, 169 /sys/devices/**/revision r, 170 /sys/devices/**/serial r, 171 /sys/devices/**/vendor r, 172 /sys/devices/system/node/node[0-9]*/meminfo r, 173 174 # Allow getting the manufacturer and model of the 175 # computer where Chrome/chromium is currently running. 176 # This is going to be used by the upcoming Hardware Platform 177 # extension API. 178 # https://chromium.googlesource.com/chromium/src.git/+/84618eee98fdf7548905e883e63e4f693800fcfa 179 /sys/devices/virtual/dmi/id/product_name r, 180 /sys/devices/virtual/dmi/id/sys_vendor r, 181 182 # Chromium content api tries to read these. It is an information disclosure 183 # since these contain the names of snaps. Chromium operates fine without the 184 # access so just block it. 185 deny /sys/devices/virtual/block/loop[0-9]*/loop/backing_file r, 186 deny /sys/devices/virtual/block/dm-[0-9]*/dm/name r, 187 188 # networking 189 /run/udev/data/n[0-9]* r, 190 /run/udev/data/+bluetooth:hci[0-9]* r, 191 /run/udev/data/+rfkill:rfkill[0-9]* r, 192 /run/udev/data/c241:[0-9]* r, # /dev/vhost-vsock 193 194 # storage 195 /run/udev/data/b1:[0-9]* r, # /dev/ram* 196 /run/udev/data/b7:[0-9]* r, # /dev/loop* 197 /run/udev/data/b8:[0-9]* r, # /dev/sd* 198 /run/udev/data/b11:[0-9]* r, # /dev/scd* and sr* 199 /run/udev/data/b230:[0-9]* r, # /dev/zvol* 200 /run/udev/data/c21:[0-9]* r, # /dev/sg* 201 /run/udev/data/+usb:[0-9]* r, 202 203 # experimental 204 /run/udev/data/b252:[0-9]* r, 205 /run/udev/data/b253:[0-9]* r, 206 /run/udev/data/b259:[0-9]* r, 207 /run/udev/data/c24[0-9]:[0-9]* r, 208 /run/udev/data/c25[0-4]:[0-9]* r, 209 210 /sys/bus/**/devices/ r, 211 212 # Google Cloud Print 213 unix (bind) 214 type=stream 215 addr="@[0-9A-F]*._service_*", 216 217 # Policy needed only when using the chrome/chromium setuid sandbox 218 capability sys_ptrace, 219 ptrace (trace) peer=snap.@{SNAP_INSTANCE_NAME}.**, 220 unix (receive, send) peer=(label=snap.@{SNAP_INSTANCE_NAME}.**), 221 222 # If this were going to be allowed to all snaps, then for all the following 223 # rules we would want to wrap in a 'browser_sandbox' profile, but a limitation 224 # in AppArmor profile transitions prevents this. 225 # 226 # @{INSTALL_DIR}/@{SNAP_NAME}/@{SNAP_REVISION}/opt/google/chrome{,-beta,-unstable}/chrome-sandbox cx -> browser_sandbox, 227 # profile browser_sandbox { 228 # ... 229 # # This rule needs to work but generates a parser error 230 # @{INSTALL_DIR}/@{SNAP_NAME}/@{SNAP_REVISION}/opt/google/chrome/chrome px -> snap.@{SNAP_INSTANCE_NAME}.@{SNAP_APP}, 231 # @{INSTALL_DIR}/@{SNAP_INSTANCE_NAME}/@{SNAP_REVISION}/opt/google/chrome/chrome px -> snap.@{SNAP_INSTANCE_NAME}.@{SNAP_APP}, 232 # ... 233 # } 234 235 # Required for dropping into PID namespace. Keep in mind that until the 236 # process drops this capability it can escape confinement, but once it 237 # drops CAP_SYS_ADMIN we are ok. 238 capability sys_admin, 239 240 # All of these are for sanely dropping from root and chrooting 241 capability chown, 242 capability fsetid, 243 capability setgid, 244 capability setuid, 245 capability sys_chroot, 246 247 # User namespace sandbox 248 owner @{PROC}/@{pid}/setgroups rw, 249 owner @{PROC}/@{pid}/uid_map rw, 250 owner @{PROC}/@{pid}/gid_map rw, 251 252 # Webkit uses a particular SHM names # LP: 1578217 253 owner /{dev,run}/shm/WK2SharedMemory.* mrw, 254 255 # Chromium content api on (at least) later versions of Ubuntu just use this 256 owner /{dev,run}/shm/shmfd-* mrw, 257 258 # Clearing the PG_Referenced and ACCESSED/YOUNG bits provides a method to 259 # measure approximately how much memory a process is using via /proc/self/smaps 260 # (man 5 proc). This access allows the snap to clear references for pids from 261 # other snaps and the system, so it is limited to snaps that specify: 262 # allow-sandbox: true. 263 owner @{PROC}/@{pid}/clear_refs w, 264 265 # Allow setting realtime priorities. Clients require RLIMIT_RTTIME in the first 266 # place and client authorization is done via PolicyKit. Note that setrlimit() 267 # is allowed by default seccomp policy but requires 'capability sys_resource', 268 # which we deny be default. 269 # http://git.0pointer.net/rtkit.git/tree/README 270 dbus (send) 271 bus=system 272 path=/org/freedesktop/RealtimeKit1 273 interface=org.freedesktop.DBus.Properties 274 member=Get 275 peer=(name=org.freedesktop.RealtimeKit1, label=unconfined), 276 dbus (send) 277 bus=system 278 path=/org/freedesktop/RealtimeKit1 279 interface=org.freedesktop.RealtimeKit1 280 member=MakeThread{HighPriority,Realtime} 281 peer=(name=org.freedesktop.RealtimeKit1, label=unconfined), 282 ` 283 284 const browserSupportConnectedPlugSecComp = ` 285 # Description: Can access various APIs needed by modern browsers (eg, Google 286 # Chrome/Chromium and Mozilla) and file paths they expect. This interface is 287 # transitional and is only in place while upstream's work to change their paths 288 # and snappy is updated to properly mediate the APIs. 289 290 # for anonymous sockets 291 bind 292 listen 293 accept 294 accept4 295 296 # TODO: fine-tune when seccomp arg filtering available in stable distro 297 # releases 298 setpriority 299 300 # Since snapd still uses SECCOMP_RET_KILL, add a workaround rule to allow mknod 301 # on character devices since chromium unconditionally performs a mknod() to 302 # create the /dev/nvidiactl device, regardless of if it exists or not or if the 303 # process has CAP_MKNOD or not. Since we don't want to actually grant the 304 # ability to create character devices, we added an explicit deny AppArmor rule 305 # for this capability. When snapd uses SECCOMP_RET_ERRNO, we can remove this 306 # rule. 307 # https://forum.snapcraft.io/t/call-for-testing-chromium-62-0-3202-62/2569/46 308 mknod - |S_IFCHR - 309 mknodat - - |S_IFCHR - 310 ` 311 312 const browserSupportConnectedPlugSecCompWithSandbox = ` 313 # Policy needed only when using the chrome/chromium setuid sandbox 314 chroot 315 sched_setscheduler 316 317 # Chromium will attempt to set the affinity of it's renderer threads, primarily 318 # on android, but also on Linux where it is available. See 319 # https://github.com/chromium/chromium/blob/99314be8152e688bafbbf9a615536bdbb289ea87/content/common/android/cpu_affinity.cc#L51 320 sched_setaffinity 321 322 # TODO: fine-tune when seccomp arg filtering available in stable distro 323 # releases 324 setuid 325 setgid 326 327 # Policy needed for Mozilla userns sandbox 328 unshare 329 quotactl 330 331 # The Breakpad crash reporter uses ptrace to read register/memory state 332 # from the crashed process, but it doesn't need to modify any state; see 333 # https://bugzilla.mozilla.org/show_bug.cgi?id=1461848. 334 # 335 # These rules allow that but don't allow ptrace operations that 336 # write registers, which can be used to bypass security; see 337 # https://lkml.org/lkml/2016/5/26/354. 338 ptrace PTRACE_ATTACH 339 ptrace PTRACE_DETACH 340 ptrace PTRACE_GETREGS 341 ptrace PTRACE_GETFPREGS 342 ptrace PTRACE_GETFPXREGS 343 ptrace PTRACE_GETREGSET 344 ptrace PTRACE_PEEKDATA 345 ptrace PTRACE_PEEKUSER 346 ptrace PTRACE_CONT 347 ` 348 349 type browserSupportInterface struct{} 350 351 func (iface *browserSupportInterface) Name() string { 352 return "browser-support" 353 } 354 355 func (iface *browserSupportInterface) StaticInfo() interfaces.StaticInfo { 356 return interfaces.StaticInfo{ 357 Summary: browserSupportSummary, 358 ImplicitOnCore: true, 359 ImplicitOnClassic: true, 360 BaseDeclarationSlots: browserSupportBaseDeclarationSlots, 361 } 362 } 363 364 func (iface *browserSupportInterface) BeforePreparePlug(plug *snap.PlugInfo) error { 365 // It's fine if allow-sandbox isn't specified, but it it is, 366 // it needs to be bool 367 if v, ok := plug.Attrs["allow-sandbox"]; ok { 368 if _, ok = v.(bool); !ok { 369 return fmt.Errorf("browser-support plug requires bool with 'allow-sandbox'") 370 } 371 } 372 373 return nil 374 } 375 376 func (iface *browserSupportInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 377 var allowSandbox bool 378 _ = plug.Attr("allow-sandbox", &allowSandbox) 379 spec.AddSnippet(browserSupportConnectedPlugAppArmor) 380 if allowSandbox { 381 spec.AddSnippet(browserSupportConnectedPlugAppArmorWithSandbox) 382 } else { 383 spec.SetSuppressPtraceTrace() 384 } 385 return nil 386 } 387 388 func (iface *browserSupportInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 389 var allowSandbox bool 390 _ = plug.Attr("allow-sandbox", &allowSandbox) 391 snippet := browserSupportConnectedPlugSecComp 392 if allowSandbox { 393 snippet += browserSupportConnectedPlugSecCompWithSandbox 394 } 395 spec.AddSnippet(snippet) 396 return nil 397 } 398 399 func (iface *browserSupportInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 400 return true 401 } 402 403 func init() { 404 registerIface(&browserSupportInterface{}) 405 }