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