github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/builtin/appstream_metadata.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2019 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  	"path/filepath"
    24  
    25  	"github.com/snapcore/snapd/dirs"
    26  	"github.com/snapcore/snapd/interfaces"
    27  	"github.com/snapcore/snapd/interfaces/apparmor"
    28  	"github.com/snapcore/snapd/interfaces/mount"
    29  	"github.com/snapcore/snapd/osutil"
    30  )
    31  
    32  const appstreamMetadataSummary = `allows access to AppStream metadata`
    33  
    34  const appstreamMetadataBaseDeclarationSlots = `
    35    appstream-metadata:
    36      allow-installation:
    37        slot-snap-type:
    38          - core
    39      deny-auto-connection: true
    40  `
    41  
    42  // Paths for upstream and collection metadata are defined in the
    43  // AppStream specification:
    44  //   https://www.freedesktop.org/software/appstream/docs/
    45  const appstreamMetadataConnectedPlugAppArmor = `
    46  # Description: Allow access to AppStream metadata from the host system
    47  
    48  # Allow access to AppStream upstream metadata files
    49  /usr/share/metainfo/** r,
    50  /usr/share/appdata/** r,
    51  
    52  # Allow access to AppStream collection metadata
    53  /usr/share/app-info/** r,
    54  /var/cache/app-info/** r,
    55  /var/lib/app-info/** r,
    56  
    57  # Apt symlinks the DEP-11 metadata to files in /var/lib/apt/lists
    58  /var/lib/apt/lists/*.yml.gz r,
    59  `
    60  
    61  var appstreamMetadataDirs = []string{
    62  	"/usr/share/metainfo",
    63  	"/usr/share/appdata",
    64  	"/usr/share/app-info",
    65  	"/var/cache/app-info",
    66  	"/var/lib/app-info",
    67  	"/var/lib/apt/lists",
    68  }
    69  
    70  type appstreamMetadataInterface struct {
    71  	commonInterface
    72  }
    73  
    74  func (iface *appstreamMetadataInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    75  	spec.AddSnippet(appstreamMetadataConnectedPlugAppArmor)
    76  
    77  	// Generate rules to allow snap-update-ns to do its thing
    78  	emit := spec.EmitUpdateNSFunc()
    79  	for _, target := range appstreamMetadataDirs {
    80  		source := "/var/lib/snapd/hostfs" + target
    81  		emit("  # Read-only access to %s\n", target)
    82  		emit("  mount options=(bind) %s/ -> %s/,\n", source, target)
    83  		emit("  remount options=(bind, ro) %s/,\n", target)
    84  		emit("  umount %s/,\n\n", target)
    85  		// Allow constructing writable mimic to mount point We
    86  		// expect three components to already exist: /, /usr,
    87  		// and /usr/share (or equivalents under /var).
    88  		apparmor.GenWritableProfile(emit, target, 3)
    89  	}
    90  	return nil
    91  }
    92  
    93  func (iface *appstreamMetadataInterface) MountConnectedPlug(spec *mount.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    94  	for _, dir := range appstreamMetadataDirs {
    95  		dir = filepath.Join(dirs.GlobalRootDir, dir)
    96  		if !osutil.IsDirectory(dir) {
    97  			continue
    98  		}
    99  		spec.AddMountEntry(osutil.MountEntry{
   100  			Name:    "/var/lib/snapd/hostfs" + dir,
   101  			Dir:     dirs.StripRootDir(dir),
   102  			Options: []string{"bind", "ro"},
   103  		})
   104  	}
   105  
   106  	return nil
   107  }
   108  
   109  func init() {
   110  	registerIface(&appstreamMetadataInterface{commonInterface{
   111  		name:                 "appstream-metadata",
   112  		summary:              appstreamMetadataSummary,
   113  		implicitOnClassic:    true,
   114  		reservedForOS:        true,
   115  		baseDeclarationSlots: appstreamMetadataBaseDeclarationSlots,
   116  	}})
   117  }