github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/interfaces/builtin/common.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 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  	"io/ioutil"
    24  	"path/filepath"
    25  
    26  	"github.com/snapcore/snapd/interfaces"
    27  	"github.com/snapcore/snapd/interfaces/apparmor"
    28  	"github.com/snapcore/snapd/interfaces/kmod"
    29  	"github.com/snapcore/snapd/interfaces/mount"
    30  	"github.com/snapcore/snapd/interfaces/seccomp"
    31  	"github.com/snapcore/snapd/interfaces/udev"
    32  	"github.com/snapcore/snapd/osutil"
    33  	"github.com/snapcore/snapd/snap"
    34  )
    35  
    36  // evalSymlinks is either filepath.EvalSymlinks or a mocked function for
    37  // applicable for testing.
    38  var evalSymlinks = filepath.EvalSymlinks
    39  
    40  // readDir is either ioutil.ReadDir or a mocked function for applicable for
    41  // testing.
    42  var readDir = ioutil.ReadDir
    43  
    44  type commonInterface struct {
    45  	name    string
    46  	summary string
    47  	docURL  string
    48  
    49  	implicitOnCore    bool
    50  	implicitOnClassic bool
    51  
    52  	baseDeclarationPlugs string
    53  	baseDeclarationSlots string
    54  
    55  	connectedPlugAppArmor  string
    56  	connectedPlugSecComp   string
    57  	connectedPlugUDev      []string
    58  	rejectAutoConnectPairs bool
    59  
    60  	connectedPlugUpdateNSAppArmor string
    61  	connectedPlugMount            []osutil.MountEntry
    62  
    63  	connectedPlugKModModules []string
    64  	connectedSlotKModModules []string
    65  	permanentPlugKModModules []string
    66  	permanentSlotKModModules []string
    67  
    68  	usesPtraceTrace      bool
    69  	suppressPtraceTrace  bool
    70  	suppressHomeIx       bool
    71  	controlsDeviceCgroup bool
    72  }
    73  
    74  // Name returns the interface name.
    75  func (iface *commonInterface) Name() string {
    76  	return iface.name
    77  }
    78  
    79  // StaticInfo returns various meta-data about this interface.
    80  func (iface *commonInterface) StaticInfo() interfaces.StaticInfo {
    81  	return interfaces.StaticInfo{
    82  		Summary:              iface.summary,
    83  		DocURL:               iface.docURL,
    84  		ImplicitOnCore:       iface.implicitOnCore,
    85  		ImplicitOnClassic:    iface.implicitOnClassic,
    86  		BaseDeclarationPlugs: iface.baseDeclarationPlugs,
    87  		BaseDeclarationSlots: iface.baseDeclarationSlots,
    88  	}
    89  }
    90  
    91  func (iface *commonInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    92  	if iface.usesPtraceTrace {
    93  		spec.SetUsesPtraceTrace()
    94  	} else if iface.suppressPtraceTrace {
    95  		spec.SetSuppressPtraceTrace()
    96  	}
    97  	if iface.suppressHomeIx {
    98  		spec.SetSuppressHomeIx()
    99  	}
   100  	if snippet := iface.connectedPlugAppArmor; snippet != "" {
   101  		spec.AddSnippet(snippet)
   102  	}
   103  	if snippet := iface.connectedPlugUpdateNSAppArmor; snippet != "" {
   104  		spec.AddUpdateNS(snippet)
   105  	}
   106  	return nil
   107  }
   108  
   109  // AutoConnect returns whether plug and slot should be implicitly
   110  // auto-connected assuming they will be an unambiguous connection
   111  // candidate and declaration-based checks allow.
   112  //
   113  // By default we allow what declarations allowed.
   114  func (iface *commonInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool {
   115  	return !iface.rejectAutoConnectPairs
   116  }
   117  
   118  func (iface *commonInterface) KModConnectedPlug(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   119  	for _, m := range iface.connectedPlugKModModules {
   120  		if err := spec.AddModule(m); err != nil {
   121  			return err
   122  		}
   123  	}
   124  	return nil
   125  }
   126  
   127  func (iface *commonInterface) KModConnectedSlot(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   128  	for _, m := range iface.connectedSlotKModModules {
   129  		if err := spec.AddModule(m); err != nil {
   130  			return err
   131  		}
   132  	}
   133  	return nil
   134  }
   135  
   136  func (iface *commonInterface) MountConnectedPlug(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   137  	for _, entry := range iface.connectedPlugMount {
   138  		if err := spec.AddMountEntry(entry); err != nil {
   139  			return err
   140  		}
   141  	}
   142  	return nil
   143  }
   144  
   145  func (iface *commonInterface) KModPermanentPlug(spec *kmod.Specification, plug *snap.PlugInfo) error {
   146  	for _, m := range iface.permanentPlugKModModules {
   147  		if err := spec.AddModule(m); err != nil {
   148  			return err
   149  		}
   150  	}
   151  	return nil
   152  }
   153  
   154  func (iface *commonInterface) KModPermanentSlot(spec *kmod.Specification, slot *snap.SlotInfo) error {
   155  	for _, m := range iface.permanentSlotKModModules {
   156  		if err := spec.AddModule(m); err != nil {
   157  			return err
   158  		}
   159  	}
   160  	return nil
   161  }
   162  
   163  func (iface *commonInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   164  	if iface.connectedPlugSecComp != "" {
   165  		spec.AddSnippet(iface.connectedPlugSecComp)
   166  	}
   167  	return nil
   168  }
   169  
   170  func (iface *commonInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   171  	// don't tag devices if the interface controls it's own device cgroup
   172  	if iface.controlsDeviceCgroup {
   173  		spec.SetControlsDeviceCgroup()
   174  	} else {
   175  		for _, rule := range iface.connectedPlugUDev {
   176  			spec.TagDevice(rule)
   177  		}
   178  	}
   179  
   180  	return nil
   181  }