summaryrefslogtreecommitdiff
diff options
authorZygmunt Krynicki <me@zygoon.pl>2016-06-13 14:36:03 +0200
committerGitHub <noreply@github.com>2016-06-13 14:36:03 +0200
commit506eb060c69d2c03059d0f805acbcf0f2a2a6664 (patch)
treebe937e80d22a276fc9b7b9968bc2c2fa296dd1f0
parentf28b33b3599dc3884e8c41641a7da57eb276d520 (diff)
parent92b0b9cf6cf2e2bf75c2f1c494bf1092ca3ed0b0 (diff)
Merge pull request #36 from ubuntu-core/next-release
Release 1.0.29
-rw-r--r--compat/Makefile.am4
-rw-r--r--compat/ubuntu-core-launcher.in2
-rw-r--r--configure.ac33
-rw-r--r--debian/changelog10
-rw-r--r--debian/control26
-rwxr-xr-xdebian/rules8
-rw-r--r--debian/snap-confine.install2
-rw-r--r--debian/snap-confine.lintian-overrides2
-rw-r--r--debian/ubuntu-core-launcher.install2
-rw-r--r--debian/ubuntu-core-launcher.maintscript1
-rwxr-xr-xdebian/ubuntu-core-launcher.postinst4
-rwxr-xr-xdebian/ubuntu-core-launcher.postrm6
-rwxr-xr-xdebian/ubuntu-core-launcher.preinst6
-rw-r--r--debian/usr.bin.snap-confine49
-rw-r--r--src/Makefile.am20
-rw-r--r--src/README.nvidia26
-rw-r--r--src/classic.h3
-rw-r--r--src/mount-support-nvidia.c232
-rw-r--r--src/mount-support-nvidia.h23
-rw-r--r--src/mount-support.c105
-rw-r--r--src/udev-support.c1
-rw-r--r--tests/Makefile.am1
-rwxr-xr-xtests/test_create_user_data150
23 files changed, 509 insertions, 207 deletions
diff --git a/compat/Makefile.am b/compat/Makefile.am
index d682768b4b..af2283a18b 100644
--- a/compat/Makefile.am
+++ b/compat/Makefile.am
@@ -2,6 +2,6 @@ dist_bin_SCRIPTS = ubuntu-core-launcher
CLEANFILES = $(dist_bin_SCRIPTS)
EXTRA_DIST = ubuntu-core-launcher.in
-ubuntu-core-launcher: ubuntu-core-launcher.in
- sed -e 's,[@]LIBDIR[@],$(libdir),g' < $(srcdir)/ubuntu-core-launcher.in > ubuntu-core-launcher
+ubuntu-core-launcher: ubuntu-core-launcher.in Makefile
+ sed -e 's,[@]libexecdir[@],$(libexecdir),g' < $(srcdir)/ubuntu-core-launcher.in > ubuntu-core-launcher
chmod +x ubuntu-core-launcher
diff --git a/compat/ubuntu-core-launcher.in b/compat/ubuntu-core-launcher.in
index 824f203b89..a4d4cddd6d 100644
--- a/compat/ubuntu-core-launcher.in
+++ b/compat/ubuntu-core-launcher.in
@@ -1,3 +1,3 @@
#!/bin/sh
shift
-exec @LIBDIR@/snap-confine "$@"
+exec @libexecdir@/snap-confine "$@"
diff --git a/configure.ac b/configure.ac
index fd888b4df9..3a06ca373a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ([2.69])
-AC_INIT([snap-confine], [2.0], [snapcraft@lists.ubuntu.com])
+AC_INIT([snap-confine], [1.0.29], [snapcraft@lists.ubuntu.com])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AC_USE_SYSTEM_EXTENSIONS
@@ -49,7 +49,8 @@ AM_CONDITIONAL([STRICT_CONFINEMENT], [test "x$enable_confinement" = "xyes"])
AS_IF([test "x$enable_confinement" = "xyes"], [
PKG_CHECK_MODULES([APPARMOR], [libapparmor])
PKG_CHECK_MODULES([SECCOMP], [libseccomp])
- PKG_CHECK_MODULES([UDEV], [libudev])
+ PKG_CHECK_MODULES([LIBUDEV], [libudev])
+ PKG_CHECK_MODULES([UDEV], [udev])
AC_DEFINE([STRICT_CONFINEMENT], [1],
[Define if strict apparmor confinement is available])
], [
@@ -80,5 +81,33 @@ AS_IF([test "x$enable_rootfs_is_core_snap" = "xyes"], [
AC_DEFINE([ROOTFS_IS_CORE_SNAP], [1],
[Use the core snap as the root file system])])
+# Enable special support for hosts with proprietary nvidia drivers on Ubuntu.
+AC_ARG_ENABLE([nvidia-ubuntu],
+ AS_HELP_STRING([--enable-nvidia-ubuntu], [Support for proprietary nvidia drivers (Ubuntu)]),
+ [case "${enableval}" in
+ yes) enable_nvidia_ubuntu=yes ;;
+ no) enable_nvidia_ubuntu=no ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-nvidia-ubuntu])
+ esac], [enable_nvidia_ubuntu=no])
+AM_CONDITIONAL([NVIDIA_UBUNTU], [test "x$enable_nvidia_ubuntu" = "xyes"])
+
+AS_IF([test "x$enable_nvidia_ubuntu" = "xyes"], [
+ AC_DEFINE([NVIDIA_UBUNTU], [1],
+ [Support for propietary nvidia drivers (Ubuntu)])])
+
+# Enable special support for hosts with proprietary nvidia drivers on Arch.
+AC_ARG_ENABLE([nvidia-arch],
+ AS_HELP_STRING([--enable-nvidia-arch], [Support for proprietary nvidia drivers (Arch)]),
+ [case "${enableval}" in
+ yes) enable_nvidia_arch=yes ;;
+ no) enable_nvidia_arch=no ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-nvidia-arch])
+ esac], [enable_nvidia_arch=no])
+AM_CONDITIONAL([NVIDIA_ARCH], [test "x$enable_nvidia_arch" = "xyes"])
+
+AS_IF([test "x$enable_nvidia_arch" = "xyes"], [
+ AC_DEFINE([NVIDIA_ARCH], [1],
+ [Support for propietary nvidia drivers (Arch)])])
+
AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile compat/Makefile])
AC_OUTPUT
diff --git a/debian/changelog b/debian/changelog
index 99bfff6137..29cce436e0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-ubuntu-core-launcher (2.0) UNRELEASED; urgency=medium
+ubuntu-core-launcher (1.0.29) UNRELEASED; urgency=medium
[ Zygmunt Krynicki ]
* Rename the package and everything else from ubuntu-core-launcher to
@@ -22,6 +22,14 @@ ubuntu-core-launcher (2.0) UNRELEASED; urgency=medium
* Update Standards-Version.
* Add lintian override for suid binary.
+ [ Zygmunt Krynicki ]
+ * Change unreleased version back to 1.0.x after discussion with Michael Vogt.
+ * Don't mark ubuntu-core-launcher as transitional (it isn't yet).
+ * Move rm_conffile to ubuntu-core-launcher.maintscript, remove the now-empty
+ postrm and preinst scripts.
+ * Enable hardening options for snap-confine
+ * Build-depend on udev, use udevlibdir instead of hardcoding /lib/udev
+
-- Zygmunt Krynicki <zygmunt.krynicki@canonical.com> Sun, 22 May 2016 16:14:24 +0300
ubuntu-core-launcher (1.0.28) yakkety; urgency=medium
diff --git a/debian/control b/debian/control
index c710e191ff..9df0aaae46 100644
--- a/debian/control
+++ b/debian/control
@@ -2,15 +2,27 @@ Source: ubuntu-core-launcher
Section: utils
Priority: optional
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
-Build-Depends: debhelper (>= 9), libseccomp-dev, libapparmor-dev, libudev-dev, dh-apparmor, indent, shellcheck, pkg-config, autotools-dev, autoconf, automake, dh-autoreconf
+Build-Depends: autoconf,
+ automake,
+ autotools-dev,
+ debhelper (>= 9),
+ dh-apparmor,
+ dh-autoreconf,
+ indent,
+ libapparmor-dev,
+ libseccomp-dev,
+ libudev-dev,
+ pkg-config,
+ shellcheck,
+ udev
Standards-Version: 3.9.8
Vcs-Git: https://github.com/ubuntu-core/snap-confine
Package: snap-confine
Architecture: any
-Breaks: ubuntu-core-launcher (<< 2.0)
-Replaces: ubuntu-core-launcher (<< 2.0)
-Depends: ${misc:Depends}, ${shlibs:Depends}, apparmor
+Breaks: ubuntu-core-launcher (<< 1.0.29)
+Replaces: ubuntu-core-launcher (<< 1.0.29)
+Depends: apparmor, ${misc:Depends}, ${shlibs:Depends}
Description: Support executable to apply confinement for snappy apps.
This package contains an internal tool for applying confinement to snappy app.
The executable (snap-confine) is ran internally by snapd to apply confinement
@@ -19,9 +31,7 @@ Description: Support executable to apply confinement for snappy apps.
Package: ubuntu-core-launcher
Architecture: all
-Depends: ${misc:Depends}, ${shlibs:Depends}, snap-confine
+Depends: snap-confine, ${misc:Depends}, ${shlibs:Depends}
Pre-Depends: dpkg (>= 1.17.14)
Description: Launcher for ubuntu-core (snappy) apps
- This is a transitional package that lets existing installation depending on
- ubuntu-core-launcher syntax continue to work as-is. In the future this will become
- an empty transitional package.
+ This package contains the launcher for launching snappy applications
diff --git a/debian/rules b/debian/rules
index 0bfee212c2..90953e53ee 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,10 +1,16 @@
#!/usr/bin/make -f
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+DPKG_EXPORT_BUILDFLAGS = 1
+include /usr/share/dpkg/buildflags.mk
%:
dh $@ --with autoreconf
+override_dh_auto_configure:
+ ./configure --enable-nvidia-ubuntu --enable-rootfs-is-core-snap --prefix=/usr --libexecdir=/usr/lib/snap-confine
+
override_dh_fixperms:
- dh_fixperms -Xusr/bin/snap-confine
+ dh_fixperms -Xusr/lib/snap-confine/snap-confine
override_dh_installdeb:
dh_apparmor --profile-name=usr.bin.snap-confine -psnap-confine
diff --git a/debian/snap-confine.install b/debian/snap-confine.install
index 88c84013ea..9b14c7247b 100644
--- a/debian/snap-confine.install
+++ b/debian/snap-confine.install
@@ -1,3 +1,3 @@
debian/usr.bin.snap-confine etc/apparmor.d
-usr/*
lib/*
+usr/lib/snap-confine/*
diff --git a/debian/snap-confine.lintian-overrides b/debian/snap-confine.lintian-overrides
index 60d639fa77..533b245806 100644
--- a/debian/snap-confine.lintian-overrides
+++ b/debian/snap-confine.lintian-overrides
@@ -1,2 +1,2 @@
# Yes, we expect this to be suid.
-snap-confine: setuid-binary usr/bin/snap-confine 4755 root/root
+snap-confine: setuid-binary usr/lib/snap-confine/snap-confine 4755 root/root
diff --git a/debian/ubuntu-core-launcher.install b/debian/ubuntu-core-launcher.install
index 0275f1dab6..f0b1bd57bb 100644
--- a/debian/ubuntu-core-launcher.install
+++ b/debian/ubuntu-core-launcher.install
@@ -1 +1 @@
-compat/ubuntu-core-launcher usr/bin
+usr/bin/ubuntu-core-launcher
diff --git a/debian/ubuntu-core-launcher.maintscript b/debian/ubuntu-core-launcher.maintscript
new file mode 100644
index 0000000000..71afe81f2b
--- /dev/null
+++ b/debian/ubuntu-core-launcher.maintscript
@@ -0,0 +1 @@
+rm_conffile /etc/apparmor.d/usr.bin.ubuntu-core-launcher 1.0.29~ -- "$@"
diff --git a/debian/ubuntu-core-launcher.postinst b/debian/ubuntu-core-launcher.postinst
index f432eff384..0d3db2a528 100755
--- a/debian/ubuntu-core-launcher.postinst
+++ b/debian/ubuntu-core-launcher.postinst
@@ -2,10 +2,6 @@
#DEBHELPER#
-# XXX: doesn't seem to really work in practice. Perhaps the version needs love
-dpkg-maintscript-helper rm_conffile \
- /etc/apparmor.d/usr.bin.ubuntu-core-launcher 2.0~ -- "$@"
-
case $1 in
configure)
# remove current profile so that the pass-through can still run
diff --git a/debian/ubuntu-core-launcher.postrm b/debian/ubuntu-core-launcher.postrm
deleted file mode 100755
index b7f56fe6fb..0000000000
--- a/debian/ubuntu-core-launcher.postrm
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-#DEBHELPER#
-
-dpkg-maintscript-helper rm_conffile \
- /etc/apparmor.d/usr.bin.ubuntu-core-launcher 2.0~ -- "$@"
diff --git a/debian/ubuntu-core-launcher.preinst b/debian/ubuntu-core-launcher.preinst
deleted file mode 100755
index b7f56fe6fb..0000000000
--- a/debian/ubuntu-core-launcher.preinst
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-#DEBHELPER#
-
-dpkg-maintscript-helper rm_conffile \
- /etc/apparmor.d/usr.bin.ubuntu-core-launcher 2.0~ -- "$@"
diff --git a/debian/usr.bin.snap-confine b/debian/usr.bin.snap-confine
index 5500d25d97..da67189d80 100644
--- a/debian/usr.bin.snap-confine
+++ b/debian/usr.bin.snap-confine
@@ -68,22 +68,38 @@
# change_profile -> **,
# reading seccomp filters
- /var/lib/snapd/seccomp/profiles/* r,
+ /{tmp/snap.rootfs_*/,}var/lib/snapd/seccomp/profiles/* r,
# set up snap-specific private /tmp dir
capability chown,
- /tmp/ w,
- /tmp/snap.*/ w,
- /tmp/snap.*/tmp/ w,
- mount options=(rw private) -> /tmp/,
- mount options=(rw bind) /tmp/snap.*/tmp/ -> /tmp/,
- mount fstype=devpts options=(rw) devpts -> /dev/pts/,
- mount options=(rw bind) /dev/pts/ptmx -> /dev/ptmx, # for bind mounting
-
- # for running snaps on ubuntu
+ /{tmp/snap.rootfs_*/,}tmp/ w,
+ /{tmp/snap.rootfs_*/,}tmp/snap.*/ w,
+ /{tmp/snap.rootfs_*/,}tmp/snap.*/tmp/ w,
+ mount options=(rw private) -> /{tmp/snap.rootfs_*/,}tmp/,
+ mount options=(rw bind) /{tmp/snap.rootfs_*/,}tmp/snap.*/tmp/ -> /{tmp/snap.rootfs_*/,}tmp/,
+ mount fstype=devpts options=(rw) devpts -> /{tmp/snap.rootfs_*/,}dev/pts/,
+ mount options=(rw bind) /{tmp/snap.rootfs_*/,}dev/pts/ptmx -> /{tmp/snap.rootfs_*/,}dev/ptmx, # for bind mounting
+
+ # for running snaps on classic
mount options=(rw rslave) -> /,
- /snap/ r,
- /snap/** r,
+ /{tmp/snap.rootfs_*,}snap/ r,
+ /{tmp/snap.rootfs_*,}snap/** r,
+
+ # This is used when --enable-rootfs-is-core-snap is used
+ mount options=(rw bind) /snap/ubuntu-core/*/ -> /tmp/snap.rootfs_*/,
+
+ mount options=(rw rbind) /dev/ -> /tmp/snap.rootfs_*/dev/,
+ mount options=(rw rbind) /etc/ -> /tmp/snap.rootfs_*/etc/,
+ mount options=(rw rbind) /home/ -> /tmp/snap.rootfs_*/home/,
+ mount options=(rw rbind) /proc/ -> /tmp/snap.rootfs_*/proc/,
+ mount options=(rw rbind) /snap/ -> /tmp/snap.rootfs_*/snap/,
+ mount options=(rw rbind) /sys/ -> /tmp/snap.rootfs_*/sys/,
+ mount options=(rw rbind) /tmp/ -> /tmp/snap.rootfs_*/tmp/,
+ mount options=(rw rbind) /var/lib/snapd/ -> /tmp/snap.rootfs_*/var/lib/snapd/,
+ mount options=(rw rbind) /var/snap/ -> /tmp/snap.rootfs_*/var/snap/,
+ mount options=(rw rbind) /var/tmp/ -> /tmp/snap.rootfs_*/var/tmp/,
+
+ # This is used when --enable-rootfs-is-core-snap is NOT used
mount options=(rw bind) /snap/ubuntu-core/*/bin/ -> /bin/,
mount options=(rw bind) /snap/ubuntu-core/*/sbin/ -> /sbin/,
mount options=(rw bind) /snap/ubuntu-core/*/lib/ -> /lib/,
@@ -92,6 +108,15 @@
mount options=(rw bind) /snap/ubuntu-core/*/lib64/ -> /lib64/,
mount options=(rw bind) /snap/ubuntu-core/*/usr/ -> /usr/,
+ # nvidia handling, glob needs /usr/** and the launcher must be
+ # able to bind mount the nvidia dir
+ /usr/** r,
+ mount options=(rw bind) /usr/lib/nvidia-*/ -> /var/lib/snapd/lib/gl/,
+
+ # for chroot on steroids, we use pivot_root as a better chroot that makes
+ # apparmor rules behave the same on classic and outside of classic.
+ pivot_root,
+
# for creating the user data directories: ~/snap, ~/snap/<name> and
# ~/snap/<name>/<version>
/ r,
diff --git a/src/Makefile.am b/src/Makefile.am
index 0893d2c826..727af29f9d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-bin_PROGRAMS = snap-confine
+libexec_PROGRAMS = snap-confine
snap_confine_SOURCES = \
main.c \
utils.c \
@@ -8,7 +8,9 @@ snap_confine_SOURCES = \
classic.c \
classic.h \
mount-support.c \
- mount-support.h
+ mount-support.h \
+ mount-support-nvidia.c \
+ mount-support-nvidia.h
snap_confine_CFLAGS = -Wall -Werror
snap_confine_LDADD =
@@ -18,8 +20,8 @@ snap_confine_SOURCES += \
seccomp-support.h \
udev-support.c \
udev-support.h
-snap_confine_CFLAGS += $(APPARMOR_CFLAGS) $(SECCOMP_CFLAGS) $(UDEV_CFLAGS)
-snap_confine_LDADD += $(APPARMOR_LIBS) $(SECCOMP_LIBS) $(UDEV_LIBS)
+snap_confine_CFLAGS += $(APPARMOR_CFLAGS) $(SECCOMP_CFLAGS) $(LIBUDEV_CFLAGS)
+snap_confine_LDADD += $(APPARMOR_LIBS) $(SECCOMP_LIBS) $(LIBUDEV_LIBS)
endif
# Force particular coding style on all source and header files.
@@ -50,15 +52,15 @@ EXTRA_DIST = 80-snappy-assign.rules snappy-app-dev
if STRICT_CONFINEMENT
# Install udev rules
install-data-local:
- install -d -m 755 $(DESTDIR)/lib/udev/rules.d
- install -m 644 80-snappy-assign.rules $(DESTDIR)/lib/udev/rules.d
+ install -d -m 755 $(DESTDIR)$(shell pkg-config udev --variable=udevdir)/rules.d
+ install -m 644 80-snappy-assign.rules $(DESTDIR)$(shell pkg-config udev --variable=udevdir)/rules.d
# Install support script for udev rules
install-exec-local:
- install -d -m 755 $(DESTDIR)/lib/udev
- install -m 755 snappy-app-dev $(DESTDIR)/lib/udev/
+ install -d -m 755 $(DESTDIR)$(shell pkg-config udev --variable=udevdir)
+ install -m 755 snappy-app-dev $(DESTDIR)$(shell pkg-config udev --variable=udevdir)
endif
# Ensure that snap-confine is +s (setuid)
install-exec-hook:
- chmod 4755 $(DESTDIR)$(bindir)/snap-confine
+ chmod 4755 $(DESTDIR)$(libexecdir)/snap-confine
diff --git a/src/README.nvidia b/src/README.nvidia
new file mode 100644
index 0000000000..bdcae4c28d
--- /dev/null
+++ b/src/README.nvidia
@@ -0,0 +1,26 @@
+Nvidia on Arch
+==============
+
+On Arch nvidia support differs depending on the version of the driver user.
+Free drivers should work out of the box without any changes. Proprietary
+drivers were tested on the following driver versions:
+
+nvidia-340xx 340.96-13
+nvidia-340xx-libgl 340.96-1
+nvidia-340xx-utils 340.96-1
+
+The way the driver stack works was changed significantly in driver 364 and that
+version does not yet work correctly (we will gladly take patches if you beat us
+to the punch!). There is some ongoing work but it needs more investigation.
+
+Nvidia on Ubuntu
+================
+
+On Ubuntu nvidia drivers are provided in a different way and we believe that
+all versions work correctly.
+
+Nvidia on $DISTRO
+=================
+
+Free drivers should work everywhere. Support for proprietary drivers will be
+added on a case-by-case basis.
diff --git a/src/classic.h b/src/classic.h
index ff5bc65eee..8927979ad9 100644
--- a/src/classic.h
+++ b/src/classic.h
@@ -19,6 +19,9 @@
#include <stdbool.h>
+// Location of the host filesystem directory in the core snap.
+#define SC_HOSTFS_DIR "/var/lib/snapd/hostfs"
+
bool is_running_on_classic_distribution();
#endif
diff --git a/src/mount-support-nvidia.c b/src/mount-support-nvidia.c
new file mode 100644
index 0000000000..2411d92bae
--- /dev/null
+++ b/src/mount-support-nvidia.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+#include "mount-support-nvidia.h"
+
+#include <fcntl.h>
+#include <glob.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "utils.h"
+
+#ifdef NVIDIA_ARCH
+
+// List of globs that describe nvidia userspace libraries.
+// This list was compiled from the following packages.
+//
+// https://www.archlinux.org/packages/extra/x86_64/nvidia-304xx-libgl/files/
+// https://www.archlinux.org/packages/extra/x86_64/nvidia-304xx-utils/files/
+// https://www.archlinux.org/packages/extra/x86_64/nvidia-340xx-libgl/files/
+// https://www.archlinux.org/packages/extra/x86_64/nvidia-340xx-utils/files/
+// https://www.archlinux.org/packages/extra/x86_64/nvidia-libgl/files/
+// https://www.archlinux.org/packages/extra/x86_64/nvidia-utils/files/
+//
+// FIXME: this doesn't yet work with libGLX and libglvnd redirector
+static const char *nvidia_globs[] = {
+ "/usr/lib/libEGL.so*",
+ "/usr/lib/libEGL_nvidia.so*",
+ "/usr/lib/libGL.so*",
+ "/usr/lib/libGLESv1_CM.so*",
+ "/usr/lib/libGLESv1_CM_nvidia.so*",
+ "/usr/lib/libGLESv2.so*",
+ "/usr/lib/libGLESv2_nvidia.so*",
+ "/usr/lib/libGLX_indirect.so*",
+ "/usr/lib/libGLX_nvidia.so*",
+ "/usr/lib/libXvMCNVIDIA.so*",
+ "/usr/lib/libXvMCNVIDIA_dynamic.so*",
+ "/usr/lib/libcuda.so*",
+ "/usr/lib/libnvcuvid.so*",
+ "/usr/lib/libnvidia-cfg.so*",
+ "/usr/lib/libnvidia-eglcore.so*",
+ "/usr/lib/libnvidia-encode.so*",
+ "/usr/lib/libnvidia-fatbinaryloader.so*",
+ "/usr/lib/libnvidia-fbc.so*",
+ "/usr/lib/libnvidia-glcore.so*",
+ "/usr/lib/libnvidia-glsi.so*",
+ "/usr/lib/libnvidia-ifr.so*",
+ "/usr/lib/libnvidia-ml.so*",
+ "/usr/lib/libnvidia-ptxjitcompiler.so*",
+ "/usr/lib/libnvidia-tls.so*",
+};
+
+static const size_t nvidia_globs_len =
+ sizeof nvidia_globs / sizeof *nvidia_globs;
+
+static void cleanup_string(char **ptr)
+{
+ free(*ptr);
+}
+
+// Populate libgl_dir with a symlink farm to files matching glob_list.
+//
+// The symbolic links are made in one of two ways. If the library found is a
+// file a regular symlink "$libname" -> "/path/to/hostfs/$libname" is created.
+// If the library is a symbolic link then relative links are kept as-is but
+// absolute links are translated to have "/path/to/hostfs" up front so that
+// they work after the pivot_root elsewhere.
+static void sc_populate_libgl_with_hostfs_symlinks(const char *libgl_dir,
+ const char *glob_list[],
+ size_t glob_list_len)
+{
+ glob_t glob_res __attribute__ ((__cleanup__(globfree))) = {
+ .gl_pathv = NULL};
+ // Find all the entries matching the list of globs
+ for (size_t i = 0; i < glob_list_len; ++i) {
+ const char *glob_pattern = glob_list[i];
+ int err =
+ glob(glob_pattern, i ? GLOB_APPEND : 0, NULL, &glob_res);
+ // Not all of the files have to be there (they differ depending on the
+ // driver version used). Ignore all errors that are not GLOB_NOMATCH.
+ if (err != 0 && err != GLOB_NOMATCH) {
+ die("cannot search using glob pattern %s: %d",
+ glob_pattern, err);
+ }
+ }
+ // Symlink each file found
+ for (size_t i = 0; i < glob_res.gl_pathc; ++i) {
+ char symlink_name[512];
+ char symlink_target[512];
+ const char *pathname = glob_res.gl_pathv[i];
+ char *pathname_copy __attribute__ ((cleanup(cleanup_string))) =
+ strdup(pathname);
+ char *filename = basename(pathname_copy);
+ struct stat stat_buf;
+ int err = lstat(pathname, &stat_buf);
+ if (err != 0) {
+ die("cannot stat file %s", pathname);
+ }
+ switch (stat_buf.st_mode & S_IFMT) {
+ case S_IFLNK:;
+ // Read the target of the symbolic link
+ char hostfs_symlink_target[512];
+ ssize_t num_read;
+ hostfs_symlink_target[0] = 0;
+ num_read =
+ readlink(pathname, hostfs_symlink_target,
+ sizeof hostfs_symlink_target);
+ if (num_read == -1) {
+ die("cannot read symbolic link %s", pathname);
+ }
+ hostfs_symlink_target[num_read] = 0;
+ if (hostfs_symlink_target[0] == '/') {
+ must_snprintf(symlink_target,
+ sizeof symlink_target,
+ "/var/lib/snapd/hostfs%s",
+ hostfs_symlink_target);
+ } else {
+ // Keep relative symlinks as-is, so that they point to -> libfoo.so.0.123
+ must_snprintf(symlink_target,
+ sizeof symlink_target, "%s",
+ hostfs_symlink_target);
+ }
+ break;
+ case S_IFREG:
+ must_snprintf(symlink_target,
+ sizeof symlink_target,
+ "/var/lib/snapd/hostfs%s", pathname);
+ break;
+ default:
+ debug("ignoring unsupported entry: %s", pathname);
+ continue;
+ }
+ must_snprintf(symlink_name, sizeof symlink_name,
+ "%s/%s", libgl_dir, filename);
+ debug("creating symbolic link %s -> %s", symlink_name,
+ symlink_target);
+ if (symlink(symlink_target, symlink_name) != 0) {
+ die("cannot create symbolic link %s -> %s",
+ symlink_name, symlink_target);
+ }
+ }
+}
+
+static void sc_mount_nvidia_driver_arch(const char *rootfs_dir)
+{
+ // Bind mount a tmpfs on $rootfs_dir/var/lib/snapd/lib/gl
+ char buf[512];
+ must_snprintf(buf, sizeof(buf), "%s%s", rootfs_dir,
+ "/var/lib/snapd/lib/gl");
+ const char *libgl_dir = buf;
+ debug("mounting tmpfs at %s", libgl_dir);
+ if (mount("none", libgl_dir, "tmpfs", MS_NODEV | MS_NOEXEC, NULL) != 0) {
+ die("cannot mount tmpfs at %s", libgl_dir);
+ };
+ // Populate libgl_dir with symlinks to libraries from hostfs
+ sc_populate_libgl_with_hostfs_symlinks(libgl_dir, nvidia_globs,
+ nvidia_globs_len);
+ // Remount .../lib/gl read only
+ debug("remounting tmpfs as read-only %s", libgl_dir);
+ if (mount(NULL, buf, NULL, MS_REMOUNT | MS_RDONLY, NULL) != 0) {
+ die("cannot remount %s as read-only", buf);
+ }
+}
+
+#endif // ifdef NVIDIA_ARCH
+
+#ifdef NVIDIA_UBUNTU
+static void sc_mount_nvidia_driver_ubuntu(const char *rootfs_dir)
+{
+ // The driver can be in one of a few locations. On some distributions
+ // it is /usr/lib/nvidia-{xxx} (where xxx is the version number)
+ // on other distributions it is just /usr/lib/nvidia.
+ // Before this is all made easy by snapd and the mount security backend
+ // we just look in all the possible places.
+ const char *glob_pattern = "/usr/lib/nvidia-[1-9][0-9][0-9]";
+ glob_t glob_res __attribute__ ((__cleanup__(globfree))) = {
+ .gl_pathv = NULL};
+ int err = glob(glob_pattern, GLOB_ONLYDIR | GLOB_MARK, NULL, &glob_res);
+ debug("glob(%s, ...) returned %d", glob_pattern, err);
+ switch (glob_res.gl_pathc) {
+ case 0:
+ debug("cannot find any nvidia drivers");
+ break;
+ case 1:;
+ // Bind mount the binary nvidia driver into /var/lib/snapd/lib/gl.
+ const char *src = glob_res.gl_pathv[0];
+ char buf[512];
+ must_snprintf(buf, sizeof(buf), "%s%s", rootfs_dir,
+ "/var/lib/snapd/lib/gl");
+ const char *dst = buf;
+
+ debug("bind mounting nvidia driver %s -> %s", src, dst);
+ if (mount(src, dst, NULL, MS_BIND, NULL) != 0) {
+ die("cannot bind mount nvidia driver %s -> %s",
+ src, dst);
+ }
+ break;
+ default:
+ die("multiple nvidia drivers detected, this is not supported");
+ break;
+ }
+}
+#endif // ifdef NVIDIA_UBUNTU
+
+void sc_mount_nvidia_driver(const char *rootfs_dir)
+{
+#ifdef NVIDIA_UBUNTU
+ sc_mount_nvidia_driver_ubuntu(rootfs_dir);
+#endif // ifdef NVIDIA_UBUNTU
+#ifdef NVIDIA_ARCH
+ sc_mount_nvidia_driver_arch(rootfs_dir);
+#endif // ifdef NVIDIA_ARCH
+}
diff --git a/src/mount-support-nvidia.h b/src/mount-support-nvidia.h
new file mode 100644
index 0000000000..d05d284513
--- /dev/null
+++ b/src/mount-support-nvidia.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SNAP_CONFINE_MOUNT_SUPPORT_NVIDIA_H
+#define SNAP_CONFINE_MOUNT_SUPPORT_NVIDIA_H
+
+void sc_mount_nvidia_driver(const char *rootfs_dir);
+
+#endif
diff --git a/src/mount-support.c b/src/mount-support.c
index 668d13beb1..762f7a356a 100644
--- a/src/mount-support.c
+++ b/src/mount-support.c
@@ -24,12 +24,17 @@
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
+#ifdef ROOTFS_IS_CORE_SNAP
+#include <sys/syscall.h>
+#endif
#include <errno.h>
#include <sched.h>
#include <string.h>
#include "utils.h"
#include "snap.h"
+#include "classic.h"
+#include "mount-support-nvidia.h"
#define MAX_BUF 1000
@@ -124,11 +129,108 @@ void setup_private_pts()
#endif // ifdef STRICT_CONFINEMENT
}
+#ifdef NVIDIA_ARCH
+static void sc_bind_mount_hostfs(const char *rootfs_dir)
+{
+ // Create a read-only bind mount from "/" to
+ // "$rootfs_dir/var/lib/snapd/hostfs".
+ char buf[512];
+ must_snprintf(buf, sizeof buf, "%s%s", rootfs_dir, SC_HOSTFS_DIR);
+ debug("bind-mounting host filesystem at %s", buf);
+ if (mount("/", buf, NULL, MS_BIND | MS_RDONLY, NULL) != 0) {
+ if (errno == ENOENT) {
+ die("cannot bind-mount host filesystem\n"
+ "the core snap is too old, please run: snap refresh ubuntu-core");
+ } else {
+ die("cannot bind-mount host filesystem at %s", buf);
+ }
+ }
+}
+#endif // ifdef NVIDIA_ARCH
+
void setup_snappy_os_mounts()
{
debug("%s", __func__);
#ifdef ROOTFS_IS_CORE_SNAP
-#error "not implemented"
+ char rootfs_dir[MAX_BUF] = { 0 };
+ // Create a temporary directory that will become the root directory of this
+ // process later on. The directory will be used as a mount point for the
+ // core snap.
+ //
+ // XXX: This directory is never cleaned up today.
+ must_snprintf(rootfs_dir, sizeof(rootfs_dir),
+ "/tmp/snap.rootfs_XXXXXX");
+ if (mkdtemp(rootfs_dir) == NULL) {
+ die("cannot create temporary directory for the root file system");
+ }
+ // Bind mount the OS snap into the rootfs directory.
+ const char *core_snap_dir = "/snap/ubuntu-core/current";
+ debug("bind mounting core snap: %s -> %s", core_snap_dir, rootfs_dir);
+ if (mount(core_snap_dir, rootfs_dir, NULL, MS_BIND, NULL) != 0) {
+ die("cannot bind mount core snap: %s to %s", core_snap_dir,
+ rootfs_dir);
+ }
+ // Bind mount certain directories from the rootfs directory (with the core
+ // snap) to various places on the host OS. Each directory is justified with
+ // a short comment below.
+ const char *source_mounts[] = {
+ "/dev", // because it contains devices on host OS
+ "/etc", // because that's where /etc/resolv.conf lives, perhaps a bad idea
+ "/home", // to support /home/*/snap and home interface
+ "/proc", // fundamental filesystem
+ "/snap", // to get access to all the snaps
+ "/sys", // fundamental filesystem
+ "/tmp", // to get writable tmp
+ "/var/snap", // to get access to global snap data
+ "/var/lib/snapd", // to get access to snapd state and seccomp profiles
+ "/var/tmp", // to get access to the other temporary directory
+ };
+ for (int i = 0; i < sizeof(source_mounts) / sizeof *source_mounts; i++) {
+ const char *src = source_mounts[i];
+ char dst[512];
+ must_snprintf(dst, sizeof dst, "%s%s", rootfs_dir,
+ source_mounts[i]);
+ debug("bind mounting %s to %s", src, dst);
+ // NOTE: MS_REC so that we can see anything that may be mounted under
+ // any of the directories already. This is crucial for /snap, for
+ // example.
+ //
+ // NOTE: MS_SLAVE so that the started process cannot maliciously mount
+ // anything into those places and affect the system on the outside.
+ if (mount(src, dst, NULL, MS_BIND | MS_REC | MS_SLAVE, NULL) !=
+ 0) {
+ die("cannot bind mount %s to %s", src, dst);
+ }
+ }
+#ifdef NVIDIA_ARCH
+ // Make this conditional on Nvidia support for Arch as Ubuntu doesn't use
+ // this so far and it requires a very recent version of the core snap.
+ sc_bind_mount_hostfs(rootfs_dir);
+#endif
+ sc_mount_nvidia_driver(rootfs_dir);
+ // Chroot into the new root filesystem so that / is the core snap. Why are
+ // we using something as esoteric as pivot_root? Because this makes apparmor
+ // handling easy. Using a normal chroot makes all apparmor rules conditional.
+ // We are either running on an all-snap system where this would-be chroot
+ // didn't happen and all the rules see / as the root file system _OR_
+ // we are running on top of a classic distribution and this chroot has now
+ // moved all paths to /tmp/snap.rootfs_*. Because we are using unshare with
+ // CLONE_NEWNS we can essentially use pivot_root just like chroot but this
+ // makes apparmor unaware of the old root so everything works okay.
+ debug("chrooting into %s", rootfs_dir);
+ if (chdir(rootfs_dir) == -1) {
+ die("cannot change working directory to %s", rootfs_dir);
+ }
+ if (syscall(SYS_pivot_root, ".", rootfs_dir) == -1) {
+ die("cannot pivot_root to the new root filesystem");
+ }
+ // Reset path as we cannot rely on the path from the host OS to
+ // make sense. The classic distribution may use any PATH that makes
+ // sense but we cannot assume it makes sense for the core snap
+ // layout. Note that the /usr/local directories are explicitly
+ // left out as they are not part of the core snap.
+ debug("resetting PATH to values in sync with core snap");
+ setenv("PATH", "/usr/sbin:/usr/bin:/sbin:/bin:/usr/games", 1);
#else
// we mount some whitelisted directories
//
@@ -161,6 +263,7 @@ void setup_snappy_os_mounts()
die("unable to bind %s to %s", src, dst);
}
}
+ sc_mount_nvidia_driver("");
#endif // ROOTFS_IS_CORE_SNAP
}
diff --git a/src/udev-support.c b/src/udev-support.c
index 101ab27cdc..95be1e872c 100644
--- a/src/udev-support.c
+++ b/src/udev-support.c
@@ -19,6 +19,7 @@
#include <unistd.h>
#include <limits.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 026dc0ef1f..8c47b88e9f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -6,7 +6,6 @@ TESTS += \
test_bad_seccomp_filter_missing_trailing_newline \
test_complain \
test_complain_missed \
- test_create_user_data \
test_noprofile \
test_restrictions_working \
test_unrestricted \
diff --git a/tests/test_create_user_data b/tests/test_create_user_data
deleted file mode 100755
index f6cf026852..0000000000
--- a/tests/test_create_user_data
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/bin/sh
-
-set -e
-
-. "$(pwd)/common.sh"
-
-cat >"$TMP/snap.name.app-unrestricted" <<EOF
-# some comment
-@unrestricted
-EOF
-
-cat >"$TMP/snap.name.app-restricted" <<EOF
-# filter that works ok for true
-open
-close
-
-mmap
-munmap
-mprotect
-
-fstat
-access
-read
-
-brk
-execve
-
-arch_prctl
-exit_group
-
-# required for not setting nnp
-geteuid
-getuid
-
-# unknown syscalls are ignore
-i-dont-exit
-EOF
-
-# $1: Path to check existence for and potentially remove at the end
-# $2: either 'restricted' or 'unrestricted'
-# $3: True if success is expected, false otherwise
-run_launcher() {
- pass=false
- if "$L" "snap.name.app-$2" /bin/true 2>/dev/null; then
- if $3; then
- if [ ! -d "$1" ]; then
- pass=false
- fi
- pass=true
- else
- pass=false
- fi
- else
- if $3; then
- pass=false
- else
- pass=true
- fi
- fi
-
- if [ -d "$1" ]; then
- rmdir "$1"
- fi
-
- if $pass; then
- return 0
- else
- return 1
- fi
-}
-
-# $1 = $SNAP_USER_DATA definition
-# $2 = Profile name
-# $3 = True if success is expected, false otherwise
-run_current() {
- export SNAP_USER_DATA="$1"
- run_launcher "$1" "$2" "$3"
- pass=$?
- unset SNAP_USER_DATA
-
- return $pass
-}
-
-printf "Test that an unrestricted launcher creates user data"
-if run_current "$TMP/user_data" unrestricted true; then
- PASS
-else
- FAIL
-fi
-
-printf "Test that a restricted launcher creates user data"
-if run_current "$TMP/user_data" restricted true; then
- PASS
-else
- FAIL
-fi
-
-printf "Test that an unrestricted launcher creates user data with parent directory"
-if run_current "$TMP/parent/user_data" unrestricted true; then
- PASS
-else
- FAIL
-fi
-
-printf "Test that a restricted launcher creates user data with parent directory"
-if run_current "$TMP/parent/user_data" restricted true; then
- PASS
-else
- FAIL
-fi
-
-printf "Test that user data can contain multiple path separators"
-if run_current "$TMP//user_data" unrestricted true; then
- PASS
-else
- FAIL
-fi
-
-printf "Test that user data must be absolute"
-if run_current "../foo" unrestricted false; then
- PASS
-else
- FAIL
-fi
-
-printf "Testing that user data cannot be contained within a symlink"
-mkdir "$TMP/nefarious_parent"
-ln -s "$TMP/nefarious_parent" "$TMP/parent"
-# NOTE: the comma below is significant
-if run_current "$TMP/parent/user_data" unrestricted, false; then
- PASS
-else
- FAIL
-fi
-
-printf "Test that an unrestricted launcher works when user data exists (current)"
-mkdir "$TMP/user_data"
-if run_current "$TMP/user_data" unrestricted true; then
- PASS
-else
- FAIL
-fi
-
-printf "Test that an restricted launcher works when user data exists (current)"
-mkdir "$TMP/user_data"
-if run_current "$TMP/user_data" restricted true; then
- PASS
-else
- FAIL
-fi