github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/builtin/device_buttons.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/udev"
    25  )
    26  
    27  const deviceButtonsSummary = `allows access to device buttons as input events`
    28  
    29  const deviceButtonsBaseDeclarationSlots = `
    30    device-buttons:
    31      allow-installation:
    32        slot-snap-type:
    33          - core
    34      deny-auto-connection: true
    35  `
    36  
    37  const deviceButtonsConnectedPlugAppArmor = `
    38  # Description: Allow reading and writing events to device buttons exposed as
    39  #              input events.
    40  
    41  #
    42  # evdev-based interface
    43  #
    44  
    45  # /dev/input/event* is unfortunately not namespaced and includes all input
    46  # devices, including keyboards and mice, which allows input sniffing and
    47  # injection. Until we have inode tagging of devices, we use a glob rule here
    48  # and rely on udev tagging to only add evdev devices to the snap's device
    49  # cgroup that are marked with ENV{ID_INPUT_KEY}=="1" and are not marked with
    50  # ENV{ID_INPUT_KEYBOARD}. As such, even though AppArmor allows all evdev,
    51  # the device cgroup does not.
    52  /dev/input/event[0-9]* rw,
    53  
    54  # Allow reading for supported event reports for all input devices. See
    55  # https://www.kernel.org/doc/Documentation/input/event-codes.txt
    56  # FIXME: this is a very minor information leak and snapd should instead query
    57  # udev for the specific accesses associated with the above devices.
    58  /sys/devices/**/input[0-9]*/capabilities/* r,
    59  `
    60  
    61  // Add the device buttons realized in terms of GPIO. They come up with
    62  // ENV{ID_INPUT_KEY} set to "1" value and at the same time make sure these are
    63  // not a keyboard.
    64  //
    65  // Because of the unconditional /dev/input/event[0-9]* AppArmor rule, we need
    66  // to ensure that the device cgroup is in effect even when there are no
    67  // gpio keys present so that we don't give away all input to the snap.
    68  var deviceButtonsConnectedPlugUDev = []string{
    69  	`KERNEL=="event[0-9]*", SUBSYSTEM=="input", ENV{ID_INPUT_KEY}=="1", ENV{ID_INPUT_KEYBOARD}!="1"`,
    70  	`KERNEL=="full", SUBSYSTEM=="mem"`,
    71  }
    72  
    73  type deviceButtonsInterface struct {
    74  	commonInterface
    75  }
    76  
    77  func (iface *deviceButtonsInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    78  	spec.TriggerSubsystem("input/key")
    79  	return iface.commonInterface.UDevConnectedPlug(spec, plug, slot)
    80  }
    81  
    82  func init() {
    83  	registerIface(&deviceButtonsInterface{commonInterface{
    84  		name:                  "device-buttons",
    85  		summary:               deviceButtonsSummary,
    86  		implicitOnCore:        true,
    87  		implicitOnClassic:     true,
    88  		baseDeclarationSlots:  deviceButtonsBaseDeclarationSlots,
    89  		connectedPlugAppArmor: deviceButtonsConnectedPlugAppArmor,
    90  		connectedPlugUDev:     deviceButtonsConnectedPlugUDev,
    91  		reservedForOS:         true,
    92  	}})
    93  }