github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/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  		for _, vElem := range v {
    56  			vCopy = append(vCopy, vElem)
    57  		}
    58  		result[k] = vCopy
    59  	}
    60  	return result
    61  }
    62  
    63  // SnippetForTag returns a combined snippet for given security tag with individual snippets
    64  // joined with newline character. Empty string is returned for non-existing security tag.
    65  func (spec *Specification) SnippetForTag(tag string) string {
    66  	var buffer bytes.Buffer
    67  	sort.Strings(spec.snippets[tag])
    68  	for _, snippet := range spec.snippets[tag] {
    69  		buffer.WriteString(snippet)
    70  		buffer.WriteRune('\n')
    71  	}
    72  	return buffer.String()
    73  }
    74  
    75  // SecurityTags returns a list of security tags which have a snippet.
    76  func (spec *Specification) SecurityTags() []string {
    77  	var tags []string
    78  	for t := range spec.snippets {
    79  		tags = append(tags, t)
    80  	}
    81  	sort.Strings(tags)
    82  	return tags
    83  }
    84  
    85  // Implementation of methods required by interfaces.Specification
    86  
    87  // AddConnectedPlug records seccomp-specific side-effects of having a connected plug.
    88  func (spec *Specification) AddConnectedPlug(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    89  	type definer interface {
    90  		SecCompConnectedPlug(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
    91  	}
    92  	if iface, ok := iface.(definer); ok {
    93  		spec.securityTags = plug.SecurityTags()
    94  		defer func() { spec.securityTags = nil }()
    95  		return iface.SecCompConnectedPlug(spec, plug, slot)
    96  	}
    97  	return nil
    98  }
    99  
   100  // AddConnectedSlot records seccomp-specific side-effects of having a connected slot.
   101  func (spec *Specification) AddConnectedSlot(iface interfaces.Interface, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   102  	type definer interface {
   103  		SecCompConnectedSlot(spec *Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error
   104  	}
   105  	if iface, ok := iface.(definer); ok {
   106  		spec.securityTags = slot.SecurityTags()
   107  		defer func() { spec.securityTags = nil }()
   108  		return iface.SecCompConnectedSlot(spec, plug, slot)
   109  	}
   110  	return nil
   111  }
   112  
   113  // AddPermanentPlug records seccomp-specific side-effects of having a plug.
   114  func (spec *Specification) AddPermanentPlug(iface interfaces.Interface, plug *snap.PlugInfo) error {
   115  	type definer interface {
   116  		SecCompPermanentPlug(spec *Specification, plug *snap.PlugInfo) error
   117  	}
   118  	if iface, ok := iface.(definer); ok {
   119  		spec.securityTags = plug.SecurityTags()
   120  		defer func() { spec.securityTags = nil }()
   121  		return iface.SecCompPermanentPlug(spec, plug)
   122  	}
   123  	return nil
   124  }
   125  
   126  // AddPermanentSlot records seccomp-specific side-effects of having a slot.
   127  func (spec *Specification) AddPermanentSlot(iface interfaces.Interface, slot *snap.SlotInfo) error {
   128  	type definer interface {
   129  		SecCompPermanentSlot(spec *Specification, slot *snap.SlotInfo) error
   130  	}
   131  	if iface, ok := iface.(definer); ok {
   132  		spec.securityTags = slot.SecurityTags()
   133  		defer func() { spec.securityTags = nil }()
   134  		return iface.SecCompPermanentSlot(spec, slot)
   135  	}
   136  	return nil
   137  }