github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/interfaces/builtin/upower_observe.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 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/release"
    30  	"github.com/snapcore/snapd/snap"
    31  )
    32  
    33  const upowerObserveSummary = `allows operating as or reading from the UPower service`
    34  
    35  const upowerObserveBaseDeclarationSlots = `
    36    upower-observe:
    37      allow-installation:
    38        slot-snap-type:
    39          - app
    40          - core
    41      deny-connection:
    42        on-classic: false
    43  `
    44  
    45  const upowerObservePermanentSlotAppArmor = `
    46  # Description: Allow operating as the UPower service.
    47  
    48  network netlink raw,
    49  
    50  # DBus accesses
    51  #include <abstractions/dbus-strict>
    52  
    53  dbus (send)
    54     bus=system
    55     path=/org/freedesktop/DBus
    56     interface=org.freedesktop.DBus
    57     member={Request,Release}Name
    58     peer=(name=org.freedesktop.DBus),
    59  
    60  dbus (receive, send)
    61     bus=system
    62     path=/org/freedesktop/DBus
    63     interface=org.freedesktop.DBus
    64     member="GetConnectionUnix{ProcessID,User}"
    65     peer=(label=unconfined),
    66  
    67  # Allow binding the service to the requested connection name
    68  dbus (bind)
    69      bus=system
    70      name="org.freedesktop.UPower",
    71  
    72  # Allow read-only access to service properties
    73  dbus (receive)
    74      bus=system
    75      path=/org/freedesktop/login1{,/**}
    76      interface=org.freedesktop.DBus.Properties
    77      peer=(label=unconfined),
    78  # do not use peer=(label=unconfined) here since this is DBus activated
    79  dbus (send)
    80      bus=system
    81      path=/org/freedesktop/login1{,/**}
    82      interface=org.freedesktop.DBus.Properties
    83      member=Get{,All},
    84  
    85  # Allow receiving any signals from the logind service
    86  dbus (receive)
    87      bus=system
    88      path=/org/freedesktop/login1{,/**}
    89      interface=org.freedesktop.login1.*
    90      peer=(label=unconfined),
    91  
    92  # Allow access to logind service as we need to query it for possible
    93  # power states and trigger these when the battery gets low and the
    94  # system enters a critical state.
    95  dbus (send)
    96      bus=system
    97      path=/org/freedesktop/login1{,/**}
    98      interface=org.freedesktop.login1.Manager
    99      member={CanPowerOff,CanSuspend,CanHibernate,CanHybridSleep,PowerOff,Suspend,Hibernate,HybridSleep}
   100      peer=(label=unconfined),
   101  `
   102  
   103  const upowerObserveConnectedSlotAppArmor = `
   104  # Allow traffic to/from our path and interface with any method
   105  dbus (receive, send)
   106      bus=system
   107      path=/org/freedesktop/UPower{,/**}
   108      interface=org.freedesktop.UPower*
   109      peer=(label=###PLUG_SECURITY_TAGS###),
   110  
   111  # Allow traffic to/from org.freedesktop.DBus for the UPower service
   112  dbus (receive, send)
   113      bus=system
   114      path=/org/freedesktop/UPower{,/**}
   115      interface=org.freedesktop.DBus.*
   116      peer=(label=###PLUG_SECURITY_TAGS###),
   117  `
   118  
   119  const upowerObservePermanentSlotSeccomp = `
   120  # libudev
   121  bind
   122  socket AF_NETLINK - NETLINK_KOBJECT_UEVENT
   123  `
   124  
   125  const upowerObservePermanentSlotDBus = `
   126  <!-- DBus policy for upower (based on upstream version 0.99.4) -->
   127  <policy user="root">
   128    <allow own="org.freedesktop.UPower"/>
   129  </policy>
   130  <policy context="default">
   131    <deny own="org.freedesktop.UPower"/>
   132  
   133    <allow send_destination="org.freedesktop.UPower"
   134           send_interface="org.freedesktop.DBus.Introspectable"/>
   135  
   136    <allow send_destination="org.freedesktop.UPower"
   137           send_interface="org.freedesktop.DBus.Peer"/>
   138    <allow send_destination="org.freedesktop.UPower"
   139           send_interface="org.freedesktop.DBus.Properties"/>
   140    <allow send_destination="org.freedesktop.UPower.Device"
   141           send_interface="org.freedesktop.DBus.Properties"/>
   142    <allow send_destination="org.freedesktop.UPower.KbdBacklight"
   143           send_interface="org.freedesktop.DBus.Properties"/>
   144    <allow send_destination="org.freedesktop.UPower.Wakeups"
   145           send_interface="org.freedesktop.DBus.Properties"/>
   146  
   147    <allow send_destination="org.freedesktop.UPower"
   148           send_interface="org.freedesktop.UPower"/>
   149    <allow send_destination="org.freedesktop.UPower"
   150           send_interface="org.freedesktop.UPower.Device"/>
   151    <allow send_destination="org.freedesktop.UPower"
   152           send_interface="org.freedesktop.UPower.KbdBacklight"/>
   153    <allow send_destination="org.freedesktop.UPower"
   154           send_interface="org.freedesktop.UPower.Wakeups"/>
   155  </policy>
   156  `
   157  
   158  const upowerObserveConnectedPlugAppArmor = `
   159  # Description: Can query UPower for power devices, history and statistics.
   160  
   161  #include <abstractions/dbus-strict>
   162  
   163  # Find all devices monitored by UPower
   164  dbus (send)
   165      bus=system
   166      path=/org/freedesktop/UPower
   167      interface=org.freedesktop.UPower
   168      member=EnumerateDevices
   169      peer=(label=###SLOT_SECURITY_TAGS###),
   170  
   171  # Read all properties from UPower and devices
   172  # do not use peer=(label=unconfined) here since this is DBus activated
   173  dbus (send)
   174      bus=system
   175      path=/org/freedesktop/UPower{,/Wakeups,/devices/**}
   176      interface=org.freedesktop.DBus.Properties
   177      member=Get{,All},
   178  
   179  dbus (send)
   180      bus=system
   181      path=/org/freedesktop/UPower
   182      interface=org.freedesktop.UPower
   183      member=GetCriticalAction
   184      peer=(label=###SLOT_SECURITY_TAGS###),
   185  
   186  dbus (send)
   187      bus=system
   188      path=/org/freedesktop/UPower
   189      interface=org.freedesktop.UPower
   190      member=GetDisplayDevice
   191      peer=(label=###SLOT_SECURITY_TAGS###),
   192  
   193  dbus (send)
   194      bus=system
   195      path=/org/freedesktop/UPower/devices/**
   196      interface=org.freedesktop.UPower.Device
   197      member=GetHistory
   198      peer=(label=###SLOT_SECURITY_TAGS###),
   199  
   200  # Receive property changed events
   201  dbus (receive)
   202      bus=system
   203      path=/org/freedesktop/UPower{,/devices/**}
   204      interface=org.freedesktop.DBus.Properties
   205      member=PropertiesChanged
   206      peer=(label=###SLOT_SECURITY_TAGS###),
   207  
   208  # Allow clients to introspect the service
   209  # do not use peer=(label=unconfined) here since this is DBus activated
   210  dbus (send)
   211      bus=system
   212      interface=org.freedesktop.DBus.Introspectable
   213      path=/org/freedesktop/UPower
   214      member=Introspect,
   215  `
   216  
   217  type upowerObserveInterface struct{}
   218  
   219  func (iface *upowerObserveInterface) Name() string {
   220  	return "upower-observe"
   221  }
   222  
   223  func (iface *upowerObserveInterface) StaticInfo() interfaces.StaticInfo {
   224  	return interfaces.StaticInfo{
   225  		Summary:              upowerObserveSummary,
   226  		ImplicitOnClassic:    true,
   227  		BaseDeclarationSlots: upowerObserveBaseDeclarationSlots,
   228  	}
   229  }
   230  
   231  func (iface *upowerObserveInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   232  	old := "###SLOT_SECURITY_TAGS###"
   233  	new := slotAppLabelExpr(slot)
   234  	if release.OnClassic {
   235  		// Let confined apps access unconfined upower on classic
   236  		new = "unconfined"
   237  	}
   238  	snippet := strings.Replace(upowerObserveConnectedPlugAppArmor, old, new, -1)
   239  	spec.AddSnippet(snippet)
   240  	return nil
   241  }
   242  
   243  func (iface *upowerObserveInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error {
   244  	spec.AddSnippet(upowerObservePermanentSlotAppArmor)
   245  	return nil
   246  }
   247  
   248  func (iface *upowerObserveInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *snap.SlotInfo) error {
   249  	spec.AddSnippet(upowerObservePermanentSlotSeccomp)
   250  	return nil
   251  }
   252  
   253  func (iface *upowerObserveInterface) DBusPermanentSlot(spec *dbus.Specification, slot *snap.SlotInfo) error {
   254  	spec.AddSnippet(upowerObservePermanentSlotDBus)
   255  	return nil
   256  }
   257  
   258  func (iface *upowerObserveInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   259  	old := "###PLUG_SECURITY_TAGS###"
   260  	new := plugAppLabelExpr(plug)
   261  	snippet := strings.Replace(upowerObserveConnectedSlotAppArmor, old, new, -1)
   262  	spec.AddSnippet(snippet)
   263  	return nil
   264  }
   265  
   266  func (iface *upowerObserveInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool {
   267  	// allow what declarations allowed
   268  	return true
   269  }
   270  
   271  func init() {
   272  	registerIface(&upowerObserveInterface{})
   273  }