github.com/ubuntu-core/snappy@v0.0.0-20210827154228-9e584df982bb/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  	affectsPlugOnRefresh bool
    53  
    54  	baseDeclarationPlugs string
    55  	baseDeclarationSlots string
    56  
    57  	connectedPlugAppArmor  string
    58  	connectedPlugSecComp   string
    59  	connectedPlugUDev      []string
    60  	rejectAutoConnectPairs bool
    61  
    62  	connectedPlugUpdateNSAppArmor string
    63  	connectedPlugMount            []osutil.MountEntry
    64  
    65  	connectedPlugKModModules []string
    66  	connectedSlotKModModules []string
    67  	permanentPlugKModModules []string
    68  	permanentSlotKModModules []string
    69  
    70  	usesPtraceTrace      bool
    71  	suppressPtraceTrace  bool
    72  	suppressHomeIx       bool
    73  	controlsDeviceCgroup bool
    74  
    75  	serviceSnippets []string
    76  }
    77  
    78  // Name returns the interface name.
    79  func (iface *commonInterface) Name() string {
    80  	return iface.name
    81  }
    82  
    83  // StaticInfo returns various meta-data about this interface.
    84  func (iface *commonInterface) StaticInfo() interfaces.StaticInfo {
    85  	return interfaces.StaticInfo{
    86  		Summary:              iface.summary,
    87  		DocURL:               iface.docURL,
    88  		ImplicitOnCore:       iface.implicitOnCore,
    89  		ImplicitOnClassic:    iface.implicitOnClassic,
    90  		BaseDeclarationPlugs: iface.baseDeclarationPlugs,
    91  		BaseDeclarationSlots: iface.baseDeclarationSlots,
    92  		// affects the plug snap because of mount backend
    93  		AffectsPlugOnRefresh: iface.affectsPlugOnRefresh,
    94  	}
    95  }
    96  
    97  func (iface *commonInterface) ServicePermanentPlug(plug *snap.PlugInfo) []string {
    98  	return iface.serviceSnippets
    99  }
   100  
   101  func (iface *commonInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   102  	if iface.usesPtraceTrace {
   103  		spec.SetUsesPtraceTrace()
   104  	} else if iface.suppressPtraceTrace {
   105  		spec.SetSuppressPtraceTrace()
   106  	}
   107  	if iface.suppressHomeIx {
   108  		spec.SetSuppressHomeIx()
   109  	}
   110  	if snippet := iface.connectedPlugAppArmor; snippet != "" {
   111  		spec.AddSnippet(snippet)
   112  	}
   113  	if snippet := iface.connectedPlugUpdateNSAppArmor; snippet != "" {
   114  		spec.AddUpdateNS(snippet)
   115  	}
   116  	return nil
   117  }
   118  
   119  // AutoConnect returns whether plug and slot should be implicitly
   120  // auto-connected assuming they will be an unambiguous connection
   121  // candidate and declaration-based checks allow.
   122  //
   123  // By default we allow what declarations allowed.
   124  func (iface *commonInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool {
   125  	return !iface.rejectAutoConnectPairs
   126  }
   127  
   128  func (iface *commonInterface) KModConnectedPlug(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   129  	for _, m := range iface.connectedPlugKModModules {
   130  		if err := spec.AddModule(m); err != nil {
   131  			return err
   132  		}
   133  	}
   134  	return nil
   135  }
   136  
   137  func (iface *commonInterface) KModConnectedSlot(spec *kmod.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   138  	for _, m := range iface.connectedSlotKModModules {
   139  		if err := spec.AddModule(m); err != nil {
   140  			return err
   141  		}
   142  	}
   143  	return nil
   144  }
   145  
   146  func (iface *commonInterface) MountConnectedPlug(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   147  	for _, entry := range iface.connectedPlugMount {
   148  		if err := spec.AddMountEntry(entry); err != nil {
   149  			return err
   150  		}
   151  	}
   152  	return nil
   153  }
   154  
   155  func (iface *commonInterface) KModPermanentPlug(spec *kmod.Specification, plug *snap.PlugInfo) error {
   156  	for _, m := range iface.permanentPlugKModModules {
   157  		if err := spec.AddModule(m); err != nil {
   158  			return err
   159  		}
   160  	}
   161  	return nil
   162  }
   163  
   164  func (iface *commonInterface) KModPermanentSlot(spec *kmod.Specification, slot *snap.SlotInfo) error {
   165  	for _, m := range iface.permanentSlotKModModules {
   166  		if err := spec.AddModule(m); err != nil {
   167  			return err
   168  		}
   169  	}
   170  	return nil
   171  }
   172  
   173  func (iface *commonInterface) SecCompConnectedPlug(spec *seccomp.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   174  	if iface.connectedPlugSecComp != "" {
   175  		spec.AddSnippet(iface.connectedPlugSecComp)
   176  	}
   177  	return nil
   178  }
   179  
   180  func (iface *commonInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   181  	// don't tag devices if the interface controls it's own device cgroup
   182  	if iface.controlsDeviceCgroup {
   183  		spec.SetControlsDeviceCgroup()
   184  	} else {
   185  		for _, rule := range iface.connectedPlugUDev {
   186  			spec.TagDevice(rule)
   187  		}
   188  	}
   189  
   190  	return nil
   191  }