github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/interfaces/builtin/bluez.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  	"strings"
    24  
    25  	"github.com/snapcore/snapd/interfaces"
    26  	"github.com/snapcore/snapd/interfaces/apparmor"
    27  	"github.com/snapcore/snapd/interfaces/dbus"
    28  	"github.com/snapcore/snapd/interfaces/seccomp"
    29  	"github.com/snapcore/snapd/interfaces/udev"
    30  	"github.com/snapcore/snapd/release"
    31  	"github.com/snapcore/snapd/snap"
    32  )
    33  
    34  const bluezSummary = `allows operating as the bluez service`
    35  
    36  const bluezBaseDeclarationSlots = `
    37    bluez:
    38      allow-installation:
    39        slot-snap-type:
    40          - app
    41          - core
    42      deny-auto-connection: true
    43      deny-connection:
    44        on-classic: false
    45  `
    46  
    47  const bluezPermanentSlotAppArmor = `
    48  # Description: Allow operating as the bluez service. This gives privileged
    49  # access to the system.
    50  
    51  network bluetooth,
    52  
    53  capability net_admin,
    54  capability net_bind_service,
    55  
    56  # libudev
    57  network netlink raw,
    58  
    59  # File accesses
    60  /sys/bus/usb/drivers/btusb/     r,
    61  /sys/bus/usb/drivers/btusb/**   r,
    62  /sys/class/bluetooth/           r,
    63  /sys/devices/**/bluetooth/      rw,
    64  /sys/devices/**/bluetooth/**    rw,
    65  /sys/devices/**/id/chassis_type r,
    66  
    67  # TODO: use snappy hardware assignment for this once LP: #1498917 is fixed
    68  /dev/rfkill rw,
    69  
    70  # DBus accesses
    71  #include <abstractions/dbus-strict>
    72  dbus (send)
    73     bus=system
    74     path=/org/freedesktop/DBus
    75     interface=org.freedesktop.DBus
    76     member={Request,Release}Name
    77     peer=(name=org.freedesktop.DBus, label=unconfined),
    78  
    79  dbus (send)
    80    bus=system
    81    path=/org/freedesktop/*
    82    interface=org.freedesktop.DBus.Properties
    83    peer=(label=unconfined),
    84  
    85  # Allow binding the service to the requested connection name
    86  dbus (bind)
    87      bus=system
    88      name="org.bluez",
    89  
    90  # Allow binding the service to the requested connection name
    91  dbus (bind)
    92      bus=system
    93      name="org.bluez.obex",
    94  
    95  # Allow binding the service to the requested connection name
    96  dbus (bind)
    97      bus=system
    98      name="org.bluez.mesh",
    99  
   100  # Allow traffic to/from our interface with any method for unconfined clients
   101  # to talk to our bluez services. For the org.bluez interface we don't specify
   102  # an Object Path since according to the bluez specification these can be
   103  # anything (https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc).
   104  dbus (receive, send)
   105      bus=system
   106      interface=org.bluez.*
   107      peer=(label=unconfined),
   108  dbus (receive, send)
   109      bus=system
   110      path=/org/bluez{,/**}
   111      interface=org.freedesktop.DBus.*
   112      peer=(label=unconfined),
   113  
   114  # Allow traffic to/from org.freedesktop.DBus for bluez service. This rule is
   115  # not snap-specific and grants privileged access to the org.freedesktop.DBus
   116  # on the system bus.
   117  dbus (receive, send)
   118      bus=system
   119      path=/
   120      interface=org.freedesktop.DBus.*
   121      peer=(label=unconfined),
   122  
   123  # Allow access to hostname system service
   124  dbus (receive, send)
   125      bus=system
   126      path=/org/freedesktop/hostname1
   127      interface=org.freedesktop.DBus.Properties
   128      peer=(label=unconfined),
   129  
   130  # do not use peer=(label=unconfined) here since this is DBus activated
   131  dbus (send)
   132      bus=system
   133      path=/org/freedesktop/hostname1
   134      interface=org.freedesktop.DBus.Properties
   135      member="Get{,All}",
   136  dbus (send)
   137      bus=system
   138      path=/org/freedesktop/hostname1
   139      interface=org.freedesktop.DBus.Introspectable
   140      member=Introspect,
   141  `
   142  
   143  const bluezConnectedSlotAppArmor = `
   144  # Allow connected clients to interact with the service
   145  
   146  # Allow all access to bluez service
   147  dbus (receive, send)
   148      bus=system
   149      peer=(label=###PLUG_SECURITY_TAGS###),
   150  `
   151  
   152  const bluezConnectedPlugAppArmor = `
   153  # Description: Allow using bluez service. This gives privileged access to the
   154  # bluez service.
   155  
   156  #include <abstractions/dbus-strict>
   157  
   158  # Allow all access to bluez service
   159  dbus (receive, send)
   160      bus=system
   161      peer=(label=###SLOT_SECURITY_TAGS###),
   162  
   163  dbus (send)
   164      bus=system
   165      peer=(name=org.bluez, label=unconfined),
   166  
   167  dbus (send)
   168      bus=system
   169      peer=(name=org.bluez.obex, label=unconfined),
   170  
   171  dbus (send)
   172      bus=system
   173      peer=(name=org.bluez.mesh, label=unconfined),
   174  
   175  dbus (receive)
   176      bus=system
   177      path=/
   178      interface=org.freedesktop.DBus.ObjectManager
   179      peer=(label=unconfined),
   180  
   181  dbus (receive)
   182      bus=system
   183      path=/org/bluez{,/**}
   184      interface=org.freedesktop.DBus.*
   185      peer=(label=unconfined),
   186  
   187  # Allow access to bluetooth audio streams
   188  network bluetooth,
   189  `
   190  
   191  const bluezPermanentSlotSecComp = `
   192  # Description: Allow operating as the bluez service. This gives privileged
   193  # access to the system.
   194  accept
   195  accept4
   196  bind
   197  listen
   198  # libudev
   199  socket AF_NETLINK - NETLINK_KOBJECT_UEVENT
   200  `
   201  
   202  const bluezPermanentSlotDBus = `
   203  <policy user="root">
   204      <allow own="org.bluez"/>
   205      <allow own="org.bluez.obex"/>
   206      <allow own="org.bluez.mesh"/>
   207      <allow send_destination="org.bluez"/>
   208      <allow send_destination="org.bluez.obex"/>
   209      <allow send_destination="org.bluez.mesh"/>
   210      <allow send_interface="org.bluez.Agent1"/>
   211      <allow send_interface="org.bluez.MediaEndpoint1"/>
   212      <allow send_interface="org.bluez.MediaPlayer1"/>
   213      <allow send_interface="org.bluez.ThermometerWatcher1"/>
   214      <allow send_interface="org.bluez.AlertAgent1"/>
   215      <allow send_interface="org.bluez.Profile1"/>
   216      <allow send_interface="org.bluez.HeartRateWatcher1"/>
   217      <allow send_interface="org.bluez.CyclingSpeedWatcher1"/>
   218      <allow send_interface="org.bluez.GattCharacteristic1"/>
   219      <allow send_interface="org.bluez.GattDescriptor1"/>
   220      <allow send_interface="org.bluez.mesh.Element1"/>
   221      <allow send_interface="org.bluez.mesh.Application1"/>
   222      <allow send_interface="org.bluez.mesh.ProvisionAgent1"/>
   223      <allow send_interface="org.bluez.mesh.Provisioner1"/>
   224      <allow send_interface="org.bluez.mesh.Attention1"/>
   225      <allow send_interface="org.bluez.mesh.Network1"/>
   226      <allow send_interface="org.bluez.mesh.Node1"/>
   227      <allow send_interface="org.bluez.mesh.Management1"/>
   228      <allow send_interface="org.freedesktop.DBus.ObjectManager"/>
   229      <allow send_interface="org.freedesktop.DBus.Properties"/>
   230  </policy>
   231  <policy context="default">
   232      <deny send_destination="org.bluez"/>
   233  </policy>
   234  `
   235  
   236  type bluezInterface struct{}
   237  
   238  func (iface *bluezInterface) Name() string {
   239  	return "bluez"
   240  }
   241  
   242  func (iface *bluezInterface) StaticInfo() interfaces.StaticInfo {
   243  	return interfaces.StaticInfo{
   244  		Summary:              bluezSummary,
   245  		ImplicitOnClassic:    true,
   246  		BaseDeclarationSlots: bluezBaseDeclarationSlots,
   247  	}
   248  }
   249  
   250  func (iface *bluezInterface) DBusPermanentSlot(spec *dbus.Specification, slot *snap.SlotInfo) error {
   251  	if !release.OnClassic {
   252  		spec.AddSnippet(bluezPermanentSlotDBus)
   253  	}
   254  	return nil
   255  }
   256  
   257  func (iface *bluezInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   258  	old := "###SLOT_SECURITY_TAGS###"
   259  	var new string
   260  	if release.OnClassic {
   261  		new = "unconfined"
   262  	} else {
   263  		new = slotAppLabelExpr(slot)
   264  	}
   265  	snippet := strings.Replace(bluezConnectedPlugAppArmor, old, new, -1)
   266  	spec.AddSnippet(snippet)
   267  	return nil
   268  }
   269  
   270  func (iface *bluezInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   271  	if !release.OnClassic {
   272  		old := "###PLUG_SECURITY_TAGS###"
   273  		new := plugAppLabelExpr(plug)
   274  		snippet := strings.Replace(bluezConnectedSlotAppArmor, old, new, -1)
   275  		spec.AddSnippet(snippet)
   276  	}
   277  	return nil
   278  }
   279  
   280  func (iface *bluezInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   281  	spec.TagDevice(`KERNEL=="rfkill"`)
   282  	return nil
   283  }
   284  
   285  func (iface *bluezInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error {
   286  	if !release.OnClassic {
   287  		spec.AddSnippet(bluezPermanentSlotAppArmor)
   288  	}
   289  	return nil
   290  }
   291  
   292  func (iface *bluezInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *snap.SlotInfo) error {
   293  	if !release.OnClassic {
   294  		spec.AddSnippet(bluezPermanentSlotSecComp)
   295  	}
   296  	return nil
   297  }
   298  
   299  func (iface *bluezInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool {
   300  	// allow what declarations allowed
   301  	return true
   302  }
   303  
   304  func init() {
   305  	registerIface(&bluezInterface{})
   306  }