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