From 364da01b5be63a2f992fb6e8e293ab87e84d70dd Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Mon, 29 Jul 2024 14:42:12 +0200 Subject: [PATCH] interfaces/builtin/gpio_control: add support for accessing gpiochip* devices (#14244) * interfaces/builtin/gpio_control: add support for /dev/gipochip* devices Add supported for /dev/gpiochip* devices implementing the new GPIO character device kernel APIs. Signed-off-by: Maciej Borzecki * tests/lib/snaps/store/test-snapd-gpio-control: snap for testing gpio-control interface Signed-off-by: Maciej Borzecki * tests/main/interfaces-gpio-control: add spread test for gpio-control with simulated GPIO Signed-off-by: Maciej Borzecki * tests/lib/snaps/test-snapd-policy-app-consumer: remove gpio-control since we have a dedicated test Signed-off-by: Maciej Borzecki --------- Signed-off-by: Maciej Borzecki --- interfaces/builtin/gpio_control.go | 12 ++++ .../store/test-snapd-gpio-control/bin/cmd | 3 + .../test-snapd-gpio-control/snapcraft.yaml | 46 +++++++++++++++ .../meta/snap.yaml | 3 - tests/main/interfaces-gpio-control/task.yaml | 59 +++++++++++++++++++ 5 files changed, 120 insertions(+), 3 deletions(-) create mode 100755 tests/lib/snaps/store/test-snapd-gpio-control/bin/cmd create mode 100644 tests/lib/snaps/store/test-snapd-gpio-control/snapcraft.yaml create mode 100644 tests/main/interfaces-gpio-control/task.yaml diff --git a/interfaces/builtin/gpio_control.go b/interfaces/builtin/gpio_control.go index b1bb84457ed..a17f5528d14 100644 --- a/interfaces/builtin/gpio_control.go +++ b/interfaces/builtin/gpio_control.go @@ -38,17 +38,28 @@ const gpioControlBaseDeclarationSlots = ` deny-auto-connection: true ` +// TODO extend apparmor pattern to allow /sys/devices/platform/gpio-sim.[0-9]* +// for better spread testing const gpioControlConnectedPlugAppArmor = ` # Description: Allow controlling all aspects of GPIO pins. This can potentially # impact the system and other snaps, and allows privileged access to hardware. +# Access through legacy sysfs interface /sys/class/gpio/{,un}export rw, /sys/class/gpio/gpio[0-9]*/{active_low,direction,value,edge} rw, # apparmor needs the symlink targets which on most platforms the path # below (see also PR#12816) /sys/devices/platform/**/gpio/gpio[0-9]*/{active_low,direction,value,edge} rw, + +# Access through gpiod interface +# see https://www.kernel.org/doc/html/latest/userspace-api/gpio/chardev.html +/dev/gpiochip[0-9]* rw, ` +var gpioControlConnectedPlugUDev = []string{ + `SUBSYSTEM=="gpio", KERNEL=="gpiochip[0-9]*"`, +} + func init() { registerIface(&commonInterface{ name: "gpio-control", @@ -58,5 +69,6 @@ func init() { baseDeclarationPlugs: gpioControlBaseDeclarationPlugs, baseDeclarationSlots: gpioControlBaseDeclarationSlots, connectedPlugAppArmor: gpioControlConnectedPlugAppArmor, + connectedPlugUDev: gpioControlConnectedPlugUDev, }) } diff --git a/tests/lib/snaps/store/test-snapd-gpio-control/bin/cmd b/tests/lib/snaps/store/test-snapd-gpio-control/bin/cmd new file mode 100755 index 00000000000..5fc44481d23 --- /dev/null +++ b/tests/lib/snaps/store/test-snapd-gpio-control/bin/cmd @@ -0,0 +1,3 @@ +#!/bin/bash + +exec "$@" diff --git a/tests/lib/snaps/store/test-snapd-gpio-control/snapcraft.yaml b/tests/lib/snaps/store/test-snapd-gpio-control/snapcraft.yaml new file mode 100644 index 00000000000..c437f8000dd --- /dev/null +++ b/tests/lib/snaps/store/test-snapd-gpio-control/snapcraft.yaml @@ -0,0 +1,46 @@ +name: test-snapd-gpio-control +version: "1.0" +summary: Basic gpio-control snap +description: A basic snap which access to gpiod device +grade: stable +confinement: strict +base: core24 + +apps: + gpiodetect: + command: usr/bin/gpiodetect + plugs: [gpio-control] + + gpioinfo: + command: usr/bin/gpioinfo + plugs: [gpio-control] + + cmd: + command: bin/cmd + plugs: [gpio-control] + +parts: + libgpiod: + source: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/snapshot/libgpiod-2.1.2.tar.gz + plugin: autotools + autotools-configure-parameters: + - --prefix=/usr + - --enable-tools=yes + build-packages: + - build-essential + - autoconf-archive + - autoconf + - automake + - libtool + - pkg-config + stage: + - -usr/lib/libgpiod.a + - -usr/lib/libgpiod.la + - -usr/include + - -usr/lib/pkgconfig + + cmd: + plugin: dump + source: . + override-build: | + install -D -m 755 -t "${CRAFT_PART_INSTALL}/bin" bin/cmd diff --git a/tests/lib/snaps/test-snapd-policy-app-consumer/meta/snap.yaml b/tests/lib/snaps/test-snapd-policy-app-consumer/meta/snap.yaml index ed9eb0bf999..a808e59b43d 100644 --- a/tests/lib/snaps/test-snapd-policy-app-consumer/meta/snap.yaml +++ b/tests/lib/snaps/test-snapd-policy-app-consumer/meta/snap.yaml @@ -71,9 +71,6 @@ apps: gconf: command: bin/run plugs: [ gconf ] - gpio-control: - command: bin/run - plugs: [ gpio-control ] greengrass-support: command: bin/run plugs: [ greengrass-support ] diff --git a/tests/main/interfaces-gpio-control/task.yaml b/tests/main/interfaces-gpio-control/task.yaml new file mode 100644 index 00000000000..e8c653a8d8c --- /dev/null +++ b/tests/main/interfaces-gpio-control/task.yaml @@ -0,0 +1,59 @@ +summary: Ensure that the GPIO control interface works. + +details: | + The gpio-control interface allows read/write access to GPIO devices. + +# TODO: extend to support ubuntu-core VM, but gpio-sim module is not included in the pc-kernel +# TODO: extend to support ubuntu-core-arm +# TODO: extend the test to cover PI +systems: [ubuntu-24.04-*] + +prepare: | + # set up a simulated GPIO device, see + # https://www.kernel.org/doc/html/latest/admin-guide/gpio/gpio-sim.html + apt install -y "linux-modules-extra-$(uname -r)" + modprobe gpio-sim + mkdir /sys/kernel/config/gpio-sim/snaptest + mkdir /sys/kernel/config/gpio-sim/snaptest/gpio-bank0 + mkdir /sys/kernel/config/gpio-sim/snaptest/gpio-bank0/line0 + echo snap-test > /sys/kernel/config/gpio-sim/snaptest/gpio-bank0/line0/name + echo 1 > /sys/kernel/config/gpio-sim/snaptest/live + + echo "Given the test-snapd-gpio-control snap is installed" + snap install test-snapd-gpio-control + +restore: | + echo 0 > /sys/kernel/config/gpio-sim/snaptest/live || true + rmdir /sys/kernel/config/gpio-sim/snaptest/gpio-bank0/line0 || true + rmdir /sys/kernel/config/gpio-sim/snaptest/gpio-bank0 || true + rmdir /sys/kernel/config/gpio-sim/snaptest || true + rmmod gpio-sim || true + +execute: | + echo "The interface is not connected by default" + #shellcheck disable=SC1117 + snap connections test-snapd-gpio-control | MATCH '^gpio-control +test-snapd-gpio-control:gpio-control +-' + + echo "When the interface is connected" + snap connect test-snapd-gpio-control:gpio-control + + echo "Then the snap is able list GPIO devices" + # example gpiodetect output: + # gpiochip0 [pinctrl-bcm2711] (58 lines) + # gpiochip1 [raspberrypi-exp-gpio] (8 lines) + # there could be additional devices already present + test-snapd-gpio-control.gpiodetect | MATCH 'gpiochip[0-9]+ .* \(.* lines\)' + # and our gpio sim device + test-snapd-gpio-control.gpiodetect | MATCH 'gpiochip[0-9]+ .*gpio-sim.* \(1 lines\)' + # and we can list lines + test-snapd-gpio-control.gpioinfo | MATCH 'line\s+0:\s+"snap-test"' + + echo "When the plug is disconnected" + snap disconnect test-snapd-gpio-control:gpio-control + + echo "Then the snap is not able to access the GPIO devices" + if test-snapd-gpio-control.gpiodetect 2> call.error; then + echo "Expected permission error with disconnected plug" + exit 1 + fi + MATCH "unable to open chip '/dev/gpiochip[0-9]+': Operation not permitted" < call.error