diff options
| author | Zygmunt Krynicki <me@zygoon.pl> | 2016-06-13 14:36:03 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-06-13 14:36:03 +0200 |
| commit | 506eb060c69d2c03059d0f805acbcf0f2a2a6664 (patch) | |
| tree | be937e80d22a276fc9b7b9968bc2c2fa296dd1f0 | |
| parent | f28b33b3599dc3884e8c41641a7da57eb276d520 (diff) | |
| parent | 92b0b9cf6cf2e2bf75c2f1c494bf1092ca3ed0b0 (diff) | |
Merge pull request #36 from ubuntu-core/next-release
Release 1.0.29
| -rw-r--r-- | compat/Makefile.am | 4 | ||||
| -rw-r--r-- | compat/ubuntu-core-launcher.in | 2 | ||||
| -rw-r--r-- | configure.ac | 33 | ||||
| -rw-r--r-- | debian/changelog | 10 | ||||
| -rw-r--r-- | debian/control | 26 | ||||
| -rwxr-xr-x | debian/rules | 8 | ||||
| -rw-r--r-- | debian/snap-confine.install | 2 | ||||
| -rw-r--r-- | debian/snap-confine.lintian-overrides | 2 | ||||
| -rw-r--r-- | debian/ubuntu-core-launcher.install | 2 | ||||
| -rw-r--r-- | debian/ubuntu-core-launcher.maintscript | 1 | ||||
| -rwxr-xr-x | debian/ubuntu-core-launcher.postinst | 4 | ||||
| -rwxr-xr-x | debian/ubuntu-core-launcher.postrm | 6 | ||||
| -rwxr-xr-x | debian/ubuntu-core-launcher.preinst | 6 | ||||
| -rw-r--r-- | debian/usr.bin.snap-confine | 49 | ||||
| -rw-r--r-- | src/Makefile.am | 20 | ||||
| -rw-r--r-- | src/README.nvidia | 26 | ||||
| -rw-r--r-- | src/classic.h | 3 | ||||
| -rw-r--r-- | src/mount-support-nvidia.c | 232 | ||||
| -rw-r--r-- | src/mount-support-nvidia.h | 23 | ||||
| -rw-r--r-- | src/mount-support.c | 105 | ||||
| -rw-r--r-- | src/udev-support.c | 1 | ||||
| -rw-r--r-- | tests/Makefile.am | 1 | ||||
| -rwxr-xr-x | tests/test_create_user_data | 150 |
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 |
