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 }