github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/interfaces/seccomp/spec.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016-2017 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 seccomp
    21  
    22  import (
    23  	"bytes"
    24  	"sort"
    25  
    26  	"github.com/snapcore/snapd/interfaces"
    27  	"github.com/snapcore/snapd/snap"
    28  )
    29  
    30  // Specification keeps all the seccomp snippets.
    31  type Specification struct {
    32  	// Snippets are indexed by security tag.
    33  	snippets     map[string][]string
    34  	securityTags []string
    35  }
    36  
    37  // AddSnippet adds a new seccomp snippet.
    38  func (spec *Specification) AddSnippet(snippet string) {
    39  	if len(spec.securityTags) == 0 {
    40  		return
    41  	}
    42  	if spec.snippets == nil {
    43  		spec.snippets = make(map[string][]string)
    44  	}
    45  	for _, tag := range spec.securityTags {
    46  		spec.snippets[tag] = append(spec.snippets[tag], snippet)
    47  	}
    48  }
    49  
    50  // Snippets returns a deep copy of all the added snippets.
    51  func (spec *Specification) Snippets() map[string][]string {
    52  	result := make(map[string][]string, len(spec.snippets))
    53  	for k, v := range spec.snippets {
    54  		vCopy := make([]string, 0, len(v))
    55  		vCopy = append(vCopy, v...)
    56  		result[k] = vCopy
    57  	}
    58  	return result
    59  }
    60  
    61  // SnippetForTag returns a combined snippet for given security tag with individual snippets
    62  // joined with newline character. Empty string is returned for non-existing security tag.
    63  func (spec *Specification) SnippetForTag(tag string) string {
    64  	var buffer bytes.Buffer
    65  	sort.Strings(spec.snippets[tag])
    66  	for _, snippet := range spec.snippets[tag] {
    67  		buffer.WriteString(snippet)
    68  		buffer.WriteRune('\n')
    69  	}
    70  	return buffer.String()
    71  }
    72  
    73  // SecurityTags returns a list of security tags which have a snippet.
    74  func (spec *Specification) SecurityTags() []string {
    75  	var tags []string
    76  	for t := range spec.snippets {
    77  		tags = append(tags, t)
    78  	}
    79  	sort.Strings(tags)
    80  	return tags
    81  }
    82  
    83  // Implementation of methods required by interfaces.Specification
    84  
    85  // AddConnectedPlug records seccomp-specific side-effects of having a connected plug.
    86  func (spec *Specification) AddConnectedPlug(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    87  	type definer interface {
    88  		SecCompConnectedPlug(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    89  	}
    90  	if iface, ok := iface.(definer); ok {
    91  		spec.securityTags = plug.SecurityTags()
    92  		defer func() { spec.securityTags = nil }()
    93  		return iface.SecCompConnectedPlug(spec, plug, slot)
    94  	}
    95  	return nil
    96  }
    97  
    98  // AddConnectedSlot records seccomp-specific side-effects of having a connected slot.
    99  func (spec *Specification) AddConnectedSlot(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   100  	type definer interface {
   101  		SecCompConnectedSlot(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
   102  	}
   103  	if iface, ok := iface.(definer); ok {
   104  		spec.securityTags = slot.SecurityTags()
   105  		defer func() { spec.securityTags = nil }()
   106  		return iface.SecCompConnectedSlot(spec, plug, slot)
   107  	}
   108  	return nil
   109  }
   110  
   111  // AddPermanentPlug records seccomp-specific side-effects of having a plug.
   112  func (spec *Specification) AddPermanentPlug(iface interfaces.Interface, plug *snap.PlugInfo) error {
   113  	type definer interface {
   114  		SecCompPermanentPlug(spec *Specification, plug *snap.PlugInfo) error
   115  	}
   116  	if iface, ok := iface.(definer); ok {
   117  		spec.securityTags = plug.SecurityTags()
   118  		defer func() { spec.securityTags = nil }()
   119  		return iface.SecCompPermanentPlug(spec, plug)
   120  	}
   121  	return nil
   122  }
   123  
   124  // AddPermanentSlot records seccomp-specific side-effects of having a slot.
   125  func (spec *Specification) AddPermanentSlot(iface interfaces.Interface, slot *snap.SlotInfo) error {
   126  	type definer interface {
   127  		SecCompPermanentSlot(spec *Specification, slot *snap.SlotInfo) error
   128  	}
   129  	if iface, ok := iface.(definer); ok {
   130  		spec.securityTags = slot.SecurityTags()
   131  		defer func() { spec.securityTags = nil }()
   132  		return iface.SecCompPermanentSlot(spec, slot)
   133  	}
   134  	return nil
   135  }