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

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (c) 2016-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 dtails.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.
    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/seccomp"
    28  	"github.com/snapcore/snapd/interfaces/udev"
    29  	"github.com/snapcore/snapd/snap"
    30  )
    31  
    32  const mirSummary = `allows operating as the Mir server`
    33  
    34  const mirBaseDeclarationSlots = `
    35    mir:
    36      allow-installation:
    37        slot-snap-type:
    38          - app
    39      deny-connection: true
    40  `
    41  
    42  const mirPermanentSlotAppArmor = `
    43  # Description: Allow operating as the Mir server. This gives privileged access
    44  # to the system.
    45  
    46  # needed since Mir is the display server, to configure tty devices
    47  capability sys_tty_config,
    48  /dev/tty[0-9]* rw,
    49  
    50  # mir uses open("/dev/shm", O_TMPFILE...) which shows up in AppArmor
    51  # as /dev/shm/#NUMBER. This is then fed to mmap with MAP_SHARED
    52  # for communication with the client (note that the file doesn't actually
    53  # exist and isn't accessible by other processes). Also see:
    54  # https://www.kernel.org/doc/gorman/html/understand/understand015.html
    55  /{dev,run}/shm/\#[0-9]* mrw,
    56  
    57  /run/mir_socket rw,
    58  /run/user/[0-9]*/mir_socket rw,
    59  
    60  # Needed for mode setting via drmSetMaster() and drmDropMaster()
    61  capability sys_admin,
    62  
    63  # NOTE: this allows reading and inserting all input events
    64  /dev/input/* rw,
    65  
    66  # For using udev
    67  network netlink raw,
    68  /run/udev/data/c13:[0-9]* r,
    69  /run/udev/data/+input:input[0-9]* r,
    70  /run/udev/data/+platform:* r,
    71  `
    72  
    73  const mirPermanentSlotSecComp = `
    74  # Description: Allow operating as the mir server. This gives privileged access
    75  # to the system.
    76  # Needed for server launch
    77  bind
    78  listen
    79  # Needed by server upon client connect
    80  accept
    81  accept4
    82  shmctl
    83  # for udev
    84  socket AF_NETLINK - NETLINK_KOBJECT_UEVENT
    85  `
    86  
    87  const mirConnectedSlotAppArmor = `
    88  # Description: Permit clients to use Mir
    89  unix (receive, send) type=seqpacket addr=none peer=(label=###PLUG_SECURITY_TAGS###),
    90  `
    91  
    92  const mirConnectedPlugAppArmor = `
    93  # Description: Permit clients to use Mir
    94  unix (receive, send) type=seqpacket addr=none peer=(label=###SLOT_SECURITY_TAGS###),
    95  /run/mir_socket rw,
    96  /run/user/[0-9]*/mir_socket rw,
    97  
    98  # Mir uses /dev/shm for sharing memory with clients
    99  /{dev,run}/shm/\#[0-9]* mrw,
   100  `
   101  
   102  type mirInterface struct{}
   103  
   104  func (iface *mirInterface) Name() string {
   105  	return "mir"
   106  }
   107  
   108  func (iface *mirInterface) StaticInfo() interfaces.StaticInfo {
   109  	return interfaces.StaticInfo{
   110  		Summary:              mirSummary,
   111  		BaseDeclarationSlots: mirBaseDeclarationSlots,
   112  	}
   113  }
   114  
   115  func (iface *mirInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   116  	old := "###SLOT_SECURITY_TAGS###"
   117  	new := slotAppLabelExpr(slot)
   118  	snippet := strings.Replace(mirConnectedPlugAppArmor, old, new, -1)
   119  	spec.AddSnippet(snippet)
   120  	return nil
   121  }
   122  
   123  func (iface *mirInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   124  	old := "###PLUG_SECURITY_TAGS###"
   125  	new := plugAppLabelExpr(plug)
   126  	snippet := strings.Replace(mirConnectedSlotAppArmor, old, new, -1)
   127  	spec.AddSnippet(snippet)
   128  	return nil
   129  }
   130  
   131  func (iface *mirInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error {
   132  	spec.AddSnippet(mirPermanentSlotAppArmor)
   133  	return nil
   134  }
   135  
   136  func (iface *mirInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *snap.SlotInfo) error {
   137  	spec.AddSnippet(mirPermanentSlotSecComp)
   138  	return nil
   139  }
   140  
   141  func (iface *mirInterface) UDevPermanentSlot(spec *udev.Specification, slot *snap.SlotInfo) error {
   142  	spec.TriggerSubsystem("input")
   143  	spec.TagDevice(`KERNEL=="tty[0-9]*"`)
   144  	spec.TagDevice(`KERNEL=="mice"`)
   145  	spec.TagDevice(`KERNEL=="mouse[0-9]*"`)
   146  	spec.TagDevice(`KERNEL=="event[0-9]*"`)
   147  	spec.TagDevice(`KERNEL=="ts[0-9]*"`)
   148  	return nil
   149  }
   150  
   151  func (iface *mirInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool {
   152  	return true
   153  }
   154  
   155  func init() {
   156  	registerIface(&mirInterface{})
   157  }