diff --git a/.gitignore b/.gitignore index 00538f1..4cab908 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,5 @@ /snapd_2.53.1.only-vendor.tar.xz /snapd_2.53.2.no-vendor.tar.xz /snapd_2.53.2.only-vendor.tar.xz +/snapd_2.53.4.no-vendor.tar.xz +/snapd_2.53.4.only-vendor.tar.xz diff --git a/0001-cmd-libsnap-confine-private-fix-snap-device-helper-d.patch b/0001-cmd-libsnap-confine-private-fix-snap-device-helper-d.patch deleted file mode 100644 index 44a77c6..0000000 --- a/0001-cmd-libsnap-confine-private-fix-snap-device-helper-d.patch +++ /dev/null @@ -1,369 +0,0 @@ -From 5f18b1be0f2ce492017cf19a0ad9dd52248283ba Mon Sep 17 00:00:00 2001 -Message-Id: <5f18b1be0f2ce492017cf19a0ad9dd52248283ba.1638186196.git.maciej.zenon.borzecki@canonical.com> -From: Maciej Borzecki -Date: Fri, 26 Nov 2021 08:58:57 +0100 -Subject: [PATCH] cmd/libsnap-confine-private: fix snap-device-helper device - allow list modification on cgroup v2 - -* cmd/libsnap-confine-private: split attaching BPF program to own cgroup - -Split attaching the BPF filtering program to own cgroup, such that the process -of setting up the map, loading device acecsses is not mixed with locking down -own cgroup. This makes the cgroup v2 setup even closer to v1, and fixes -snap-device-helper which tried to verify own cgroup during initialization what -prevented it from properly responding to device events. - -Signed-off-by: Maciej Borzecki - -* tests/main/security-device-cgroups-helper: spread test for snap-device-helper - -Signed-off-by: Maciej Borzecki - -* cmd/libsnap-confine-private: tweak variable naming - -Signed-off-by: Maciej Borzecki - -* tests/main/security-device-cgroups-helper: comment tweaks - -Signed-off-by: Maciej Borzecki ---- - .../device-cgroup-support.c | 100 ++++++++++------ - .../security-device-cgroups-helper/task.yaml | 109 ++++++++++++++++++ - .../test-strict-cgroup-helper/bin/sh | 3 + - .../test-strict-cgroup-helper/meta/snap.yaml | 8 ++ - 4 files changed, 183 insertions(+), 37 deletions(-) - create mode 100644 tests/main/security-device-cgroups-helper/task.yaml - create mode 100755 tests/main/security-device-cgroups-helper/test-strict-cgroup-helper/bin/sh - create mode 100644 tests/main/security-device-cgroups-helper/test-strict-cgroup-helper/meta/snap.yaml - -diff --git a/cmd/libsnap-confine-private/device-cgroup-support.c b/cmd/libsnap-confine-private/device-cgroup-support.c -index 5557179745de49b93ab2354e0ccb876c9d5ebde9..e215632b3a782464d7545dc48ca1272ea94dbf79 100644 ---- a/cmd/libsnap-confine-private/device-cgroup-support.c -+++ b/cmd/libsnap-confine-private/device-cgroup-support.c -@@ -57,8 +57,8 @@ struct sc_device_cgroup { - sc_cgroup_fds fds; - } v1; - struct { -- int cgroup_fd; - int devmap_fd; -+ int prog_fd; - char *tag; - struct rlimit old_limit; - } v2; -@@ -82,13 +82,13 @@ static int _sc_cgroup_v1_init(sc_device_cgroup *self, int flags) { - } - die("cannot prepare cgroup v1 device hierarchy"); - } -- /* Only deny devices if we are not using an existing group - -+ /* Only deny devices if we are not using an existing group - - * if we deny devices for an existing group that we just opened, - * we risk denying access to a device that a currently running process - * is about to access and should legitimately have access to. - * A concrete example of this is when this function is used by snap-device-helper - * when a new udev device event is triggered and we are adding that device -- * to the snap's device cgroup. At this point, a running application may be -+ * to the snap's device cgroup. At this point, a running application may be - * accessing other devices which it should have access to (such as /dev/null - * or one of the other common, default devices) we would deny access to that - * existing device by re-creating the allow list of devices every time. -@@ -148,11 +148,6 @@ typedef struct sc_cgroup_v2_device_key sc_cgroup_v2_device_key; - */ - typedef uint8_t sc_cgroup_v2_device_value; - --static void _sc_cgroup_v2_attach_pid(sc_device_cgroup *self, pid_t pid) { -- /* nothing to do here, the device controller is attached to the cgroup -- * already, and we are part of it */ --} -- - #ifdef ENABLE_BPF - static int load_devcgroup_prog(int map_fd) { - /* Basic rules about registers: -@@ -316,34 +311,13 @@ static bool _sc_is_snap_cgroup(const char *group) { - - static int _sc_cgroup_v2_init_bpf(sc_device_cgroup *self, int flags) { - self->v2.devmap_fd = -1; -- self->v2.cgroup_fd = -1; -- -- char *own_group SC_CLEANUP(sc_cleanup_string) = sc_cgroup_v2_own_path_full(); -- if (own_group == NULL) { -- die("cannot obtain own group path"); -- } -- debug("process in cgroup %s", own_group); -- if (!_sc_is_snap_cgroup(own_group)) { -- /* we cannot proceed to install a device filtering program when the -- * process is not in a snap specific cgroup, as we would effectively -- * lock down the group that can be shared with other processes or even -- * the whole desktop session */ -- die("%s is not a snap cgroup", own_group); -- } -+ self->v2.prog_fd = -1; - - /* fix the memlock limit if needed, this affects creating maps */ - self->v2.old_limit = _sc_cgroup_v2_adjust_memlock_limit(); - - const bool from_existing = (flags & SC_DEVICE_CGROUP_FROM_EXISTING) != 0; - -- char own_group_full[PATH_MAX] = {0}; -- sc_must_snprintf(own_group_full, sizeof(own_group_full), "/sys/fs/cgroup/%s", own_group); -- int cgroup_fd = open(own_group_full, O_PATH | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); -- if (cgroup_fd < 0) { -- die("cannot open own cgroup directory %s", own_group_full); -- } -- debug("cgroup %s opened at %d", own_group_full, cgroup_fd); -- - self->v2.tag = sc_strdup(self->security_tag); - /* bpffs is unhappy about dots in the name, replace all with underscores */ - for (char *c = strchr(self->v2.tag, '.'); c != NULL; c = strchr(c, '.')) { -@@ -363,14 +337,19 @@ static int _sc_cgroup_v2_init_bpf(sc_device_cgroup *self, int flags) { - } - /* and obtain a file descriptor to the map, also as root */ - int devmap_fd = bpf_get_by_path(path); -+ /* keep a copy of errno in case it gets clobbered */ -+ int get_by_path_errno = errno; - (void)sc_set_effective_identity(old); - /* XXX: this should be more than enough keys */ - const size_t max_entries = 500; - if (devmap_fd < 0) { -- if (errno != ENOENT) { -+ if (get_by_path_errno != ENOENT) { - die("cannot get existing device map"); - } - if (from_existing) { -+ debug("device map not present, not creating one"); -+ /* restore the errno so that the caller sees ENOENT */ -+ errno = get_by_path_errno; - /* there is no map, and we haven't been asked to setup a new cgroup */ - return -1; - } -@@ -464,15 +443,12 @@ static int _sc_cgroup_v2_init_bpf(sc_device_cgroup *self, int flags) { - /* load and attach the BPF program as root */ - (void)sc_set_effective_identity(sc_root_group_identity()); - int prog_fd = load_devcgroup_prog(devmap_fd); -- int attach = bpf_prog_attach(BPF_CGROUP_DEVICE, cgroup_fd, prog_fd); -- if (attach < 0) { -- die("cannot attach cgroup program"); -- } - (void)sc_set_effective_identity(old); -+ /* keep track of the program */ -+ self->v2.prog_fd = prog_fd; - } - - self->v2.devmap_fd = devmap_fd; -- self->v2.cgroup_fd = cgroup_fd; - - return 0; - } -@@ -485,7 +461,7 @@ static void _sc_cgroup_v2_close_bpf(sc_device_cgroup *self) { - /* the map is pinned to a per-snap-application file and referenced by the - * program */ - sc_cleanup_close(&self->v2.devmap_fd); -- sc_cleanup_close(&self->v2.cgroup_fd); -+ sc_cleanup_close(&self->v2.prog_fd); - } - - static void _sc_cgroup_v2_allow_bpf(sc_device_cgroup *self, int kind, int major, int minor) { -@@ -512,6 +488,48 @@ static void _sc_cgroup_v2_deny_bpf(sc_device_cgroup *self, int kind, int major, - die("cannot delete device map entry for key %c %u:%u", key.type, key.major, key.minor); - } - } -+ -+static void _sc_cgroup_v2_attach_pid_bpf(sc_device_cgroup *self, pid_t pid) { -+ /* we are setting up device filtering for ourselves */ -+ if (pid != getpid()) { -+ die("internal error: cannot attach device cgroup to other process than current"); -+ } -+ if (self->v2.prog_fd == -1) { -+ die("internal error: BPF program not loaded"); -+ } -+ -+ char *own_group SC_CLEANUP(sc_cleanup_string) = sc_cgroup_v2_own_path_full(); -+ if (own_group == NULL) { -+ die("cannot obtain own group path"); -+ } -+ debug("process in cgroup %s", own_group); -+ -+ if (!_sc_is_snap_cgroup(own_group)) { -+ /* we cannot proceed to install a device filtering program when the -+ * process is not in a snap specific cgroup, as we would effectively -+ * lock down the group that can be shared with other processes or even -+ * the whole desktop session */ -+ die("%s is not a snap cgroup", own_group); -+ } -+ -+ char own_group_full_path[PATH_MAX] = {0}; -+ sc_must_snprintf(own_group_full_path, sizeof(own_group_full_path), "/sys/fs/cgroup/%s", own_group); -+ -+ int cgroup_fd SC_CLEANUP(sc_cleanup_close) = -1; -+ cgroup_fd = open(own_group_full_path, O_PATH | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); -+ if (cgroup_fd < 0) { -+ die("cannot open own cgroup directory %s", own_group_full_path); -+ } -+ debug("cgroup %s opened at %d", own_group_full_path, cgroup_fd); -+ -+ /* attach the program to the cgroup */ -+ sc_identity old = sc_set_effective_identity(sc_root_group_identity()); -+ int attach = bpf_prog_attach(BPF_CGROUP_DEVICE, cgroup_fd, self->v2.prog_fd); -+ (void)sc_set_effective_identity(old); -+ if (attach < 0) { -+ die("cannot attach cgroup program"); -+ } -+} - #endif /* ENABLE_BPF */ - - static void _sc_cgroup_v2_close(sc_device_cgroup *self) { -@@ -536,6 +554,14 @@ static void _sc_cgroup_v2_deny(sc_device_cgroup *self, int kind, int major, int - #endif - } - -+static void _sc_cgroup_v2_attach_pid(sc_device_cgroup *self, pid_t pid) { -+#ifdef ENABLE_BPF -+ _sc_cgroup_v2_attach_pid_bpf(self, pid); -+#else -+ die("device cgroup v2 is not enabled"); -+#endif -+} -+ - static int _sc_cgroup_v2_init(sc_device_cgroup *self, int flags) { - #ifdef ENABLE_BPF - return _sc_cgroup_v2_init_bpf(self, flags); -diff --git a/tests/main/security-device-cgroups-helper/task.yaml b/tests/main/security-device-cgroups-helper/task.yaml -new file mode 100644 -index 0000000000000000000000000000000000000000..3d8caaf031dca2960f6e60c5c5efe9347b23695c ---- /dev/null -+++ b/tests/main/security-device-cgroups-helper/task.yaml -@@ -0,0 +1,109 @@ -+summary: Check that snap-device-helper operates correctly -+ -+details: | -+ The test verifies that snap-device-helper correctly modifies the cgroups -+ -+environment: -+ # note that /dev/full has well known major:minor which is 1:7 -+ DEVICES_PATH_MEM_FULL: /devices/virtual/mem/full -+ # and /dev/kmsg has 1:11 -+ DEVICES_PATH_MEM_KMSG: /devices/virtual/mem/kmsg -+ -+execute: | -+ #shellcheck source=tests/lib/systems.sh -+ . "$TESTSLIB/systems.sh" -+ libexecdir=$(os.paths libexec-dir) -+ -+ echo "Given a snap is installed" -+ "$TESTSTOOLS"/snaps-state install-local test-strict-cgroup-helper -+ -+ echo "Verify that no devices are assigned to that snap" -+ udevadm info "/sys/$DEVICES_PATH_MEM_FULL" | NOMATCH "E: (CURRENT_)?TAGS=.*snap_test-strict-cgroup-helper_sh" -+ udevadm info "/sys/$DEVICES_PATH_MEM_KMSG" | NOMATCH "E: (CURRENT_)?TAGS=.*snap_test-strict-cgroup-helper_sh" -+ -+ echo "Force a device cgroup to be assigned to a snap" -+ # this will assign the /dev/full device to a snap -+ content='KERNEL=="full", TAG+="snap_test-strict-cgroup-helper_sh" ' -+ echo "$content" > /etc/udev/rules.d/70-snap.test-strict-cgroup-helper.rules -+ udevadm control --reload-rules -+ udevadm settle -+ udevadm trigger -+ udevadm settle -+ -+ # /dev/full is now tagged for the snap -+ udevadm info "/sys/$DEVICES_PATH_MEM_FULL" | MATCH "E: (CURRENT_)?TAGS=.*snap_test-strict-cgroup-helper_sh" -+ # but /dev/kmsg is not -+ udevadm info "/sys/$DEVICES_PATH_MEM_KMSG" | NOMATCH "E: (CURRENT_)?TAGS=.*snap_test-strict-cgroup-helper_sh" -+ -+ # the apparmor profile prevents the app from accessing /dev/kmsg workaround -+ # it by switching the profile to complain -+ if aa-status && test -e /var/lib/snapd/apparmor/profiles/snap.test-strict-cgroup-helper.sh; then -+ sed -i -e 's/attach_disconnected,/attach_disconnected,complain,/' \ -+ /var/lib/snapd/apparmor/profiles/snap.test-strict-cgroup-helper.sh -+ apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.test-strict-cgroup-helper.sh -+ fi -+ -+ snap run test-strict-cgroup-helper.sh -c 'echo hello' -+ -+ # explicitly verify that the right cgroup path exists, which is either -+ # /sys/fs/cgroup/devices/snap.test-strict-cgroup-helper.sh or -+ # /sys/fs/bpf/snap/test-strict-cgroup-helper_sh -+ if is_cgroupv2; then -+ test -e /sys/fs/bpf/snap/snap_test-strict-cgroup-helper_sh -+ else -+ test -e /sys/fs/cgroup/devices/snap.test-strict-cgroup-helper.sh -+ fi -+ -+ tests.device-cgroup test-strict-cgroup-helper.sh dump | MATCH 'c 1:7 rwm' -+ # /dev/kmsg is not added -+ tests.device-cgroup test-strict-cgroup-helper.sh dump | NOMATCH 'c 1:11 rwm' -+ # and it's not possible to read /dev/kmsg -+ snap run test-strict-cgroup-helper.sh -c 'head -1 /dev/kmsg' 2>&1 | MATCH "Operation not permitted" -+ -+ # snap-device-helper is invoked by udev as: -+ # RUN+="$libexecdir/snapd/snap-device-helper $env{ACTION} snap_test-strict-cgroup-helper_sh $devpath $major:$minor" -+ -+ "$libexecdir"/snapd/snap-device-helper add snap_test-strict-cgroup-helper_sh "$DEVICES_PATH_MEM_FULL" 1:7 -+ "$libexecdir"/snapd/snap-device-helper change snap_test-strict-cgroup-helper_sh "$DEVICES_PATH_MEM_FULL" 1:7 -+ # still present -+ tests.device-cgroup test-strict-cgroup-helper.sh dump | MATCH 'c 1:7 rwm' -+ -+ # now invoke it for /dev/kmsg, but since the device cgroup is reinitialized -+ # when the snap starts, we have to make the operation async -+ rm -f /var/snap/test-strict-cgroup-helper/common/ready -+ snap run test-strict-cgroup-helper.sh -c 'touch /var/snap/test-strict-cgroup-helper/common/started; until test -e /var/snap/test-strict-cgroup-helper/common/ready; do sleep 1; done; head -1 /dev/kmsg' > run.log 2>&1 & -+ retry -n 5 test -e /var/snap/test-strict-cgroup-helper/common/started -+ -+ # device got added -+ "$libexecdir"/snapd/snap-device-helper add snap_test-strict-cgroup-helper_sh "$DEVICES_PATH_MEM_KMSG" 1:11 -+ tests.device-cgroup test-strict-cgroup-helper.sh dump | MATCH 'c 1:11 rwm' -+ # or changed -+ "$libexecdir"/snapd/snap-device-helper change snap_test-strict-cgroup-helper_sh "$DEVICES_PATH_MEM_KMSG" 1:11 -+ tests.device-cgroup test-strict-cgroup-helper.sh dump | MATCH 'c 1:11 rwm' -+ # and it should be possible to read a line now -+ touch /var/snap/test-strict-cgroup-helper/common/ready -+ # wait for the snap application we started in the background earlier to -+ # finish -+ wait -+ NOMATCH 'Operation not permitted' < run.log -+ test -n "$(cat run.log)" -+ -+ # now remove the cgroup -+ if is_cgroupv2; then -+ rm /sys/fs/bpf/snap/snap_test-strict-cgroup-helper_sh -+ else -+ rmdir /sys/fs/cgroup/devices/snap.test-strict-cgroup-helper.sh -+ fi -+ -+ # running the helper does not fail for either device and action -+ "$libexecdir"/snapd/snap-device-helper add snap_test-strict-cgroup-helper_sh "$DEVICES_PATH_MEM_FULL" 1:7 -+ "$libexecdir"/snapd/snap-device-helper change snap_test-strict-cgroup-helper_sh "$DEVICES_PATH_MEM_FULL" 1:7 -+ "$libexecdir"/snapd/snap-device-helper add snap_test-strict-cgroup-helper_sh "$DEVICES_PATH_MEM_KMSG" 1:11 -+ "$libexecdir"/snapd/snap-device-helper change snap_test-strict-cgroup-helper_sh "$DEVICES_PATH_MEM_KMSG" 1:11 -+ -+ # and the device cgroup map/directory is still gone -+ if is_cgroupv2; then -+ test ! -e /sys/fs/bpf/snap/snap_test-strict-cgroup-helper_sh -+ else -+ test ! -e /sys/fs/cgroup/devices/snap.test-strict-cgroup-helper.sh -+ fi -diff --git a/tests/main/security-device-cgroups-helper/test-strict-cgroup-helper/bin/sh b/tests/main/security-device-cgroups-helper/test-strict-cgroup-helper/bin/sh -new file mode 100755 -index 0000000000000000000000000000000000000000..0f845e07c5a8d6873f48e485a1a213dfa7b41a45 ---- /dev/null -+++ b/tests/main/security-device-cgroups-helper/test-strict-cgroup-helper/bin/sh -@@ -0,0 +1,3 @@ -+#!/bin/sh -+PS1='$ ' -+exec /bin/sh "$@" -diff --git a/tests/main/security-device-cgroups-helper/test-strict-cgroup-helper/meta/snap.yaml b/tests/main/security-device-cgroups-helper/test-strict-cgroup-helper/meta/snap.yaml -new file mode 100644 -index 0000000000000000000000000000000000000000..c2df1aa37d8e75f057ae095c4db5d3c2afca0db4 ---- /dev/null -+++ b/tests/main/security-device-cgroups-helper/test-strict-cgroup-helper/meta/snap.yaml -@@ -0,0 +1,8 @@ -+name: test-strict-cgroup-helper -+version: 1.0 -+summary: snap-device-helper tester -+confinement: strict -+ -+apps: -+ sh: -+ command: bin/sh --- -2.34.1 - diff --git a/0001-cmd-snap-confine-do-not-include-libglvnd-libraries-f.patch b/0001-cmd-snap-confine-do-not-include-libglvnd-libraries-f.patch new file mode 100644 index 0000000..fc90af9 --- /dev/null +++ b/0001-cmd-snap-confine-do-not-include-libglvnd-libraries-f.patch @@ -0,0 +1,482 @@ +From f4cefc704d6c46f204b0a0651379e0766d478ba5 Mon Sep 17 00:00:00 2001 +Message-Id: +From: James Henstridge +Date: Thu, 2 Dec 2021 17:39:04 +0800 +Subject: [PATCH] cmd/snap-confine: do not include libglvnd libraries from the + host system + +* cmd/snap-confine: do not include libglvnd libraries from the host system + +* tests: we no longer symlink libGLX.so + +* cmd/snap-confine: include glvnd globs for old "base: core" snaps + +Ubuntu 16.04 did not include the glvnd driver multiplexing libraries, +and the Mesa version of libGL will not function with the Nvidia X +drivers. + +While the glvnd drivers may not be compatible with the libraries in the +snap's sandbox (e.g. we know that Ubuntu 21.10's libEGL uses new glibc +symbols), it is better than the nothing working. In particular, X11 +based OpenGL apps will function, which will cover the majority of these +old snaps. + +* tests: adjust opengl-nvidia test to use its own test snap. + +Also update to run on Ubuntu 20.04, and drop 14.04. Still todo: test +against the core20 test snap. + +* cmd/libsnap-confine-private: add a unit test for sc_cleanup_shallow_strv + +Signed-off-by: Maciej Borzecki + +* tests: don't specify base for gl-core16 test snap + +* tests: show that host system GLVND libraries are not exposed to snaps using newer bases + +* tests: do not run the gl-core20 part of the test on i386 + +* tests: show that the nvidia backend drivers are still available on core20 + +* tests: adjust spread test + +* tests: add back missing canary file + +* cmd/snap-confine: only create the globs array if NVIDIA_BIARCH||NVIDIA_MULTIARCH + +Co-authored-by: Maciej Borzecki +Signed-off-by: Maciej Borzecki +--- + .../cleanup-funcs-test.c | 22 ++++++ + cmd/libsnap-confine-private/cleanup-funcs.c | 8 ++ + cmd/libsnap-confine-private/cleanup-funcs.h | 10 +++ + cmd/snap-confine/mount-support-nvidia.c | 74 +++++++++++++------ + cmd/snap-confine/mount-support-nvidia.h | 2 +- + cmd/snap-confine/mount-support.c | 2 +- + .../gl-core16/bin/run | 3 + + .../gl-core16/meta/snap.yaml | 9 +++ + .../gl-core20/bin/run | 3 + + .../gl-core20/meta/snap.yaml | 10 +++ + tests/main/interfaces-opengl-nvidia/task.yaml | 54 +++++++++----- + 11 files changed, 157 insertions(+), 40 deletions(-) + create mode 100755 tests/main/interfaces-opengl-nvidia/gl-core16/bin/run + create mode 100644 tests/main/interfaces-opengl-nvidia/gl-core16/meta/snap.yaml + create mode 100755 tests/main/interfaces-opengl-nvidia/gl-core20/bin/run + create mode 100644 tests/main/interfaces-opengl-nvidia/gl-core20/meta/snap.yaml + +diff --git a/cmd/libsnap-confine-private/cleanup-funcs-test.c b/cmd/libsnap-confine-private/cleanup-funcs-test.c +index 203193e47792e2e0833b36f51515764ae0c7807c..509df3ee8a50b24a48dad0871495cfebe56b7aef 100644 +--- a/cmd/libsnap-confine-private/cleanup-funcs-test.c ++++ b/cmd/libsnap-confine-private/cleanup-funcs-test.c +@@ -142,6 +142,27 @@ static void test_cleanup_close(void) + g_assert_cmpint(fd, ==, -1); + } + ++static void test_cleanup_shallow_strv(void) ++{ ++ /* It is safe to use with a NULL pointer */ ++ sc_cleanup_shallow_strv(NULL); ++ ++ const char **argses = NULL; ++ /* It is ok of the pointer value is NULL */ ++ sc_cleanup_shallow_strv(&argses); ++ g_assert_null(argses); ++ ++ argses = calloc(10, sizeof(char *)); ++ g_assert_nonnull(argses); ++ /* Fill with bogus pointers so attempts to free them would segfault */ ++ for (int i = 0; i < 10; i++) { ++ argses[i] = (char *)0x100 + i; ++ } ++ sc_cleanup_shallow_strv(&argses); ++ g_assert_null(argses); ++ /* If we are alive at this point, most likely only the array was free'd */ ++} ++ + static void __attribute__((constructor)) init(void) + { + g_test_add_func("/cleanup/sanity", test_cleanup_sanity); +@@ -150,4 +171,5 @@ static void __attribute__((constructor)) init(void) + g_test_add_func("/cleanup/endmntent", test_cleanup_endmntent); + g_test_add_func("/cleanup/closedir", test_cleanup_closedir); + g_test_add_func("/cleanup/close", test_cleanup_close); ++ g_test_add_func("/cleanup/shallow_strv", test_cleanup_shallow_strv); + } +diff --git a/cmd/libsnap-confine-private/cleanup-funcs.c b/cmd/libsnap-confine-private/cleanup-funcs.c +index 369235cbcc17426372427d952b7f83a16515c268..d96a2ba0f3e4c5f80bb9b7fe9e699b0262508814 100644 +--- a/cmd/libsnap-confine-private/cleanup-funcs.c ++++ b/cmd/libsnap-confine-private/cleanup-funcs.c +@@ -28,6 +28,14 @@ void sc_cleanup_string(char **ptr) + } + } + ++void sc_cleanup_shallow_strv(const char ***ptr) ++{ ++ if (ptr != NULL && *ptr != NULL) { ++ free(*ptr); ++ *ptr = NULL; ++ } ++} ++ + void sc_cleanup_file(FILE ** ptr) + { + if (ptr != NULL && *ptr != NULL) { +diff --git a/cmd/libsnap-confine-private/cleanup-funcs.h b/cmd/libsnap-confine-private/cleanup-funcs.h +index b1fee959c5920d59f67e417795e9e8441378d5e2..43ef1515c9cf8ca0c06abbe051d6c8e73261c92f 100644 +--- a/cmd/libsnap-confine-private/cleanup-funcs.h ++++ b/cmd/libsnap-confine-private/cleanup-funcs.h +@@ -40,6 +40,16 @@ + **/ + void sc_cleanup_string(char **ptr); + ++/** ++ * Shallow free a dynamically allocated string vector. ++ * ++ * The strings in the vector will not be freed. ++ * This function is designed to be used with SC_CLEANUP() macro. ++ * The variable MUST be initialized for correct operation. ++ * The safe initialisation value is NULL. ++ */ ++void sc_cleanup_shallow_strv(const char ***ptr); ++ + /** + * Close an open file. + * +diff --git a/cmd/snap-confine/mount-support-nvidia.c b/cmd/snap-confine/mount-support-nvidia.c +index 2968e1f21a44c2c9d5ba2698afcb525ae91da7fc..75f7265f1bde49beac5725f3b2bf2a755479476c 100644 +--- a/cmd/snap-confine/mount-support-nvidia.c ++++ b/cmd/snap-confine/mount-support-nvidia.c +@@ -81,19 +81,10 @@ static const size_t egl_vendor_globs_len = + // FIXME: this doesn't yet work with libGLX and libglvnd redirector + // FIXME: this still doesn't work with the 361 driver + static const char *nvidia_globs[] = { +- "libEGL.so*", + "libEGL_nvidia.so*", +- "libGL.so*", +- "libOpenGL.so*", +- "libGLESv1_CM.so*", + "libGLESv1_CM_nvidia.so*", +- "libGLESv2.so*", + "libGLESv2_nvidia.so*", +- "libGLX_indirect.so*", + "libGLX_nvidia.so*", +- "libGLX.so*", +- "libGLdispatch.so*", +- "libGLU.so*", + "libXvMCNVIDIA.so*", + "libXvMCNVIDIA_dynamic.so*", + "libnvidia-cfg.so*", +@@ -162,6 +153,21 @@ static const char *nvidia_globs[] = { + static const size_t nvidia_globs_len = + sizeof nvidia_globs / sizeof *nvidia_globs; + ++static const char *glvnd_globs[] = { ++ "libEGL.so*", ++ "libGL.so*", ++ "libOpenGL.so*", ++ "libGLESv1_CM.so*", ++ "libGLESv2.so*", ++ "libGLX_indirect.so*", ++ "libGLX.so*", ++ "libGLdispatch.so*", ++ "libGLU.so*", ++}; ++ ++static const size_t glvnd_globs_len = ++ sizeof glvnd_globs / sizeof *glvnd_globs; ++ + #endif // defined(NVIDIA_BIARCH) || defined(NVIDIA_MULTIARCH) + + // Populate libgl_dir with a symlink farm to files matching glob_list. +@@ -351,7 +357,7 @@ static void sc_mkdir_and_mount_and_glob_files(const char *rootfs_dir, + // + // In non GLVND cases we just copy across the exposed libGLs and NVIDIA + // libraries from wherever we find, and clobbering is also harmless. +-static void sc_mount_nvidia_driver_biarch(const char *rootfs_dir) ++static void sc_mount_nvidia_driver_biarch(const char *rootfs_dir, const char **globs, size_t globs_len) + { + + const char *native_sources[] = { +@@ -374,14 +380,14 @@ static void sc_mount_nvidia_driver_biarch(const char *rootfs_dir) + // Primary arch + sc_mkdir_and_mount_and_glob_files(rootfs_dir, + native_sources, native_sources_len, +- SC_LIBGL_DIR, nvidia_globs, +- nvidia_globs_len); ++ SC_LIBGL_DIR, globs, ++ globs_len); + + #if UINTPTR_MAX == 0xffffffffffffffff + // Alternative 32-bit support + sc_mkdir_and_mount_and_glob_files(rootfs_dir, lib32_sources, + lib32_sources_len, SC_LIBGL32_DIR, +- nvidia_globs, nvidia_globs_len); ++ globs, globs_len); + #endif + } + +@@ -501,7 +507,7 @@ static int sc_mount_nvidia_is_driver_in_dir(const char *dir) + return 0; + } + +-static void sc_mount_nvidia_driver_multiarch(const char *rootfs_dir) ++static void sc_mount_nvidia_driver_multiarch(const char *rootfs_dir, const char **globs, size_t globs_len) + { + const char *native_libdir = NATIVE_LIBDIR "/" HOST_ARCH_TRIPLET; + const char *lib32_libdir = NATIVE_LIBDIR "/" HOST_ARCH32_TRIPLET; +@@ -519,8 +525,8 @@ static void sc_mount_nvidia_driver_multiarch(const char *rootfs_dir) + sc_mkdir_and_mount_and_glob_files(rootfs_dir, + native_sources, + native_sources_len, +- SC_LIBGL_DIR, nvidia_globs, +- nvidia_globs_len); ++ SC_LIBGL_DIR, globs, ++ globs_len); + + // Alternative 32-bit support + if ((strlen(HOST_ARCH32_TRIPLET) > 0) && +@@ -536,8 +542,8 @@ static void sc_mount_nvidia_driver_multiarch(const char *rootfs_dir) + lib32_sources, + lib32_sources_len, + SC_LIBGL32_DIR, +- nvidia_globs, +- nvidia_globs_len); ++ globs, ++ globs_len); + } + } else { + // Attempt mount of both the native and 32-bit variants of the driver if they exist +@@ -576,7 +582,7 @@ static void sc_mount_egl(const char *rootfs_dir) + egl_vendor_globs_len); + } + +-void sc_mount_nvidia_driver(const char *rootfs_dir) ++void sc_mount_nvidia_driver(const char *rootfs_dir, const char *base_snap_name) + { + /* If NVIDIA module isn't loaded, don't attempt to mount the drivers */ + if (access(SC_NVIDIA_DRIVER_VERSION_FILE, F_OK) != 0) { +@@ -593,11 +599,37 @@ void sc_mount_nvidia_driver(const char *rootfs_dir) + die("cannot change ownership of " SC_LIB); + } + (void)sc_set_effective_identity(old); ++ ++#if defined(NVIDIA_BIARCH) || defined(NVIDIA_MULTIARCH) ++ /* We include the globs for the glvnd libraries for old snaps ++ * based on core, Ubuntu 16.04 did not include glvnd itself. ++ * ++ * While there is no guarantee that the host system's glvnd ++ * libGL will be compatible (as it is built with the host ++ * system's glibc), the Mesa libGL included with the snap will ++ * definitely not be compatible (as it expects to find the Mesa ++ * implementation of the GLX extension).. ++ */ ++ const char **globs = nvidia_globs; ++ size_t globs_len = nvidia_globs_len; ++ const char **full_globs SC_CLEANUP(sc_cleanup_shallow_strv) = NULL; ++ if (sc_streq(base_snap_name, "core")) { ++ full_globs = malloc(sizeof nvidia_globs + sizeof glvnd_globs); ++ if (full_globs == NULL) { ++ die("cannot allocate globs array"); ++ } ++ memcpy(full_globs, nvidia_globs, sizeof nvidia_globs); ++ memcpy(&full_globs[nvidia_globs_len], glvnd_globs, sizeof glvnd_globs); ++ globs = full_globs; ++ globs_len = nvidia_globs_len + glvnd_globs_len; ++ } ++#endif ++ + #ifdef NVIDIA_MULTIARCH +- sc_mount_nvidia_driver_multiarch(rootfs_dir); ++ sc_mount_nvidia_driver_multiarch(rootfs_dir, globs, globs_len); + #endif // ifdef NVIDIA_MULTIARCH + #ifdef NVIDIA_BIARCH +- sc_mount_nvidia_driver_biarch(rootfs_dir); ++ sc_mount_nvidia_driver_biarch(rootfs_dir, globs, globs_len); + #endif // ifdef NVIDIA_BIARCH + + // Common for both driver mechanisms +diff --git a/cmd/snap-confine/mount-support-nvidia.h b/cmd/snap-confine/mount-support-nvidia.h +index 56ec893f6c7d8c1cecfd0a16c17add2540bfb32b..9835fb42665b1e2c65a9b557c81e73e2f296aceb 100644 +--- a/cmd/snap-confine/mount-support-nvidia.h ++++ b/cmd/snap-confine/mount-support-nvidia.h +@@ -43,6 +43,6 @@ + * /usr/lib directory on the classic filesystem. After the pivot_root() call + * those symlinks rely on the /var/lib/snapd/hostfs directory as a "gateway". + **/ +-void sc_mount_nvidia_driver(const char *rootfs_dir); ++void sc_mount_nvidia_driver(const char *rootfs_dir, const char *base_snap_name); + + #endif +diff --git a/cmd/snap-confine/mount-support.c b/cmd/snap-confine/mount-support.c +index 44dea9d9550b047f169b47647276c73425e4f7b6..d5331b2eebb1e612955131f66b6be7f6f217da15 100644 +--- a/cmd/snap-confine/mount-support.c ++++ b/cmd/snap-confine/mount-support.c +@@ -494,7 +494,7 @@ static void sc_bootstrap_mount_namespace(const struct sc_mount_config *config) + // code changes the nvidia code assumes it has access to the existing + // pre-pivot filesystem. + if (config->distro == SC_DISTRO_CLASSIC) { +- sc_mount_nvidia_driver(scratch_dir); ++ sc_mount_nvidia_driver(scratch_dir, config->base_snap_name); + } + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + // pivot_root +diff --git a/tests/main/interfaces-opengl-nvidia/gl-core16/bin/run b/tests/main/interfaces-opengl-nvidia/gl-core16/bin/run +new file mode 100755 +index 0000000000000000000000000000000000000000..f07e1ec43b397bf78af6a20ab96a3d4cee87317f +--- /dev/null ++++ b/tests/main/interfaces-opengl-nvidia/gl-core16/bin/run +@@ -0,0 +1,3 @@ ++#!/bin/sh ++PS1='$ ' ++exec "$@" +diff --git a/tests/main/interfaces-opengl-nvidia/gl-core16/meta/snap.yaml b/tests/main/interfaces-opengl-nvidia/gl-core16/meta/snap.yaml +new file mode 100644 +index 0000000000000000000000000000000000000000..83851c75ef120a19d186c25ad421d5a06d6a876a +--- /dev/null ++++ b/tests/main/interfaces-opengl-nvidia/gl-core16/meta/snap.yaml +@@ -0,0 +1,9 @@ ++name: gl-core16 ++version: 1.0 ++summary: Test snap that plugs opengl and uses the core base snap ++confinement: strict ++ ++apps: ++ gl-core16: ++ command: bin/run ++ plugs: [ opengl ] +diff --git a/tests/main/interfaces-opengl-nvidia/gl-core20/bin/run b/tests/main/interfaces-opengl-nvidia/gl-core20/bin/run +new file mode 100755 +index 0000000000000000000000000000000000000000..f07e1ec43b397bf78af6a20ab96a3d4cee87317f +--- /dev/null ++++ b/tests/main/interfaces-opengl-nvidia/gl-core20/bin/run +@@ -0,0 +1,3 @@ ++#!/bin/sh ++PS1='$ ' ++exec "$@" +diff --git a/tests/main/interfaces-opengl-nvidia/gl-core20/meta/snap.yaml b/tests/main/interfaces-opengl-nvidia/gl-core20/meta/snap.yaml +new file mode 100644 +index 0000000000000000000000000000000000000000..422f183b8316d0dd32bac76e9d83fdc953c02645 +--- /dev/null ++++ b/tests/main/interfaces-opengl-nvidia/gl-core20/meta/snap.yaml +@@ -0,0 +1,10 @@ ++name: gl-core20 ++version: 1.0 ++summary: Test snap that plugs opengl and uses the core20 base snap ++confinement: strict ++base: core20 ++ ++apps: ++ gl-core20: ++ command: bin/run ++ plugs: [ opengl ] +diff --git a/tests/main/interfaces-opengl-nvidia/task.yaml b/tests/main/interfaces-opengl-nvidia/task.yaml +index 0767c587b4f8231c0deb7df4236de32ebc84e788..bad3ed4e3acfb8f603d676d6ab66a5584e3767b3 100644 +--- a/tests/main/interfaces-opengl-nvidia/task.yaml ++++ b/tests/main/interfaces-opengl-nvidia/task.yaml +@@ -1,6 +1,6 @@ + summary: Ensure that basic opengl works with faked nvidia + +-systems: [ubuntu-14.04-*, ubuntu-16.04-*, ubuntu-18.04-*] ++systems: [ubuntu-16.04-*, ubuntu-18.04-*, ubuntu-20.04-*] + + environment: + NV_VERSION/stable: "123.456" +@@ -18,7 +18,7 @@ prepare: | + mkdir -p /usr/share/vulkan/icd.d + echo "canary-vulkan" > /usr/share/vulkan/icd.d/nvidia_icd.json + +- if os.query is-bionic; then ++ if ! os.query is-xenial; then + # mock GLVND EGL vendor file + echo "Test GLVND EGL vendor files access" + mkdir -p /usr/share/glvnd/egl_vendor.d +@@ -26,7 +26,7 @@ prepare: | + fi + + # mock nvidia libraries +- if os.query is-bionic; then ++ if ! os.query is-xenial; then + mkdir -p /usr/lib/"$(dpkg-architecture -qDEB_HOST_MULTIARCH)"/tls + mkdir -p /usr/lib/"$(dpkg-architecture -qDEB_HOST_MULTIARCH)"/vdpau + echo "canary-triplet" >> /usr/lib/"$(dpkg-architecture -qDEB_HOST_MULTIARCH)"/libGLX.so.0.0.1 +@@ -69,7 +69,7 @@ restore: | + umount -t tmpfs /sys/module + rm -rf /usr/share/vulkan + +- if os.query is-bionic; then ++ if ! os.query is-xenial; then + rm -rf /usr/share/glvnd/egl_vendor.d/10_nvidia.json + rm -rf /usr/lib/"$(dpkg-architecture -qDEB_HOST_MULTIARCH)"/tls + rm -rf /usr/lib/"$(dpkg-architecture -qDEB_HOST_MULTIARCH)"/vdpau +@@ -90,35 +90,55 @@ restore: | + rm -rf /usr/lib32/nvidia-123 + + execute: | +- "$TESTSTOOLS"/snaps-state install-local test-snapd-policy-app-consumer ++ "$TESTSTOOLS"/snaps-state install-local gl-core16 + + echo "When the interface is connected" +- snap connect test-snapd-policy-app-consumer:opengl core:opengl ++ snap connect gl-core16:opengl core:opengl + + echo "App can access nvidia library files" +- expected="canary-legacy" +- if os.query is-bionic; then +- expected="canary-triplet" ++ expected="canary-triplet" ++ if os.query is-xenial; then ++ expected="canary-legacy" + fi + files="libGLX.so.0.0.1 libGLX_nvidia.so.0.0.1 libnvidia-glcore.so.$NV_VERSION tls/libnvidia-tls.so.$NV_VERSION libnvidia-tls.so.$NV_VERSION vdpau/libvdpau_nvidia.so.$NV_VERSION" + for f in $files; do +- snap run test-snapd-policy-app-consumer.opengl -c "cat /var/lib/snapd/lib/gl/$f" | MATCH "$expected" ++ gl-core16 cat "/var/lib/snapd/lib/gl/$f" | MATCH "$expected" + done + + if os.query is-pc-amd64; then +- expected32="canary-32-legacy" +- if os.query is-bionic; then +- expected32="canary-32-triplet" ++ expected32="canary-32-triplet" ++ if os.query is-xenial; then ++ expected32="canary-32-legacy" + fi + for f in $files; do +- snap run test-snapd-policy-app-consumer.opengl -c "cat /var/lib/snapd/lib/gl32/$f" | MATCH "$expected32" ++ gl-core16 cat "/var/lib/snapd/lib/gl32/$f" | MATCH "$expected32" + done + fi + + echo "And vulkan ICD file" +- snap run test-snapd-policy-app-consumer.opengl -c "cat /var/lib/snapd/lib/vulkan/icd.d/nvidia_icd.json" | MATCH canary-vulkan ++ gl-core16 cat /var/lib/snapd/lib/vulkan/icd.d/nvidia_icd.json | MATCH canary-vulkan + +- if os.query is-bionic; then ++ if ! os.query is-xenial; then + echo "And GLVND EGL vendor file" +- snap run test-snapd-policy-app-consumer.opengl -c "cat /var/lib/snapd/lib/glvnd/egl_vendor.d/10_nvidia.json" | MATCH canary-egl ++ gl-core16 cat /var/lib/snapd/lib/glvnd/egl_vendor.d/10_nvidia.json | MATCH canary-egl ++ fi ++ ++ # There is no core20 snap on i386, so the following tests will not ++ # function there. ++ if os.query is-pc-i386; then ++ exit 0 ++ fi ++ ++ echo "For host systems using glvnd, the glvnd libraries are not exposed to snaps using newer bases" ++ "$TESTSTOOLS"/snaps-state install-local gl-core20 ++ snap connect gl-core20:opengl core:opengl ++ ++ echo "While glvnd frontend libraries are not available, the backend nvidia drivers are" ++ if ! os.query is-xenial; then ++ not gl-core20 test -f /var/lib/snapd/lib/gl/libGLX.so.0.0.1 ++ gl-core20 cat /var/lib/snapd/lib/gl/libGLX_nvidia.so.0.0.1 | MATCH canary-triplet ++ if os.query is-pc-amd64; then ++ not gl-core20 cat /var/lib/snapd/lib/gl32/libGLX.so.0.0.1 ++ gl-core20 cat /var/lib/snapd/lib/gl32/libGLX_nvidia.so.0.0.1 | MATCH canary-32-triplet ++ fi + fi +-- +2.34.1 + diff --git a/snapd.spec b/snapd.spec index 88aece0..4126b69 100644 --- a/snapd.spec +++ b/snapd.spec @@ -85,14 +85,15 @@ %{!?_systemd_system_env_generator_dir: %global _systemd_system_env_generator_dir %{_prefix}/lib/systemd/system-environment-generators} Name: snapd -Version: 2.53.2 -Release: 2%{?dist} +Version: 2.53.4 +Release: 1%{?dist} Summary: A transactional software package manager License: GPLv3 URL: https://%{provider_prefix} Source0: https://%{provider_prefix}/releases/download/%{version}/%{name}_%{version}.no-vendor.tar.xz Source1: https://%{provider_prefix}/releases/download/%{version}/%{name}_%{version}.only-vendor.tar.xz -Patch0: 0001-cmd-libsnap-confine-private-fix-snap-device-helper-d.patch +# cherry picked from https://github.com/snapcore/snapd/commit/f4cefc704d6c46f204b0a0651379e0766d478ba5 +Patch0: 0001-cmd-snap-confine-do-not-include-libglvnd-libraries-f.patch %if 0%{?with_goarches} # e.g. el6 has ppc64 arch without gcc-go, so EA tag is required @@ -942,6 +943,39 @@ fi %changelog +* Wed Dec 8 2021 Maciek Borzecki - 2.53.4-1 +- Release 2.53.4 to Fedora +- Cherry pick for nvidia glvnd incompatibility + +* Thu Dec 02 2021 Ian Johnson +- New upstream release 2.53.4 + - devicestate: mock devicestate.MockTimeutilIsNTPSynchronized to + avoid host env leaking into tests + - timeutil: return NoTimedate1Error if it can't connect to the + system bus + +* Thu Dec 02 2021 Ian Johnson +- New upstream release 2.53.3 + - devicestate: Unregister deletes the device key pair as well + - daemon,tests: support forgetting device serial via API + - configcore: relax validation rules for hostname + - o/devicestate: introduce DeviceManager.Unregister + - packaging/ubuntu, packaging/debian: depend on dbus-session-bus + provider + - many: wait for up to 10min for NTP synchronization before + autorefresh + - interfaces/interfaces/scsi_generic: add interface for scsi generic + devices + - interfaces/microstack-support: set controlsDeviceCgroup to true + - interface/builtin/log_observe: allow to access /dev/kmsg + - daemon: write formdata file parts to snaps dir + - spread: run lxd tests with version from latest/edge + - cmd/libsnap-confine-private: fix snap-device-helper device allow + list modification on cgroup v2 + - interfaces/builtin/dsp: add proc files for monitoring Ambarella + DSP firmware + - interfaces/builtin/dsp: update proc file accordingly + * Mon Nov 29 2021 Maciek Borzecki - 2.53.2-2 - Cherry-pick a fix for snap-device-helper (RHBZ#2025264) diff --git a/sources b/sources index 5fd4f8e..94665f7 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (snapd_2.53.2.no-vendor.tar.xz) = f15fee3a471d005fee59fb29b0c18906779fd896602206dd58755e607a9985cd613794b4d4d6c91baa8b5ab3c4c00a94a906040def7d4951fb01111596c5c207 -SHA512 (snapd_2.53.2.only-vendor.tar.xz) = 2422e4f7f38479b83c98fa8a4e030f7ab000701f08bf62b7d7b31e63b1f9ff6c1496e6f6250ba493a949d7f7bdd0dcda56d609cac3b818d29e2f58d1bdd130d4 +SHA512 (snapd_2.53.4.no-vendor.tar.xz) = 2dad47146eaa1f41cd6ea40432cd7a118ca4ceeebe512fa22a722c185e8cd1fb347c935fed86cefd37e0628b54c538bbdddc3e816a14ca3e42c0fa1f3da78302 +SHA512 (snapd_2.53.4.only-vendor.tar.xz) = d6295e19007dd7d669ee8ee5767ab544e12940bcecf837fb776387d33cc4428af5240e4287d88b32304773e8e4f2a7d437948c68d553a04824ef60a3884d0763