github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/interfaces/builtin/audio_playback.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 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 // The audio-playback interface is the companion interface to the audio-record 32 // interface. The design of this interface is based on the idea that the slot 33 // implementation (eg pulseaudio) is expected to query snapd on if the 34 // audio-record slot is connected or not and the audio service will mediate 35 // recording (ie, the rules below allow connecting to the audio service, but do 36 // not implement enforcement rules; it is up to the audio service to provide 37 // enforcement). If other audio recording servers require different security 38 // policy for record and playback (eg, a different socket path), then those 39 // accesses will be added to this interface. 40 41 const audioPlaybackSummary = `allows audio playback via supporting services` 42 43 const audioPlaybackBaseDeclarationSlots = ` 44 audio-playback: 45 allow-installation: 46 slot-snap-type: 47 - app 48 - core 49 deny-connection: 50 on-classic: false 51 ` 52 53 const audioPlaybackConnectedPlugAppArmor = ` 54 # Allow communicating with pulseaudio service 55 /{run,dev}/shm/pulse-shm-* mrwk, 56 57 owner /{,var/}run/pulse/ r, 58 owner /{,var/}run/pulse/native rwk, 59 owner /{,var/}run/pulse/pid r, 60 owner /{,var/}run/user/[0-9]*/ r, 61 owner /{,var/}run/user/[0-9]*/pulse/ rw, 62 63 /run/udev/data/c116:[0-9]* r, 64 /run/udev/data/+sound:card[0-9]* r, 65 ` 66 67 const audioPlaybackConnectedPlugAppArmorDesktop = ` 68 # Allow communicating with pulseaudio service on the desktop in classic distro. 69 # Only on desktop do we need access to /etc/pulse for any PulseAudio client 70 # to read available client side configuration settings. On an Ubuntu Core 71 # device those things will be stored inside the snap directory. 72 /etc/pulse/ r, 73 /etc/pulse/** r, 74 owner @{HOME}/.pulse-cookie rk, 75 owner @{HOME}/.config/pulse/cookie rk, 76 owner /{,var/}run/user/*/pulse/ rwk, 77 owner /{,var/}run/user/*/pulse/native rwk, 78 owner /{,var/}run/user/*/pulse/pid r, 79 ` 80 81 const audioPlaybackConnectedPlugSecComp = ` 82 shmctl 83 ` 84 85 const audioPlaybackPermanentSlotAppArmor = ` 86 # When running PulseAudio in system mode it will switch to the at 87 # build time configured user/group on startup. 88 capability setuid, 89 capability setgid, 90 91 capability sys_nice, 92 capability sys_resource, 93 94 owner @{PROC}/@{pid}/exe r, 95 /etc/machine-id r, 96 97 # For udev 98 network netlink raw, 99 /sys/devices/virtual/dmi/id/sys_vendor r, 100 /sys/devices/virtual/dmi/id/bios_vendor r, 101 /sys/**/sound/** 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 owner /run/pulse/native/ rwk, 110 owner /run/user/[0-9]*/ r, 111 owner /run/user/[0-9]*/pulse/ rw, 112 ` 113 114 const audioPlaybackPermanentSlotSecComp = ` 115 # The following are needed for UNIX sockets 116 personality 117 setpriority 118 bind 119 listen 120 accept 121 accept4 122 shmctl 123 # Needed to set root as group for different state dirs 124 # pulseaudio creates on startup. 125 setgroups 126 setgroups32 127 # libudev 128 socket AF_NETLINK - NETLINK_KOBJECT_UEVENT 129 ` 130 131 type audioPlaybackInterface struct{} 132 133 func (iface *audioPlaybackInterface) Name() string { 134 return "audio-playback" 135 } 136 137 func (iface *audioPlaybackInterface) StaticInfo() interfaces.StaticInfo { 138 return interfaces.StaticInfo{ 139 Summary: audioPlaybackSummary, 140 ImplicitOnClassic: true, 141 BaseDeclarationSlots: audioPlaybackBaseDeclarationSlots, 142 } 143 } 144 145 func (iface *audioPlaybackInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 146 spec.AddSnippet(audioPlaybackConnectedPlugAppArmor) 147 if release.OnClassic { 148 spec.AddSnippet(audioPlaybackConnectedPlugAppArmorDesktop) 149 } 150 return nil 151 } 152 153 func (iface *audioPlaybackInterface) UDevPermanentSlot(spec *udev.Specification, slot *snap.SlotInfo) error { 154 spec.TagDevice(`KERNEL=="controlC[0-9]*"`) 155 spec.TagDevice(`KERNEL=="pcmC[0-9]*D[0-9]*[cp]"`) 156 spec.TagDevice(`KERNEL=="timer"`) 157 return nil 158 } 159 160 func (iface *audioPlaybackInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error { 161 spec.AddSnippet(audioPlaybackPermanentSlotAppArmor) 162 return nil 163 } 164 165 func (iface *audioPlaybackInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 166 spec.AddSnippet(audioPlaybackConnectedPlugSecComp) 167 return nil 168 } 169 170 func (iface *audioPlaybackInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *snap.SlotInfo) error { 171 spec.AddSnippet(audioPlaybackPermanentSlotSecComp) 172 return nil 173 } 174 175 func (iface *audioPlaybackInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 176 return true 177 } 178 179 func init() { 180 registerIface(&audioPlaybackInterface{}) 181 }