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