github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/builtin/iio.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 builtin 21 22 import ( 23 "fmt" 24 "path/filepath" 25 "regexp" 26 "strings" 27 28 "github.com/snapcore/snapd/interfaces" 29 "github.com/snapcore/snapd/interfaces/apparmor" 30 "github.com/snapcore/snapd/interfaces/udev" 31 "github.com/snapcore/snapd/snap" 32 ) 33 34 const iioSummary = `allows access to a specific IIO device` 35 36 const iioBaseDeclarationSlots = ` 37 iio: 38 allow-installation: 39 slot-snap-type: 40 - gadget 41 - core 42 deny-auto-connection: true 43 ` 44 45 const iioConnectedPlugAppArmor = ` 46 # Description: Give access to a specific IIO device on the system. 47 48 ###IIO_DEVICE_PATH### rw, 49 /sys/bus/iio/devices/###IIO_DEVICE_NAME###/ r, 50 /sys/bus/iio/devices/###IIO_DEVICE_NAME###/** rwk, 51 /sys/devices/**/###IIO_DEVICE_NAME###/ r, 52 /sys/devices/**/###IIO_DEVICE_NAME###/** rwk, 53 ` 54 55 // The type for iio interface 56 type iioInterface struct{} 57 58 // Getter for the name of the iio interface 59 func (iface *iioInterface) Name() string { 60 return "iio" 61 } 62 63 func (iface *iioInterface) StaticInfo() interfaces.StaticInfo { 64 return interfaces.StaticInfo{ 65 Summary: iioSummary, 66 BaseDeclarationSlots: iioBaseDeclarationSlots, 67 } 68 } 69 70 func (iface *iioInterface) String() string { 71 return iface.Name() 72 } 73 74 // Pattern to match allowed iio device nodes. It is going to be used to check the 75 // validity of the path attributes in case the udev is not used for 76 // identification 77 var iioControlDeviceNodePattern = regexp.MustCompile("^/dev/iio:device[0-9]+$") 78 79 // Check validity of the defined slot 80 func (iface *iioInterface) BeforePrepareSlot(slot *snap.SlotInfo) error { 81 // Validate the path 82 path, ok := slot.Attrs["path"].(string) 83 if !ok || path == "" { 84 return fmt.Errorf("%s slot must have a path attribute", iface.Name()) 85 } 86 87 path = filepath.Clean(path) 88 89 if !iioControlDeviceNodePattern.MatchString(path) { 90 return fmt.Errorf("%s path attribute must be a valid device node", iface.Name()) 91 } 92 93 return nil 94 } 95 96 func (iface *iioInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 97 var path string 98 if err := slot.Attr("path", &path); err != nil { 99 return nil 100 } 101 102 cleanedPath := filepath.Clean(path) 103 snippet := strings.Replace(iioConnectedPlugAppArmor, "###IIO_DEVICE_PATH###", cleanedPath, -1) 104 105 // The path is already verified against a regular expression 106 // in BeforePrepareSlot so we can rely on its structure here and 107 // safely strip the '/dev/' prefix to get the actual name of 108 // the IIO device. 109 deviceName := strings.TrimPrefix(path, "/dev/") 110 snippet = strings.Replace(snippet, "###IIO_DEVICE_NAME###", deviceName, -1) 111 112 spec.AddSnippet(snippet) 113 return nil 114 } 115 116 func (iface *iioInterface) UDevConnectedPlug(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 117 var path string 118 if err := slot.Attr("path", &path); err != nil { 119 return nil 120 } 121 spec.TagDevice(fmt.Sprintf(`KERNEL=="%s"`, strings.TrimPrefix(path, "/dev/"))) 122 return nil 123 } 124 125 func (iface *iioInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 126 // Allow what is allowed in the declarations 127 return true 128 } 129 130 func init() { 131 registerIface(&iioInterface{}) 132 }