github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/builtin/pulseaudio.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 "github.com/snapcore/snapd/interfaces" 24 "github.com/snapcore/snapd/interfaces/apparmor" 25 "github.com/snapcore/snapd/interfaces/seccomp" 26 "github.com/snapcore/snapd/interfaces/udev" 27 "github.com/snapcore/snapd/release" 28 "github.com/snapcore/snapd/snap" 29 ) 30 31 const pulseaudioSummary = `allows operating as or interacting with the pulseaudio service` 32 33 const pulseaudioBaseDeclarationSlots = ` 34 pulseaudio: 35 allow-installation: 36 slot-snap-type: 37 - app 38 - core 39 deny-connection: 40 on-classic: false 41 ` 42 43 const pulseaudioConnectedPlugAppArmor = ` 44 # Allow communicating with pulseaudio service for playback and, on some 45 # distributions, recording. 46 /{run,dev}/shm/pulse-shm-* mrwk, 47 48 owner /{,var/}run/pulse/ r, 49 owner /{,var/}run/pulse/native rwk, 50 owner /run/user/[0-9]*/ r, 51 owner /run/user/[0-9]*/pulse/ rw, 52 53 /run/udev/data/c116:[0-9]* r, 54 /run/udev/data/+sound:card[0-9]* r, 55 ` 56 57 const pulseaudioConnectedPlugAppArmorDesktop = ` 58 # Only on desktop do we need access to /etc/pulse for any PulseAudio client 59 # to read available client side configuration settings. On an Ubuntu Core 60 # device those things will be stored inside the snap directory. 61 /etc/pulse/ r, 62 /etc/pulse/** r, 63 owner @{HOME}/.pulse-cookie rk, 64 owner @{HOME}/.config/pulse/cookie rk, 65 owner /{,var/}run/user/*/pulse/ rwk, 66 owner /{,var/}run/user/*/pulse/native rwk, 67 ` 68 69 const pulseaudioConnectedPlugSecComp = ` 70 shmctl 71 ` 72 73 const pulseaudioPermanentSlotAppArmor = ` 74 # When running PulseAudio in system mode it will switch to the at 75 # build time configured user/group on startup. 76 capability setuid, 77 capability setgid, 78 79 capability sys_nice, 80 capability sys_resource, 81 82 owner @{PROC}/@{pid}/exe r, 83 /etc/machine-id r, 84 85 # Audio related 86 @{PROC}/asound/devices r, 87 @{PROC}/asound/card** r, 88 89 # Should use the alsa interface instead 90 /dev/snd/pcm* rw, 91 /dev/snd/control* rw, 92 /dev/snd/timer r, 93 94 /sys/**/sound/** r, 95 96 # For udev 97 network netlink raw, 98 /sys/devices/virtual/dmi/id/sys_vendor r, 99 /sys/devices/virtual/dmi/id/bios_vendor r, 100 # FIXME: use udev queries to make this more specific 101 /run/udev/data/** r, 102 103 owner /{,var/}run/pulse/ rw, 104 owner /{,var/}run/pulse/** rwk, 105 106 # Shared memory based communication with clients 107 /{run,dev}/shm/pulse-shm-* mrwk, 108 109 /usr/share/applications/ r, 110 111 owner /run/pulse/native/ rwk, 112 owner /run/user/[0-9]*/ r, 113 owner /run/user/[0-9]*/pulse/ rw, 114 ` 115 116 const pulseaudioPermanentSlotSecComp = ` 117 # The following are needed for UNIX sockets 118 personality 119 setpriority 120 bind 121 listen 122 accept 123 accept4 124 shmctl 125 # Needed to set root as group for different state dirs 126 # pulseaudio creates on startup. 127 setgroups 128 setgroups32 129 # libudev 130 socket AF_NETLINK - NETLINK_KOBJECT_UEVENT 131 ` 132 133 type pulseAudioInterface struct{} 134 135 func (iface *pulseAudioInterface) Name() string { 136 return "pulseaudio" 137 } 138 139 func (iface *pulseAudioInterface) StaticInfo() interfaces.StaticInfo { 140 return interfaces.StaticInfo{ 141 Summary: pulseaudioSummary, 142 ImplicitOnClassic: true, 143 BaseDeclarationSlots: pulseaudioBaseDeclarationSlots, 144 } 145 } 146 147 func (iface *pulseAudioInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 148 spec.AddSnippet(pulseaudioConnectedPlugAppArmor) 149 if release.OnClassic { 150 spec.AddSnippet(pulseaudioConnectedPlugAppArmorDesktop) 151 } 152 return nil 153 } 154 155 func (iface *pulseAudioInterface) UDevPermanentSlot(spec *udev.Specification, slot *snap.SlotInfo) error { 156 spec.TagDevice(`KERNEL=="controlC[0-9]*"`) 157 spec.TagDevice(`KERNEL=="pcmC[0-9]*D[0-9]*[cp]"`) 158 spec.TagDevice(`KERNEL=="timer"`) 159 return nil 160 } 161 162 func (iface *pulseAudioInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error { 163 spec.AddSnippet(pulseaudioPermanentSlotAppArmor) 164 return nil 165 } 166 167 func (iface *pulseAudioInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 168 spec.AddSnippet(pulseaudioConnectedPlugSecComp) 169 return nil 170 } 171 172 func (iface *pulseAudioInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *snap.SlotInfo) error { 173 spec.AddSnippet(pulseaudioPermanentSlotSecComp) 174 return nil 175 } 176 177 func (iface *pulseAudioInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 178 return true 179 } 180 181 func init() { 182 registerIface(&pulseAudioInterface{}) 183 }