github.com/rigado/snapd@v2.42.5-go-mod+incompatible/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 in gnome-shell reads this 80 /etc/opt/chrome/{,**} r, 81 /etc/chromium/{,**} r, 82 83 # Chrome/Chromium should be adjusted to not use gconf. It is only used with 84 # legacy systems that don't have snapd 85 deny dbus (send) 86 bus=session 87 interface="org.gnome.GConf.Server", 88 89 # webbrowser-app/webapp-container tries to read this file to determine if it is 90 # confined or not, so explicitly deny to avoid noise in the logs. 91 deny @{PROC}/@{pid}/attr/current r, 92 93 # This is an information leak but disallowing it leads to developer confusion 94 # when using the chromium content api file chooser due to a (harmless) glib 95 # warning and the noisy AppArmor denial. 96 owner @{PROC}/@{pid}/mounts r, 97 owner @{PROC}/@{pid}/mountinfo r, 98 99 # Since snapd still uses SECCOMP_RET_KILL, we have added a workaround rule to 100 # allow mknod on character devices since chromium unconditionally performs 101 # a mknod() to create the /dev/nvidiactl device, regardless of if it exists or 102 # not or if the process has CAP_MKNOD or not. Since we don't want to actually 103 # grant the ability to create character devices, explicitly deny the 104 # capability. When snapd uses SECCOMP_RET_ERRNO, we can remove this rule. 105 # https://forum.snapcraft.io/t/call-for-testing-chromium-62-0-3202-62/2569/46 106 deny capability mknod, 107 ` 108 109 const browserSupportConnectedPlugAppArmorWithSandbox = ` 110 # Leaks installed applications 111 # TODO: should this be somewhere else? 112 /etc/mailcap r, 113 # Snaps should be using xdg-open from the runtime instead of reading these 114 # files directly since the snap is unable to do anything with these files 115 # but these accesses have been allowed for a long time and remain so as not 116 # to break existing snaps. These could be changed to explicit deny rules, 117 # but that provides a worse debugging experience. Combined, the risks 118 # outweigh the benefits of closing this information leak for the small 119 # number of snaps allowed to use allow-sandbox: true. Reference: 120 # https://forum.snapcraft.io/t/cannot-open-pdf-attachment-with-thunderbird/11845 121 /usr/share/applications/{,*} r, 122 /var/lib/snapd/desktop/applications/{,*} r, 123 owner @{PROC}/@{pid}/fd/[0-9]* w, 124 125 # Various files in /run/udev/data needed by Chrome Settings. Leaks device 126 # information. 127 # input 128 /run/udev/data/c1:[0-9]* r, # /dev/psaux 129 /run/udev/data/c10:[0-9]* r, # /dev/adbmouse 130 /run/udev/data/c13:[0-9]* r, # /dev/input/* 131 /run/udev/data/c180:[0-9]* r, # /dev/vrbuttons 132 /run/udev/data/c4:[0-9]* r, # /dev/tty*, /dev/ttyS* 133 /run/udev/data/c5:[0-9]* r, # /dev/tty, /dev/console, etc 134 /run/udev/data/c7:[0-9]* r, # /dev/vcs* 135 /run/udev/data/+hid:* r, 136 /run/udev/data/+input:input[0-9]* r, 137 138 # screen 139 /run/udev/data/c29:[0-9]* r, # /dev/fb* 140 /run/udev/data/+backlight:* r, 141 /run/udev/data/+leds:* r, 142 143 # sound 144 /run/udev/data/c116:[0-9]* r, # alsa 145 /run/udev/data/+sound:card[0-9]* r, 146 147 # miscellaneous 148 /run/udev/data/c108:[0-9]* r, # /dev/ppp 149 /run/udev/data/c189:[0-9]* r, # USB serial converters 150 /run/udev/data/c89:[0-9]* r, # /dev/i2c-* 151 /run/udev/data/c81:[0-9]* r, # video4linux (/dev/video*, etc) 152 /run/udev/data/c202:[0-9]* r, # /dev/cpu/*/msr 153 /run/udev/data/c203:[0-9]* r, # /dev/cuse 154 /run/udev/data/+acpi:* r, 155 /run/udev/data/+hwmon:hwmon[0-9]* r, 156 /run/udev/data/+i2c:* r, 157 /sys/devices/**/bConfigurationValue r, 158 /sys/devices/**/descriptors r, 159 /sys/devices/**/manufacturer r, 160 /sys/devices/**/product r, 161 /sys/devices/**/revision r, 162 /sys/devices/**/serial r, 163 /sys/devices/**/vendor r, 164 /sys/devices/system/node/node[0-9]*/meminfo r, 165 166 # Chromium content api tries to read these. It is an information disclosure 167 # since these contain the names of snaps. Chromium operates fine without the 168 # access so just block it. 169 deny /sys/devices/virtual/block/loop[0-9]*/loop/backing_file r, 170 deny /sys/devices/virtual/block/dm-[0-9]*/dm/name r, 171 172 # networking 173 /run/udev/data/n[0-9]* r, 174 /run/udev/data/+bluetooth:hci[0-9]* r, 175 /run/udev/data/+rfkill:rfkill[0-9]* r, 176 /run/udev/data/c241:[0-9]* r, # /dev/vhost-vsock 177 178 # storage 179 /run/udev/data/b1:[0-9]* r, # /dev/ram* 180 /run/udev/data/b7:[0-9]* r, # /dev/loop* 181 /run/udev/data/b8:[0-9]* r, # /dev/sd* 182 /run/udev/data/b11:[0-9]* r, # /dev/scd* and sr* 183 /run/udev/data/b230:[0-9]* r, # /dev/zvol* 184 /run/udev/data/c21:[0-9]* r, # /dev/sg* 185 /run/udev/data/+usb:[0-9]* r, 186 187 # experimental 188 /run/udev/data/b252:[0-9]* r, 189 /run/udev/data/b253:[0-9]* r, 190 /run/udev/data/b259:[0-9]* r, 191 /run/udev/data/c24[0-9]:[0-9]* r, 192 /run/udev/data/c25[0-4]:[0-9]* r, 193 194 /sys/bus/**/devices/ r, 195 196 # Google Cloud Print 197 unix (bind) 198 type=stream 199 addr="@[0-9A-F]*._service_*", 200 201 # Policy needed only when using the chrome/chromium setuid sandbox 202 capability sys_ptrace, 203 ptrace (trace) peer=snap.@{SNAP_INSTANCE_NAME}.**, 204 unix (receive, send) peer=(label=snap.@{SNAP_INSTANCE_NAME}.**), 205 206 # If this were going to be allowed to all snaps, then for all the following 207 # rules we would want to wrap in a 'browser_sandbox' profile, but a limitation 208 # in AppArmor profile transitions prevents this. 209 # 210 # @{INSTALL_DIR}/@{SNAP_NAME}/@{SNAP_REVISION}/opt/google/chrome{,-beta,-unstable}/chrome-sandbox cx -> browser_sandbox, 211 # profile browser_sandbox { 212 # ... 213 # # This rule needs to work but generates a parser error 214 # @{INSTALL_DIR}/@{SNAP_NAME}/@{SNAP_REVISION}/opt/google/chrome/chrome px -> snap.@{SNAP_INSTANCE_NAME}.@{SNAP_APP}, 215 # @{INSTALL_DIR}/@{SNAP_INSTANCE_NAME}/@{SNAP_REVISION}/opt/google/chrome/chrome px -> snap.@{SNAP_INSTANCE_NAME}.@{SNAP_APP}, 216 # ... 217 # } 218 219 # Required for dropping into PID namespace. Keep in mind that until the 220 # process drops this capability it can escape confinement, but once it 221 # drops CAP_SYS_ADMIN we are ok. 222 capability sys_admin, 223 224 # All of these are for sanely dropping from root and chrooting 225 capability chown, 226 capability fsetid, 227 capability setgid, 228 capability setuid, 229 capability sys_chroot, 230 231 # User namespace sandbox 232 owner @{PROC}/@{pid}/setgroups rw, 233 owner @{PROC}/@{pid}/uid_map rw, 234 owner @{PROC}/@{pid}/gid_map rw, 235 236 # Webkit uses a particular SHM names # LP: 1578217 237 owner /{dev,run}/shm/WK2SharedMemory.* mrw, 238 239 # Chromium content api on (at least) later versions of Ubuntu just use this 240 owner /{dev,run}/shm/shmfd-* mrw, 241 242 # Clearing the PG_Referenced and ACCESSED/YOUNG bits provides a method to 243 # measure approximately how much memory a process is using via /proc/self/smaps 244 # (man 5 proc). This access allows the snap to clear references for pids from 245 # other snaps and the system, so it is limited to snaps that specify: 246 # allow-sandbox: true. 247 owner @{PROC}/@{pid}/clear_refs w, 248 ` 249 250 const browserSupportConnectedPlugSecComp = ` 251 # Description: Can access various APIs needed by modern browsers (eg, Google 252 # Chrome/Chromium and Mozilla) and file paths they expect. This interface is 253 # transitional and is only in place while upstream's work to change their paths 254 # and snappy is updated to properly mediate the APIs. 255 256 # for anonymous sockets 257 bind 258 listen 259 accept 260 accept4 261 262 # TODO: fine-tune when seccomp arg filtering available in stable distro 263 # releases 264 setpriority 265 266 # Since snapd still uses SECCOMP_RET_KILL, add a workaround rule to allow mknod 267 # on character devices since chromium unconditionally performs a mknod() to 268 # create the /dev/nvidiactl device, regardless of if it exists or not or if the 269 # process has CAP_MKNOD or not. Since we don't want to actually grant the 270 # ability to create character devices, we added an explicit deny AppArmor rule 271 # for this capability. When snapd uses SECCOMP_RET_ERRNO, we can remove this 272 # rule. 273 # https://forum.snapcraft.io/t/call-for-testing-chromium-62-0-3202-62/2569/46 274 mknod - |S_IFCHR - 275 mknodat - - |S_IFCHR - 276 ` 277 278 const browserSupportConnectedPlugSecCompWithSandbox = ` 279 # Policy needed only when using the chrome/chromium setuid sandbox 280 chroot 281 sched_setscheduler 282 283 # TODO: fine-tune when seccomp arg filtering available in stable distro 284 # releases 285 setuid 286 setgid 287 288 # Policy needed for Mozilla userns sandbox 289 unshare 290 quotactl 291 292 # The Breakpad crash reporter uses ptrace to read register/memory state 293 # from the crashed process, but it doesn't need to modify any state; see 294 # https://bugzilla.mozilla.org/show_bug.cgi?id=1461848. 295 # 296 # These rules allow that but don't allow ptrace operations that 297 # write registers, which can be used to bypass security; see 298 # https://lkml.org/lkml/2016/5/26/354. 299 ptrace PTRACE_ATTACH 300 ptrace PTRACE_DETACH 301 ptrace PTRACE_GETREGS 302 ptrace PTRACE_GETFPREGS 303 ptrace PTRACE_GETFPXREGS 304 ptrace PTRACE_GETREGSET 305 ptrace PTRACE_PEEKDATA 306 ptrace PTRACE_PEEKUSER 307 ptrace PTRACE_CONT 308 ` 309 310 type browserSupportInterface struct{} 311 312 func (iface *browserSupportInterface) Name() string { 313 return "browser-support" 314 } 315 316 func (iface *browserSupportInterface) StaticInfo() interfaces.StaticInfo { 317 return interfaces.StaticInfo{ 318 Summary: browserSupportSummary, 319 ImplicitOnCore: true, 320 ImplicitOnClassic: true, 321 BaseDeclarationSlots: browserSupportBaseDeclarationSlots, 322 } 323 } 324 325 func (iface *browserSupportInterface) BeforePreparePlug(plug *snap.PlugInfo) error { 326 // It's fine if allow-sandbox isn't specified, but it it is, 327 // it needs to be bool 328 if v, ok := plug.Attrs["allow-sandbox"]; ok { 329 if _, ok = v.(bool); !ok { 330 return fmt.Errorf("browser-support plug requires bool with 'allow-sandbox'") 331 } 332 } 333 334 return nil 335 } 336 337 func (iface *browserSupportInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 338 var allowSandbox bool 339 _ = plug.Attr("allow-sandbox", &allowSandbox) 340 spec.AddSnippet(browserSupportConnectedPlugAppArmor) 341 if allowSandbox { 342 spec.AddSnippet(browserSupportConnectedPlugAppArmorWithSandbox) 343 } else { 344 spec.SetSuppressPtraceTrace() 345 } 346 return nil 347 } 348 349 func (iface *browserSupportInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 350 var allowSandbox bool 351 _ = plug.Attr("allow-sandbox", &allowSandbox) 352 snippet := browserSupportConnectedPlugSecComp 353 if allowSandbox { 354 snippet += browserSupportConnectedPlugSecCompWithSandbox 355 } 356 spec.AddSnippet(snippet) 357 return nil 358 } 359 360 func (iface *browserSupportInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 361 return true 362 } 363 364 func init() { 365 registerIface(&browserSupportInterface{}) 366 }