diff -Nru snap-confine-1.0.38/config.h.in snap-confine-1.0.41/config.h.in --- snap-confine-1.0.38/config.h.in 2016-07-15 14:01:08.000000000 +0000 +++ snap-confine-1.0.41/config.h.in 2016-09-19 09:45:03.000000000 +0000 @@ -1,5 +1,8 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* Use capabilities rather than setuid bit */ +#undef CAPS_OVER_SETUID + /* Build with apparmor support */ #undef HAVE_APPARMOR @@ -30,6 +33,9 @@ /* Build with seccomp support */ #undef HAVE_SECCOMP +/* Define to 1 if you have the `secure_getenv' function. */ +#undef HAVE_SECURE_GETENV + /* Define to 1 if you have the `setenv' function. */ #undef HAVE_SETENV @@ -78,6 +84,9 @@ /* Define to 1 if the system has the type `_Bool'. */ #undef HAVE__BOOL +/* Support for merged /usr directory */ +#undef MERGED_USR + /* Support for propietary nvidia drivers (Arch) */ #undef NVIDIA_ARCH @@ -105,6 +114,9 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* Location of the snap mount points */ +#undef SNAP_MOUNT_DIR + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff -Nru snap-confine-1.0.38/configure snap-confine-1.0.41/configure --- snap-confine-1.0.38/configure 2016-07-15 14:01:08.000000000 +0000 +++ snap-confine-1.0.41/configure 2016-09-19 09:44:58.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for snap-confine 1.0.38. +# Generated by GNU Autoconf 2.69 for snap-confine 1.0.41. # # Report bugs to . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='snap-confine' PACKAGE_TARNAME='snap-confine' -PACKAGE_VERSION='1.0.38' -PACKAGE_STRING='snap-confine 1.0.38' +PACKAGE_VERSION='1.0.41' +PACKAGE_STRING='snap-confine 1.0.41' PACKAGE_BUGREPORT='snapcraft@lists.ubuntu.com' PACKAGE_URL='' @@ -625,12 +625,15 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS +CAPS_OVER_SETUID_FALSE +CAPS_OVER_SETUID_TRUE +SNAP_MOUNT_DIR +MERGED_USR_FALSE +MERGED_USR_TRUE NVIDIA_ARCH_FALSE NVIDIA_ARCH_TRUE NVIDIA_UBUNTU_FALSE NVIDIA_UBUNTU_TRUE -GLIB_LIBS -GLIB_CFLAGS UDEV_LIBS UDEV_CFLAGS LIBUDEV_LIBS @@ -639,6 +642,8 @@ APPARMOR_CFLAGS SECCOMP_LIBS SECCOMP_CFLAGS +GLIB_LIBS +GLIB_CFLAGS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG @@ -648,6 +653,8 @@ SECCOMP_TRUE APPARMOR_FALSE APPARMOR_TRUE +WITH_UNIT_TESTS_FALSE +WITH_UNIT_TESTS_TRUE host_os host_vendor host_cpu @@ -752,10 +759,14 @@ enable_dependency_tracking enable_silent_rules enable_maintainer_mode +with_unit_tests enable_apparmor enable_seccomp enable_nvidia_ubuntu enable_nvidia_arch +enable_merged_usr +with_snap_mount_dir +enable_caps_over_setuid ' ac_precious_vars='build_alias host_alias @@ -769,6 +780,8 @@ PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR +GLIB_CFLAGS +GLIB_LIBS SECCOMP_CFLAGS SECCOMP_LIBS APPARMOR_CFLAGS @@ -776,9 +789,7 @@ LIBUDEV_CFLAGS LIBUDEV_LIBS UDEV_CFLAGS -UDEV_LIBS -GLIB_CFLAGS -GLIB_LIBS' +UDEV_LIBS' # Initialize some variables set by options. @@ -1329,7 +1340,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures snap-confine 1.0.38 to adapt to many kinds of systems. +\`configure' configures snap-confine 1.0.41 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1400,7 +1411,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of snap-confine 1.0.38:";; + short | recursive ) echo "Configuration of snap-confine 1.0.41:";; esac cat <<\_ACEOF @@ -1421,6 +1432,16 @@ --disable-seccomp Disable seccomp support --enable-nvidia-ubuntu Support for proprietary nvidia drivers (Ubuntu) --enable-nvidia-arch Support for proprietary nvidia drivers (Arch) + --enable-merged-usr Enable support for merged /usr directory + --enable-caps-over-setuid + Use capabilities rather than setuid bit + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --without-unit-tests do not build unit test programs + --with-snap-mount-dir=DIR + Use an alternate snap mount directory Some influential environment variables: CC C compiler command @@ -1436,6 +1457,8 @@ directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path + GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config + GLIB_LIBS linker flags for GLIB, overriding pkg-config SECCOMP_CFLAGS C compiler flags for SECCOMP, overriding pkg-config SECCOMP_LIBS @@ -1450,8 +1473,6 @@ linker flags for LIBUDEV, overriding pkg-config UDEV_CFLAGS C compiler flags for UDEV, overriding pkg-config UDEV_LIBS linker flags for UDEV, overriding pkg-config - GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config - GLIB_LIBS linker flags for GLIB, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1519,7 +1540,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -snap-confine configure 1.0.38 +snap-confine configure 1.0.41 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1942,7 +1963,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by snap-confine $as_me 1.0.38, which was +It was created by snap-confine $as_me 1.0.41, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -4178,7 +4199,7 @@ # Define the identity of the package. PACKAGE='snap-confine' - VERSION='1.0.38' + VERSION='1.0.41' cat >>confdefs.h <<_ACEOF @@ -5388,7 +5409,7 @@ esac -for ac_func in mkdir regcomp setenv strdup strerror +for ac_func in mkdir regcomp setenv strdup strerror secure_getenv do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -5401,6 +5422,27 @@ done + +# Check whether --with-unit-tests was given. +if test "${with_unit_tests+set}" = set; then : + withval=$with_unit_tests; case "${withval}" in + yes) with_unit_tests=yes ;; + no) with_unit_tests=no ;; + *) as_fn_error $? "bad value ${withval} for --without-unit-tests" "$LINENO" 5 + esac +else + with_unit_tests=yes +fi + + if test "x$with_unit_tests" = "xyes"; then + WITH_UNIT_TESTS_TRUE= + WITH_UNIT_TESTS_FALSE='#' +else + WITH_UNIT_TESTS_TRUE='#' + WITH_UNIT_TESTS_FALSE= +fi + + # Allow to build without apparmor support by calling: # ./configure --disable-apparmor # This makes it possible to run snaps in devmode on almost any host, @@ -5460,7 +5502,7 @@ fi -# Check if seccomp userspace library is available +# Check for glib that we use for unit testing @@ -5581,6 +5623,103 @@ PKG_CONFIG="" fi fi +if test "x$with_unit_tests" = "xyes"; then : + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 +$as_echo_n "checking for GLIB... " >&6; } + +if test -n "$GLIB_CFLAGS"; then + pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GLIB_LIBS"; then + pkg_cv_GLIB_LIBS="$GLIB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "glib-2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0" 2>&1` + else + GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GLIB_PKG_ERRORS" >&5 + + as_fn_error $? "Package requirements (glib-2.0) were not met: + +$GLIB_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GLIB_CFLAGS +and GLIB_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details." "$LINENO" 5 +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GLIB_CFLAGS +and GLIB_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details" "$LINENO" 5; } +else + GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS + GLIB_LIBS=$pkg_cv_GLIB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +fi + +fi + +# Check if seccomp userspace library is available if test "x$enable_seccomp" = "xyes"; then : @@ -5979,98 +6118,6 @@ $as_echo "yes" >&6; } fi -# Check for glib that we use for unit testing - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 -$as_echo_n "checking for GLIB... " >&6; } - -if test -n "$GLIB_CFLAGS"; then - pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "glib-2.0") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$GLIB_LIBS"; then - pkg_cv_GLIB_LIBS="$GLIB_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0\""; } >&5 - ($PKG_CONFIG --exists --print-errors "glib-2.0") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "glib-2.0" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0" 2>&1` - else - GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$GLIB_PKG_ERRORS" >&5 - - as_fn_error $? "Package requirements (glib-2.0) were not met: - -$GLIB_PKG_ERRORS - -Consider adjusting the PKG_CONFIG_PATH environment variable if you -installed software in a non-standard prefix. - -Alternatively, you may set the environment variables GLIB_CFLAGS -and GLIB_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details." "$LINENO" 5 -elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it -is in your PATH or set the PKG_CONFIG environment variable to the full -path to pkg-config. - -Alternatively, you may set the environment variables GLIB_CFLAGS -and GLIB_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details. - -To get pkg-config, see . -See \`config.log' for more details" "$LINENO" 5; } -else - GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS - GLIB_LIBS=$pkg_cv_GLIB_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - -fi # Enable special support for hosts with proprietary nvidia drivers on Ubuntu. # Check whether --enable-nvidia-ubuntu was given. @@ -6128,6 +6175,74 @@ fi +# Check whether --enable-merged-usr was given. +if test "${enable_merged_usr+set}" = set; then : + enableval=$enable_merged_usr; case "${enableval}" in + yes) enable_merged_usr=yes ;; + no) enable_merged_usr=no ;; + *) as_fn_error $? "bad value ${enableval} for --enable-merged-usr" "$LINENO" 5 + esac +else + enable_merged_usr=no +fi + + if test "x$enable_merged_usr" = "xyes"; then + MERGED_USR_TRUE= + MERGED_USR_FALSE='#' +else + MERGED_USR_TRUE='#' + MERGED_USR_FALSE= +fi + + +if test "x$enable_merged_usr" = "xyes"; then : + + +$as_echo "#define MERGED_USR 1" >>confdefs.h + +fi + +SNAP_MOUNT_DIR="/snap" + +# Check whether --with-snap-mount-dir was given. +if test "${with_snap_mount_dir+set}" = set; then : + withval=$with_snap_mount_dir; SNAP_MOUNT_DIR="$withval" +fi + + + +cat >>confdefs.h <<_ACEOF +#define SNAP_MOUNT_DIR "${SNAP_MOUNT_DIR}" +_ACEOF + + +# Check whether --enable-caps-over-setuid was given. +if test "${enable_caps_over_setuid+set}" = set; then : + enableval=$enable_caps_over_setuid; case "${enableval}" in + yes) enable_caps_over_setuid=yes ;; + no) enable_caps_over_setuid=no ;; + *) as_fn_error $? "bad value ${enableval} for --enable-caps-over-setuid" "$LINENO" 5 + esac +else + enable_caps_over_setuid=no +fi + + if test "x$enable_caps_over_setuid" = "xyes"; then + CAPS_OVER_SETUID_TRUE= + CAPS_OVER_SETUID_FALSE='#' +else + CAPS_OVER_SETUID_TRUE='#' + CAPS_OVER_SETUID_FALSE= +fi + + +if test "x$enable_caps_over_setuid" = "xyes"; then : + + +$as_echo "#define CAPS_OVER_SETUID 1" >>confdefs.h + +fi + ac_config_files="$ac_config_files Makefile src/Makefile tests/Makefile docs/Makefile" cat >confcache <<\_ACEOF @@ -6267,6 +6382,10 @@ as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${WITH_UNIT_TESTS_TRUE}" && test -z "${WITH_UNIT_TESTS_FALSE}"; then + as_fn_error $? "conditional \"WITH_UNIT_TESTS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${APPARMOR_TRUE}" && test -z "${APPARMOR_FALSE}"; then as_fn_error $? "conditional \"APPARMOR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -6287,6 +6406,14 @@ as_fn_error $? "conditional \"NVIDIA_ARCH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${MERGED_USR_TRUE}" && test -z "${MERGED_USR_FALSE}"; then + as_fn_error $? "conditional \"MERGED_USR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${CAPS_OVER_SETUID_TRUE}" && test -z "${CAPS_OVER_SETUID_FALSE}"; then + as_fn_error $? "conditional \"CAPS_OVER_SETUID\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 @@ -6684,7 +6811,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by snap-confine $as_me 1.0.38, which was +This file was extended by snap-confine $as_me 1.0.41, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6750,7 +6877,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -snap-confine config.status 1.0.38 +snap-confine config.status 1.0.41 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru snap-confine-1.0.38/configure.ac snap-confine-1.0.41/configure.ac --- snap-confine-1.0.38/configure.ac 2016-07-15 12:53:41.000000000 +0000 +++ snap-confine-1.0.41/configure.ac 2016-09-19 09:41:32.000000000 +0000 @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([snap-confine], [1.0.38], [snapcraft@lists.ubuntu.com]) +AC_INIT([snap-confine], m4_esyscmd_s([cat VERSION]), [snapcraft@lists.ubuntu.com]) AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_HEADERS([config.h]) AC_USE_SYSTEM_EXTENSIONS @@ -30,7 +30,16 @@ AC_FUNC_ERROR_AT_LINE AC_FUNC_FORK AC_FUNC_STRNLEN -AC_CHECK_FUNCS([mkdir regcomp setenv strdup strerror]) +AC_CHECK_FUNCS([mkdir regcomp setenv strdup strerror secure_getenv]) + +AC_ARG_WITH([unit-tests], + AC_HELP_STRING([--without-unit-tests], [do not build unit test programs]), + [case "${withval}" in + yes) with_unit_tests=yes ;; + no) with_unit_tests=no ;; + *) AC_MSG_ERROR([bad value ${withval} for --without-unit-tests]) + esac], [with_unit_tests=yes]) +AM_CONDITIONAL([WITH_UNIT_TESTS], [test "x$with_unit_tests" = "xyes"]) # Allow to build without apparmor support by calling: # ./configure --disable-apparmor @@ -62,6 +71,11 @@ # The tests are of smaller value as we port more and more tests to spread. AM_CONDITIONAL([CONFINEMENT_TESTS], [test "x$enable_apparmor" = "xyes" && test "x$enable_seccomp" = "xyes" && ((test "x$host_cpu" = "xx86_64" && test "x$build_cpu" = "xx86_64") || (test "x$host_cpu" = "xi686" && test "x$build_cpu" = "xi686"))]) +# Check for glib that we use for unit testing +AS_IF([test "x$with_unit_tests" = "xyes"], [ + PKG_CHECK_MODULES([GLIB], [glib-2.0]) +]) + # Check if seccomp userspace library is available AS_IF([test "x$enable_seccomp" = "xyes"], [ PKG_CHECK_MODULES([SECCOMP], [libseccomp], [ @@ -85,8 +99,6 @@ # Those are now used unconditionally even if apparmor is disabled. PKG_CHECK_MODULES([LIBUDEV], [libudev]) PKG_CHECK_MODULES([UDEV], [udev]) -# Check for glib that we use for unit testing -PKG_CHECK_MODULES([GLIB], [glib-2.0]) # Enable special support for hosts with proprietary nvidia drivers on Ubuntu. AC_ARG_ENABLE([nvidia-ubuntu], @@ -116,5 +128,38 @@ AC_DEFINE([NVIDIA_ARCH], [1], [Support for propietary nvidia drivers (Arch)])]) +AC_ARG_ENABLE([merged-usr], + AS_HELP_STRING([--enable-merged-usr], [Enable support for merged /usr directory]), + [case "${enableval}" in + yes) enable_merged_usr=yes ;; + no) enable_merged_usr=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-merged-usr]) + esac], [enable_merged_usr=no]) +AM_CONDITIONAL([MERGED_USR], [test "x$enable_merged_usr" = "xyes"]) + +AS_IF([test "x$enable_merged_usr" = "xyes"], [ + AC_DEFINE([MERGED_USR], [1], + [Support for merged /usr directory])]) + +SNAP_MOUNT_DIR="/snap" +AC_ARG_WITH([snap-mount-dir], + AS_HELP_STRING([--with-snap-mount-dir=DIR], [Use an alternate snap mount directory]), + [SNAP_MOUNT_DIR="$withval"]) +AC_SUBST(SNAP_MOUNT_DIR) +AC_DEFINE_UNQUOTED([SNAP_MOUNT_DIR], "${SNAP_MOUNT_DIR}", [Location of the snap mount points]) + +AC_ARG_ENABLE([caps-over-setuid], + AS_HELP_STRING([--enable-caps-over-setuid], [Use capabilities rather than setuid bit]), + [case "${enableval}" in + yes) enable_caps_over_setuid=yes ;; + no) enable_caps_over_setuid=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-caps-over-setuid]) + esac], [enable_caps_over_setuid=no]) +AM_CONDITIONAL([CAPS_OVER_SETUID], [test "x$enable_caps_over_setuid" = "xyes"]) + +AS_IF([test "x$enable_caps_over_setuid" = "xyes"], [ + AC_DEFINE([CAPS_OVER_SETUID], [1], + [Use capabilities rather than setuid bit])]) + AC_CONFIG_FILES([Makefile src/Makefile tests/Makefile docs/Makefile]) AC_OUTPUT diff -Nru snap-confine-1.0.38/debian/changelog snap-confine-1.0.41/debian/changelog --- snap-confine-1.0.38/debian/changelog 2016-08-24 19:37:52.000000000 +0000 +++ snap-confine-1.0.41/debian/changelog 2016-09-21 01:01:59.000000000 +0000 @@ -1,91 +1,93 @@ -snap-confine (1.0.38-0ubuntu0.16.04.10) xenial; urgency=medium - - * debian/usr.lib.snapd.snap-confine: - - synchronize apparmor profile with upstream 1.0.40 release. - (LP: #1597842, LP: #1615113, LP: #1584456) - - -- Zygmunt Krynicki Wed, 24 Aug 2016 20:31:12 +0200 - -snap-confine (1.0.38-0ubuntu0.16.04.9) xenial; urgency=medium - - * debian/patches/04_not_die_unknown_locations.patch: - - move to /var/lib/snapd/void (with mode 0) if the current - location cannot be preserved (LP: #1612684) - - -- Michael Vogt Tue, 16 Aug 2016 15:44:39 +0200 - -snap-confine (1.0.38-0ubuntu0.16.04.8) xenial; urgency=medium - - * debian/patches/04_not_die_unknown_locations.patch: - - move to /tmp if the current location can not be preserved - (LP: #1612684) - - -- Michael Vogt Fri, 12 Aug 2016 16:45:17 +0200 - -snap-confine (1.0.38-0ubuntu0.16.04.7) xenial; urgency=medium - - * fix apparmor rules when a snap is run on new-style encrypted - home with sudo (LP: #1612291) - - -- Michael Vogt Fri, 12 Aug 2016 11:04:13 +0200 - -snap-confine (1.0.38-0ubuntu0.16.04.6) xenial; urgency=medium - - * fix apparmor rules when a snap is run on encrypted home - with sudo (LP: #1612291) - - -- Michael Vogt Thu, 11 Aug 2016 17:26:21 +0200 - -snap-confine (1.0.38-0ubuntu0.16.04.5) xenial; urgency=medium - - * 03_fix_snap_user_data_regression.patch: - - fix regression in autopkgtest with snap-confine when the - SNAP_USER_DATA directory is not created for services - (LP: #1612120) - - -- Michael Vogt Thu, 11 Aug 2016 12:39:25 +0200 - -snap-confine (1.0.38-0ubuntu0.16.04.4) xenial; urgency=medium - - * fix regression in autopkgtests snapd test for root run - X11 applications - - -- Michael Vogt Sun, 31 Jul 2016 17:13:43 +0200 - -snap-confine (1.0.38-0ubuntu0.16.04.3) xenial; urgency=medium +snap-confine (1.0.41-0ubuntu2~16.04.1) xenial; urgency=medium + * Build for Xenial. Fixes bugs: + - Allow access to the currently running kernel sources from /usr/src + (LP: #1597842) + - snap-confine regression when running commands as root (LP: #1607796) + - Juju snap can no longer interact with LXD in devmode (LP: #1613845) + - snap-confine prevented from mounting base directory through the "content" + interface (LP: #1615113) + - apparmor denial using ptmx char device (LP: #1584456) + - snap-confine: dpkg --compare-versions error outputs during installation + from snapd/ubuntu-core-launcher upgrade (LP: #1605052) + - dies when run in a place that is not inside the snap chroot (LP: #1612684) + - Usage of secure_getenv prevents build against musl libc (LP: #1623725) + - Add support for capability-based permissions (LP: #1615610) + - /dev/pts/# denial when running snap-confine under sshd configured for + pam-apparmor (LP: #1621624) + - Make /snap a build-time configuration option (LP: #1616872) + - gcc -Wdeprecated fails with: readdir_r is deprecated (LP: #1615615) + - snap-confine doesn't work with new snap-run/snap-exec flow (LP: #1621127) + - pivot_root or mounts setup breaks unshare of userns (LP: #1618683) + - ubuntu-core-launcher nvidia driver detection is bogus (LP: #1615248) + - Cannot share a namespaces created with 'ip netns' between apps in a + devmode SNAP (LP: #1611444) + + -- Michael Hudson-Doyle Wed, 21 Sep 2016 12:32:00 +1200 + +snap-confine (1.0.41-0ubuntu2) yakkety; urgency=medium + + * add skip-nsfs-magic-tests-on-old-kernels.patch to disable NSFS tests on + kernels older than 3.19 (LP: #1625565) + + -- Jamie Strandboge Tue, 20 Sep 2016 10:58:54 -0500 + +snap-confine (1.0.41-0ubuntu1) yakkety; urgency=medium + + * New upstream release, full list of issues is available at + https://launchpad.net/snap-confine/+milestone/1.0.41 + * Drop all patches (included upstream). + * Add version to apparmor run-time dependency. + + -- Michael Hudson-Doyle Tue, 20 Sep 2016 20:45:24 +1200 + +snap-confine (1.0.40-1) unstable; urgency=medium + + * New upstream release, full list of issues is available at + https://launchpad.net/snap-confine/+milestone/1.0.40 + * Drop apparmor profile from the debian/ directory and install it straight + from upstream package. This is now automatically consistent with package + configuration prefix. + * Drop patch: prctl-compatibility.patch(applied upstream) + * Add directory /var/lib/snapd/void to snap-confine + * Add patch: 0001-Don-t-shellcheck-files-spread-prepare-script.patch that + fixes make check due to a mistake upstream. + * Add patch: 0001-Stop-using-deprecated-readdir_r.patch (LP: #1615615) + + -- Zygmunt Krynicki Tue, 23 Aug 2016 10:53:16 +0200 + +snap-confine (1.0.39-1) unstable; urgency=medium + + * New upstream release. + * Remove d/patches/01_lp1606277.patch, applied upstream. + + -- Michael Hudson-Doyle Tue, 16 Aug 2016 14:54:46 +1200 + +snap-confine (1.0.38-3) unstable; urgency=medium + + * debian/patches/prctl-compatibility.patch: add shadow definitions for + compatibility with older kernel headers. + * drop build-dependency on shellcheck, which is not used at build time + and doesn't exist in trusty. + * make ubuntu-core-launcher "arch:any" to workaround an issue in + rm_conffile which does not deal with changing architectures * fix log-observer interface regression (LP: #1606277) - -- Michael Vogt Wed, 27 Jul 2016 14:17:11 +0200 - -snap-confine (1.0.38-0ubuntu0.16.04.2) xenial; urgency=medium - - * debian/*.maintscript: - - do not include "--" (LP: #1605052) - * debian/control: - - make ubuntu-core-launcher "arch:any" to workaround an issue in - rm_conffile which does not deal with changing architectures - * debian/ubuntu-core-launcher.maintscript: - - update version to match previous xenial-proposed upload - * debian/usr.lib.snapd.snap-confine: - - update to the latest upstream version to ensure content-sharing - fully works - - -- Michael Vogt Thu, 21 Jul 2016 11:51:18 +0200 + -- Steve Langasek Thu, 28 Jul 2016 21:00:38 +0000 -snap-confine (1.0.38-0ubuntu0.16.04.1) xenial; urgency=medium +snap-confine (1.0.38-2) unstable; urgency=medium - * New upstream release: - - uploaded to xenial (16.04): LP: #1593396 + * Fix invocations of rm_conffile. + * Update d/usr.lib.snapd.snap-confine to the latest upstream version to + ensure content-sharing fully works. - -- Michael Vogt Fri, 15 Jul 2016 16:07:07 +0200 + -- Michael Hudson-Doyle Fri, 22 Jul 2016 12:09:51 +1200 -snap-confine (1.0.37-0ubuntu1) yakkety; urgency=medium +snap-confine (1.0.38-1) unstable; urgency=medium - * New upstream release - - uploaded to xenial (16.04): LP: #1593396 + * New upstream release. - -- Michael Vogt Fri, 15 Jul 2016 14:57:11 +0200 + -- Michael Hudson-Doyle Wed, 20 Jul 2016 21:10:58 +1200 snap-confine (1.0.36-1) unstable; urgency=medium diff -Nru snap-confine-1.0.38/debian/control snap-confine-1.0.41/debian/control --- snap-confine-1.0.38/debian/control 2016-07-21 09:21:31.000000000 +0000 +++ snap-confine-1.0.41/debian/control 2016-09-21 00:30:38.000000000 +0000 @@ -1,8 +1,10 @@ Source: snap-confine Section: utils Priority: optional -Maintainer: Steve Langasek -Uploaders: Michael Hudson-Doyle +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Steve Langasek +Uploaders: Michael Hudson-Doyle , + Zygmunt Krynicki Build-Depends: autoconf, automake, autotools-dev, @@ -16,7 +18,6 @@ libudev-dev, pkg-config, python3-docutils, - shellcheck, udev Standards-Version: 3.9.8 Vcs-Git: git://anonscm.debian.org/collab-maint/snap-confine.git -b debian @@ -26,7 +27,7 @@ Architecture: any Breaks: ubuntu-core-launcher (<< 1.0.32) Replaces: ubuntu-core-launcher (<< 1.0.32) -Depends: apparmor, ${misc:Depends}, ${shlibs:Depends} +Depends: apparmor (>= 2.10.95-0ubuntu2.2), ${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 diff -Nru snap-confine-1.0.38/debian/patches/01_lp1606277.patch snap-confine-1.0.41/debian/patches/01_lp1606277.patch --- snap-confine-1.0.38/debian/patches/01_lp1606277.patch 2016-07-27 12:20:25.000000000 +0000 +++ snap-confine-1.0.41/debian/patches/01_lp1606277.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -Description: cherry pick snap-confine patch -Author: Zygmunt Krynicki -Bug-Ubuntu: https://bugs.launchpad.net/bugs/1606277 - ---- -Origin: upstream -Bug-Ubuntu: https://bugs.launchpad.net/bugs/1606277 - ---- /dev/null -+++ snap-confine-1.0.38/spread-tests/regression/lp-1606277/task.yaml -@@ -0,0 +1,17 @@ -+summary: Regression check for https://bugs.launchpad.net/snap-confine/+bug/1606277 -+# This is blacklisted on debian because debian doesn't use apparmor yet -+systems: [-debian-8] -+details: | -+ A missing bind mount for /var/log prevents access to system log files -+ even if the log-observe interface is being used. -+prepare: | -+ echo "Having installed the snapd-hacker-toolbelt snap" -+ snap install snapd-hacker-toolbelt -+ echo "And having connected the log-observe interface" -+ snap connect snapd-hacker-toolbelt:log-observe ubuntu-core:log-observe -+execute: | -+ echo "We can now see a non-empty /var/log directory" -+ cd / -+ [ "$(/snap/bin/snapd-hacker-toolbelt.busybox ls /var/log | wc -l)" != 0 ] -+restore: | -+ snap remove snapd-hacker-toolbelt ---- snap-confine-1.0.38.orig/src/mount-support.c -+++ snap-confine-1.0.38/src/mount-support.c -@@ -204,6 +204,7 @@ void setup_snappy_os_mounts() - "/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 -+ "/var/log", // to get access to log files via log-observe interface - "/run", // to get /run with sockets and what not - "/media", // access to the users removable devices - "/lib/modules", // access to the modules of the running kernel diff -Nru snap-confine-1.0.38/debian/patches/02_fix_root_mount_regression.patch snap-confine-1.0.41/debian/patches/02_fix_root_mount_regression.patch --- snap-confine-1.0.38/debian/patches/02_fix_root_mount_regression.patch 2016-07-31 15:20:55.000000000 +0000 +++ snap-confine-1.0.41/debian/patches/02_fix_root_mount_regression.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -commit ffcb79268af3cffdb7592eb352cc5b7c9281534e -Author: Zygmunt Krynicki -Date: Fri Jul 29 19:18:27 2016 +0200 - - Bind mount /root on classic - - Signed-off-by: Zygmunt Krynicki - -Index: snap-confine-1.0.38/src/mount-support.c -=================================================================== ---- snap-confine-1.0.38.orig/src/mount-support.c -+++ snap-confine-1.0.38/src/mount-support.c -@@ -197,6 +197,7 @@ void setup_snappy_os_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 -+ "/root", // because that is $HOME for services - "/proc", // fundamental filesystem - "/snap", // to get access to all the snaps - "/sys", // fundamental filesystem diff -Nru snap-confine-1.0.38/debian/patches/03_fix_snap_user_data_regression.patch snap-confine-1.0.41/debian/patches/03_fix_snap_user_data_regression.patch --- snap-confine-1.0.38/debian/patches/03_fix_snap_user_data_regression.patch 2016-08-16 13:59:19.000000000 +0000 +++ snap-confine-1.0.41/debian/patches/03_fix_snap_user_data_regression.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,200 +0,0 @@ -From 5a5f6ef7333b337f80aaa36cf43b8e0c31b3a322 Mon Sep 17 00:00:00 2001 -From: Zygmunt Krynicki -Date: Wed, 10 Aug 2016 14:05:36 +0200 -Subject: [PATCH 1/5] Revert "Remove support for creating user data directory" - -This reverts commit ef8e286076e21d0f9c5073b5c2023f716998a9bf. ---- - src/Makefile.am | 4 +- - src/sc-main.c | 5 ++- - src/user-support.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - src/user-support.h | 23 +++++++++++ - 4 files changed, 140 insertions(+), 2 deletions(-) - create mode 100644 src/user-support.c - create mode 100644 src/user-support.h - -diff --git a/src/Makefile.am b/src/Makefile.am -index ccc306c..bf8153e 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -17,7 +17,9 @@ snap_confine_SOURCES = \ - cleanup-funcs.c \ - cleanup-funcs.h \ - udev-support.c \ -- udev-support.h -+ udev-support.h \ -+ user-support.c \ -+ user-support.h - - snap_confine_CFLAGS = -Wall -Werror $(AM_CFLAGS) - snap_confine_LDFLAGS = $(AM_LDFLAGS) -diff --git a/src/sc-main.c b/src/sc-main.c -index 4adb45d..6620adf 100644 ---- a/src/sc-main.c -+++ b/src/sc-main.c -@@ -35,6 +35,7 @@ - #endif // ifdef HAVE_SECCOMP - #include "udev-support.h" - #include "cleanup-funcs.h" -+#include "user-support.h" - - int sc_main(int argc, char **argv) - { -@@ -134,8 +135,10 @@ int sc_main(int argc, char **argv) - if (real_uid != 0 && getegid() == 0) - die("dropping privs did not work"); - } -- // https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement -+ // Ensure that the user data path exists. -+ setup_user_data(); - -+ // https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement - #ifdef HAVE_APPARMOR - int rc = 0; - // set apparmor rules -diff --git a/src/user-support.c b/src/user-support.c -new file mode 100644 -index 0000000..d4a69b4 ---- /dev/null -+++ b/src/user-support.c -@@ -0,0 +1,110 @@ -+/* -+ * 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 . -+ * -+ */ -+#include "config.h" -+#include "user-support.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "utils.h" -+ -+static void mkpath(const char *const path) -+{ -+ // If asked to create an empty path, return immediately. -+ if (strlen(path) == 0) { -+ return; -+ } -+ // We're going to use strtok_r, which needs to modify the path, so -+ // we'll make a copy of it. -+ char *path_copy = strdup(path); -+ if (path_copy == NULL) { -+ die("failed to create user data directory"); -+ } -+ // Open flags to use while we walk the user data path: -+ // - Don't follow symlinks -+ // - Don't allow child access to file descriptor -+ // - Only open a directory (fail otherwise) -+ int open_flags = O_NOFOLLOW | O_CLOEXEC | O_DIRECTORY; -+ -+ // We're going to create each path segment via openat/mkdirat calls -+ // instead of mkdir calls, to avoid following symlinks and placing the -+ // user data directory somewhere we never intended for it to go. The -+ // first step is to get an initial file descriptor. -+ int fd = AT_FDCWD; -+ if (path_copy[0] == '/') { -+ fd = open("/", open_flags); -+ if (fd < 0) { -+ free(path_copy); -+ die("failed to create user data directory"); -+ } -+ } -+ // strtok_r needs a pointer to keep track of where it is in the string. -+ char *path_walker; -+ -+ // Initialize tokenizer and obtain first path segment. -+ char *path_segment = strtok_r(path_copy, "/", &path_walker); -+ while (path_segment) { -+ // Try to create the directory. It's okay if it already -+ // existed, but any other error is fatal. -+ if (mkdirat(fd, path_segment, 0755) < 0 && errno != EEXIST) { -+ close(fd); // we die regardless of return code -+ free(path_copy); -+ die("failed to create user data directory"); -+ } -+ // Open the parent directory we just made (and close the -+ // previous one) so we can continue down the path. -+ int previous_fd = fd; -+ fd = openat(fd, path_segment, open_flags); -+ if (close(previous_fd) != 0) { -+ free(path_copy); -+ die("could not close path segment"); -+ } -+ if (fd < 0) { -+ free(path_copy); -+ die("failed to create user data directory"); -+ } -+ // Obtain the next path segment. -+ path_segment = strtok_r(NULL, "/", &path_walker); -+ } -+ -+ // Close the descriptor for the final directory in the path. -+ if (close(fd) != 0) { -+ free(path_copy); -+ die("could not close final directory"); -+ } -+ -+ free(path_copy); -+} -+ -+void setup_user_data() -+{ -+ const char *user_data = getenv("SNAP_USER_DATA"); -+ -+ if (user_data == NULL) -+ return; -+ // Only support absolute paths. -+ if (user_data[0] != '/') { -+ die("user data directory must be an absolute path"); -+ } -+ -+ mkpath(user_data); -+} -diff --git a/src/user-support.h b/src/user-support.h -new file mode 100644 -index 0000000..dc2fafb ---- /dev/null -+++ b/src/user-support.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 . -+ * -+ */ -+ -+#ifndef SNAP_CONFINE_USER_SUPPORT_H -+#define SNAP_CONFINE_USER_SUPPORT_H -+ -+void setup_user_data(); -+ -+#endif - diff -Nru snap-confine-1.0.38/debian/patches/04_not_die_unknown_locations.patch snap-confine-1.0.41/debian/patches/04_not_die_unknown_locations.patch --- snap-confine-1.0.38/debian/patches/04_not_die_unknown_locations.patch 2016-08-16 13:57:09.000000000 +0000 +++ snap-confine-1.0.41/debian/patches/04_not_die_unknown_locations.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -1diff --git a/src/sc-main.c b/src/sc-main.c -index 6620adf..59d04d4 100644 -Index: snap-confine-1.0.38/src/sc-main.c -=================================================================== ---- snap-confine-1.0.38.orig/src/sc-main.c -+++ snap-confine-1.0.38/src/sc-main.c -@@ -121,7 +121,12 @@ int sc_main(int argc, char **argv) - // Try to re-locate back to vanilla working directory. This can fail - // because that directory is no longer present. - if (chdir(vanilla_cwd) != 0) { -- die("cannot remain in %s, please run this snap from another location", vanilla_cwd); -+ fprintf(stderr, -+ "cannot remain in %s, moved to the void directory\n", -+ vanilla_cwd); -+ if (chdir(SC_VOID_DIR) != 0) { -+ die("cannot chdir to %s", SC_VOID_DIR); -+ } - } - // the rest does not so temporarily drop privs back to calling - // user (we'll permanently drop after loading seccomp) -Index: snap-confine-1.0.38/src/sc-main.h -=================================================================== ---- snap-confine-1.0.38.orig/src/sc-main.h -+++ snap-confine-1.0.38/src/sc-main.h -@@ -18,6 +18,12 @@ - #ifndef SNAP_CONFINE_MAIN - #define SNAP_CONFINE_MAIN - -+/*! The void directory. -+ * Snap confine moves to that directory in case it cannot retain -+ * the current working directory across the pivot_root call. -+ **/ -+#define SC_VOID_DIR "/var/lib/snapd/void" -+ - int sc_main(int argc, char **argv); - - #endif // SNAP_CONFINE_MAIN -Index: snap-confine-1.0.38/src/Makefile.am -=================================================================== ---- snap-confine-1.0.38.orig/src/Makefile.am -+++ snap-confine-1.0.38/src/Makefile.am -@@ -91,10 +91,12 @@ EXTRA_DIST = 80-snappy-assign.rules snap - # http://www.gnu.org/software/automake/manual/automake.html#Hard_002dCoded-Install-Paths - # - # Install udev rules -+# NOTE: The 'void' directory *has to* be chmod 000 - install-data-local: - install -d -m 755 $(DESTDIR)$(shell pkg-config udev --variable=udevdir)/rules.d - install -m 644 $(srcdir)/80-snappy-assign.rules $(DESTDIR)$(shell pkg-config udev --variable=udevdir)/rules.d -- -+ install -d -m 000 $(DESTDIR)/var/lib/snapd/void -+ - # Install support script for udev rules - install-exec-local: - install -d -m 755 $(DESTDIR)$(shell pkg-config udev --variable=udevdir) diff -Nru snap-confine-1.0.38/debian/patches/series snap-confine-1.0.41/debian/patches/series --- snap-confine-1.0.38/debian/patches/series 2016-08-16 13:41:33.000000000 +0000 +++ snap-confine-1.0.41/debian/patches/series 2016-09-20 21:09:05.000000000 +0000 @@ -1,4 +1 @@ -01_lp1606277.patch -02_fix_root_mount_regression.patch -03_fix_snap_user_data_regression.patch -04_not_die_unknown_locations.patch +skip-nsfs-magic-tests-on-old-kernels.patch diff -Nru snap-confine-1.0.38/debian/patches/skip-nsfs-magic-tests-on-old-kernels.patch snap-confine-1.0.41/debian/patches/skip-nsfs-magic-tests-on-old-kernels.patch --- snap-confine-1.0.38/debian/patches/skip-nsfs-magic-tests-on-old-kernels.patch 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/debian/patches/skip-nsfs-magic-tests-on-old-kernels.patch 2016-09-20 21:09:05.000000000 +0000 @@ -0,0 +1,47 @@ +From b30f09f8961ff623995a19e6456f2292b7b6e93c Mon Sep 17 00:00:00 2001 +From: Zygmunt Krynicki +Date: Tue, 20 Sep 2016 13:15:51 +0200 +Subject: [PATCH] Skip tests that require Linux kernel 3.19+ + +The test sanity code that checks if /proc/self/ns/mnt is an NSFS_MAGIC +filesystem is skipped if invoked on a Kernel older than 3.19. This lets +the package build in an older kernel and a newer chroot sensibly (e.g. +in a launchpad builder). + +Signed-off-by: Zygmunt Krynicki + +Index: snap-confine-1.0.41/src/ns-support-test.c +=================================================================== +--- snap-confine-1.0.41.orig/src/ns-support-test.c ++++ snap-confine-1.0.41/src/ns-support-test.c +@@ -22,6 +22,7 @@ + + #include + #include // for NSFS_MAGIC ++#include + #include + + #include +@@ -317,6 +318,22 @@ static void test_sc_initialize_ns_groups + // expect, aka NSFS_MAGIC. + static void test_nsfs_fs_id() + { ++ struct utsname uts; ++ if (uname(&uts) < 0) { ++ g_test_message("cannot use uname(2)"); ++ g_test_fail(); ++ return; ++ } ++ int major, minor; ++ if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) { ++ g_test_message("cannot use sscanf(2) to parse kernel release"); ++ g_test_fail(); ++ return; ++ } ++ if (major < 3 || (major == 3 && minor < 19)) { ++ g_test_skip("this test needs kernel 3.19+"); ++ return; ++ } + struct statfs buf; + int err = statfs("/proc/self/ns/mnt", &buf); + g_assert_cmpint(err, ==, 0); diff -Nru snap-confine-1.0.38/debian/snap-confine.dirs snap-confine-1.0.41/debian/snap-confine.dirs --- snap-confine-1.0.38/debian/snap-confine.dirs 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/debian/snap-confine.dirs 2016-09-20 21:06:16.000000000 +0000 @@ -0,0 +1 @@ +/var/lib/snapd/void diff -Nru snap-confine-1.0.38/debian/snap-confine.install snap-confine-1.0.41/debian/snap-confine.install --- snap-confine-1.0.38/debian/snap-confine.install 2016-08-16 13:44:24.000000000 +0000 +++ snap-confine-1.0.41/debian/snap-confine.install 2016-09-20 21:06:16.000000000 +0000 @@ -1,4 +1,3 @@ -debian/usr.lib.snapd.snap-confine etc/apparmor.d +etc/apparmor.d/*.snap-confine lib/* usr/lib/snapd/* -var/lib/snapd/void \ No newline at end of file diff -Nru snap-confine-1.0.38/debian/ubuntu-core-launcher.maintscript snap-confine-1.0.41/debian/ubuntu-core-launcher.maintscript --- snap-confine-1.0.38/debian/ubuntu-core-launcher.maintscript 2016-07-21 09:37:18.000000000 +0000 +++ snap-confine-1.0.41/debian/ubuntu-core-launcher.maintscript 2016-09-20 21:06:16.000000000 +0000 @@ -1 +1 @@ -rm_conffile /etc/apparmor.d/usr.bin.ubuntu-core-launcher 1.0.38-0ubuntu0.16.04.2~ +rm_conffile /etc/apparmor.d/usr.bin.ubuntu-core-launcher 1.0.29~ diff -Nru snap-confine-1.0.38/debian/usr.lib.snapd.snap-confine snap-confine-1.0.41/debian/usr.lib.snapd.snap-confine --- snap-confine-1.0.38/debian/usr.lib.snapd.snap-confine 2016-08-24 19:37:24.000000000 +0000 +++ snap-confine-1.0.41/debian/usr.lib.snapd.snap-confine 1970-01-01 00:00:00.000000000 +0000 @@ -1,184 +0,0 @@ -# Author: Jamie Strandboge -#include - -/usr/lib/snapd/snap-confine (attach_disconnected) { - # We run privileged, so be fanatical about what we include and don't use - # any abstractions - /etc/ld.so.cache r, - /lib/@{multiarch}/ld-*.so mr, - # libc, you are funny - /lib/@{multiarch}/libc{,-[0-9]*}.so* mr, - /lib/@{multiarch}/libpthread{,-[0-9]*}.so* mr, - /lib/@{multiarch}/librt{,-[0-9]*}.so* mr, - /lib/@{multiarch}/libgcc_s.so* mr, - # normal libs in order - /lib/@{multiarch}/libapparmor.so* mr, - /lib/@{multiarch}/libcgmanager.so* mr, - /lib/@{multiarch}/libnih.so* mr, - /lib/@{multiarch}/libnih-dbus.so* mr, - /lib/@{multiarch}/libdbus-1.so* mr, - /lib/@{multiarch}/libudev.so* mr, - /usr/lib/@{multiarch}/libseccomp.so* mr, - /lib/@{multiarch}/libseccomp.so* mr, - - /usr/lib/snapd/snap-confine r, - - /dev/null rw, - /dev/full rw, - /dev/zero rw, - /dev/random r, - /dev/urandom r, - - # cgroups - capability sys_admin, - capability dac_override, - /sys/fs/cgroup/devices/snap{,py}.*/ w, - /sys/fs/cgroup/devices/snap{,py}.*/tasks w, - /sys/fs/cgroup/devices/snap{,py}.*/devices.{allow,deny} w, - - # querying udev - /etc/udev/udev.conf r, - /sys/devices/**/uevent r, - /lib/udev/snappy-app-dev ixr, # drop - /run/udev/** rw, - /{,usr/}bin/tr ixr, - /usr/lib/locale/** r, - /usr/lib/@{multiarch}/gconv/gconv-modules r, - /usr/lib/@{multiarch}/gconv/gconv-modules.cache r, - - # priv dropping - capability setuid, - capability setgid, - - # changing profile - @{PROC}/[0-9]*/attr/exec w, - - # don't allow changing profile to unconfined or profiles that start with - # '/' - change_profile -> [^u/]**, - change_profile -> u[^n]**, - change_profile -> un[^c]**, - change_profile -> unc[^o]**, - change_profile -> unco[^n]**, - change_profile -> uncon[^f]**, - change_profile -> unconf[^i]**, - change_profile -> unconfi[^n]**, - change_profile -> unconfin[^e]**, - change_profile -> unconfine[^d]**, - change_profile -> unconfined?**, - # allow changing to a few not caught above - change_profile -> {u,un,unc,unco,uncon,unconf,unconfi,unconfin,unconfine}, - - # LP: #1446794 - when this bug is fixed, change the above to: - # deny change_profile -> {unconfined,/**}, - # change_profile -> **, - - # reading seccomp filters - /{tmp/snap.rootfs_*/,}var/lib/snapd/seccomp/profiles/* r, - - # reading mount profiles - /{tmp/snap.rootfs_*/,}var/lib/snapd/mount/*.fstab r, - - # set up snap-specific private /tmp dir - capability chown, - /{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 - # Workaround for LP: #1584456 on older kernels that mistakenly think - # /dev/pts/ptmx needs a trailing '/' - mount options=(rw bind) /{tmp/snap.rootfs_*/,}dev/pts/ptmx/ -> /{tmp/snap.rootfs_*/,}dev/ptmx/, - - # for running snaps on classic - mount options=(rw rslave) -> /, - /{tmp/snap.rootfs_*,}snap/ r, - /{tmp/snap.rootfs_*,}snap/** r, - - # mount calls to setup the pivot_root based chroot with the core snap as - # the root filesystem. - 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) /root/ -> /tmp/snap.rootfs_*/root/, - 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/, - mount options=(rw rbind) /run/ -> /tmp/snap.rootfs_*/run/, - mount options=(rw rbind) /media/ -> /tmp/snap.rootfs_*/media/, - mount options=(rw rbind) {/usr,}/lib/modules/ -> /tmp/snap.rootfs_*/lib/modules/, - mount options=(rw rbind) /var/log/ -> /tmp/snap.rootfs_*/var/log/, - mount options=(rw rbind) /usr/src/ -> /tmp/snap.rootfs_*/usr/src/, - mount options=(rw bind) /snap/ubuntu-core/*/etc/alternatives/ -> /tmp/snap.rootfs_*/etc/alternatives/, - - # Allow to mkdir /var/lib/snapd/hostfs - /var/lib/snapd/hostfs/ rw, - # Allow to mount / as hostfs in the chroot - mount options=(ro bind) / -> /tmp/snap.rootfs_*/var/lib/snapd/hostfs/, - - # Support mount profiles via the content interface - mount options=(rw bind) /snap/*/** -> /snap/*/*/**, - mount options=(ro bind) /snap/*/** -> /snap/*/*/**, - # But we don't want anyone to touch /snap/bin - audit deny mount /snap/bin/** -> /**, - audit deny mount /** -> /snap/bin/**, - # Allow the content interface to bind fonts from the host filesystem - mount options=(ro bind) /var/lib/snapd/hostfs/usr/share/fonts/ -> /snap/*/*/**, - - # 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-*/ -> /{tmp/snap.rootfs_*/,}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/ and - # ~/snap// - / r, - @{HOMEDIRS}/ r, - # These should both have 'owner' match but due to LP: #1466234, we can't - # yet - @{HOME}/ r, - @{HOME}/snap/{,*/,*/*/} rw, - - # for creating the user shared memory directories - /{dev,run}/{,shm/} r, - # This should both have 'owner' match but due to LP: #1466234, we can't yet - /{dev,run}/shm/{,*/,*/*/} rw, - - # Workaround https://launchpad.net/bugs/359338 until upstream handles - # stacked filesystems generally. - # encrypted ~/.Private and old-style encrypted $HOME - @{HOME}/.Private/ r, - @{HOME}/.Private/** mrixwlk, - # new-style encrypted $HOME - @{HOMEDIRS}/.ecryptfs/*/.Private/ r, - @{HOMEDIRS}/.ecryptfs/*/.Private/** mrixwlk, - - # Support for the quirk system - /var/ r, - /var/lib/ r, - /var/lib/** rw, - /tmp/ r, - /tmp/snapd.quirks_*/ rw, - mount options=(move) /var/lib/snapd/ -> /tmp/snapd.quirks_*/, - mount fstype=tmpfs options=(rw nodev nosuid) none -> /var/lib/, - mount options=(ro rbind) /snap/ubuntu-core/*/var/lib/** -> /var/lib/**, - umount /var/lib/snapd/, - mount options=(move) /tmp/snapd.quirks_*/ -> /var/lib/snapd/, - - # support for the LXD quirk - mount options=(rw rbind nodev nosuid noexec) /var/lib/snapd/hostfs/var/lib/lxd/ -> /var/lib/lxd/, - /var/lib/lxd/ w, - /var/lib/snapd/hostfs/var/lib/lxd r, -} diff -Nru snap-confine-1.0.38/docs/Makefile.am snap-confine-1.0.41/docs/Makefile.am --- snap-confine-1.0.38/docs/Makefile.am 2016-06-30 11:47:02.000000000 +0000 +++ snap-confine-1.0.41/docs/Makefile.am 2016-09-19 09:41:32.000000000 +0000 @@ -1,9 +1,9 @@ -dist_man_MANS = snap-confine.5 ubuntu-core-launcher.1 +dist_man_MANS = snap-confine.5 snap-discard-ns.5 ubuntu-core-launcher.1 -CLEANFILES = snap-confine.5 ubuntu-core-launcher.1 -EXTRA_DIST = snap-confine.rst ubuntu-core-launcher.rst +CLEANFILES = snap-confine.5 snap-discard-ns.5 ubuntu-core-launcher.1 +EXTRA_DIST = snap-confine.rst snap-discard-ns.rst ubuntu-core-launcher.rst -snap-confine.5: snap-confine.rst +%.5: %.rst rst2man $^ > $@ ubuntu-core-launcher.1: ubuntu-core-launcher.rst diff -Nru snap-confine-1.0.38/docs/Makefile.in snap-confine-1.0.41/docs/Makefile.in --- snap-confine-1.0.38/docs/Makefile.in 2016-07-15 14:01:09.000000000 +0000 +++ snap-confine-1.0.41/docs/Makefile.in 2016-09-19 09:44:58.000000000 +0000 @@ -206,6 +206,7 @@ SECCOMP_LIBS = @SECCOMP_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SNAP_MOUNT_DIR = @SNAP_MOUNT_DIR@ STRIP = @STRIP@ UDEV_CFLAGS = @UDEV_CFLAGS@ UDEV_LIBS = @UDEV_LIBS@ @@ -261,9 +262,9 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -dist_man_MANS = snap-confine.5 ubuntu-core-launcher.1 -CLEANFILES = snap-confine.5 ubuntu-core-launcher.1 -EXTRA_DIST = snap-confine.rst ubuntu-core-launcher.rst +dist_man_MANS = snap-confine.5 snap-discard-ns.5 ubuntu-core-launcher.1 +CLEANFILES = snap-confine.5 snap-discard-ns.5 ubuntu-core-launcher.1 +EXTRA_DIST = snap-confine.rst snap-discard-ns.rst ubuntu-core-launcher.rst all: all-am .SUFFIXES: @@ -542,7 +543,7 @@ .PRECIOUS: Makefile -snap-confine.5: snap-confine.rst +%.5: %.rst rst2man $^ > $@ ubuntu-core-launcher.1: ubuntu-core-launcher.rst diff -Nru snap-confine-1.0.38/docs/snap-confine.5 snap-confine-1.0.41/docs/snap-confine.5 --- snap-confine-1.0.38/docs/snap-confine.5 2016-07-15 14:01:17.000000000 +0000 +++ snap-confine-1.0.41/docs/snap-confine.5 2016-09-19 09:45:04.000000000 +0000 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH SNAP-CONFINE 5 "2016-07-15" "1.0.38" "snappy" +.TH SNAP-CONFINE 5 "2016-09-19" "1.0.41" "snappy" .SH NAME snap-confine \- internal tool for confining snappy applications . @@ -79,6 +79,23 @@ option (e.g. \fIrw\fP can cause the mount point to be writable). .sp As a security precaution only \fIbind\fP mounts are supported at this time. +.SS Quirks +.sp +\fIsnap\-confine\fP contains a quirk system that emulates some or the behavior of +the older versions of snap\-confine that certain snaps (still in devmode but +useful and important) have grown to rely on. This section documents the list of +quirks: +.INDENT 0.0 +.IP \(bu 2 +The /var/lib/lxd directory, if it exists on the host, is made available in +the execution environment. This allows various snaps, while running in +devmode, to access the LXD socket. LP: #1613845 +.UNINDENT +.SS Sharing of the mount namespace +.sp +As of version 1.0.41 all the applications from the same snap will share the +same mount namespace. Applications from different snaps continue to use +separate mount namespaces. .SH ENVIRONMENT .sp \fIsnap\-confine\fP responds to the following environment variables @@ -101,6 +118,13 @@ .TP .B \fISNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR\fP: Internal variable that should not be relied upon. +.TP +.B \fISNAP_USER_DATA\fP: +Full path to the directory like /home/$LOGNAME/snap/$SNAP_NAME/$SNAP_REVISION. +.sp +This directory is created by snap\-confine on startup. This is a temporary +feature that will be merged into snapd\(aqs snap\-run command. The set of directories +that can be created is confined with apparmor. .UNINDENT .SH FILES .sp @@ -120,6 +144,59 @@ .UNINDENT .UNINDENT .sp +\fI/run/snapd/ns/\fP: +.INDENT 0.0 +.INDENT 3.5 +Directory used to keep shared mount namespaces. +.sp +\fIsnap\-confine\fP internally converts this directory to a private bind mount. +Semantically the behavior is identical to the following mount commands: +.sp +mount \-\-bind /run/snapd/ns /run/snapd/ns +mount \-\-make\-private /run/snapd/ns +.UNINDENT +.UNINDENT +.sp +\fI/run/snapd/ns/.lock\fP: +.INDENT 0.0 +.INDENT 3.5 +A \fIflock(2)\fP\-based lock file acquired to create and convert +\fI/run/snapd/ns/\fP to a private bind mount. +.UNINDENT +.UNINDENT +.sp +\fI/run/snapd/ns/$SNAP_NAME.lock\fP: +.INDENT 0.0 +.INDENT 3.5 +A \fIflock(2)\fP\-based lock file acquired to create or join the mount namespace +represented as \fI/run/snaps/ns/$SNAP_NAME.mnt\fP\&. +.UNINDENT +.UNINDENT +.sp +\fI/run/snapd/ns/$SNAP_NAME.mnt\fP: +.INDENT 0.0 +.INDENT 3.5 +This file can be either: +.INDENT 0.0 +.IP \(bu 2 +An empty file that may be seen before the mount namespace is preserved or +when the mount namespace is unmounted. +.IP \(bu 2 +A file belonging to the \fInsfs\fP file system, representing a fully +populated mount namespace of a given snap. The file is bind mounted from +\fI/proc/self/ns/mnt\fP from the first process in any snap. +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fI/proc/self/mountinfo\fP: +.INDENT 0.0 +.INDENT 3.5 +This file is read to decide if \fI/run/snapd/ns/\fP needs to be created and +converted to a private bind mount, as described above. +.UNINDENT +.UNINDENT +.sp Note that the apparmor profile is external to \fIsnap\-confine\fP and is loaded directly into the kernel. The actual apparmor profile is managed by \fIsnapd\fP\&. .SH BUGS diff -Nru snap-confine-1.0.38/docs/snap-confine.rst snap-confine-1.0.41/docs/snap-confine.rst --- snap-confine-1.0.38/docs/snap-confine.rst 2016-07-15 13:59:57.000000000 +0000 +++ snap-confine-1.0.41/docs/snap-confine.rst 2016-09-19 09:41:32.000000000 +0000 @@ -7,9 +7,9 @@ ----------------------------------------------- :Author: zygmunt.krynicki@canonical.com -:Date: 2016-07-15 +:Date: 2016-09-19 :Copyright: Canonical Ltd. -:Version: 1.0.38 +:Version: 1.0.41 :Manual section: 5 :Manual group: snappy @@ -73,6 +73,25 @@ As a security precaution only `bind` mounts are supported at this time. +Quirks +------ + +`snap-confine` contains a quirk system that emulates some or the behavior of +the older versions of snap-confine that certain snaps (still in devmode but +useful and important) have grown to rely on. This section documents the list of +quirks: + +- The /var/lib/lxd directory, if it exists on the host, is made available in + the execution environment. This allows various snaps, while running in + devmode, to access the LXD socket. LP: #1613845 + +Sharing of the mount namespace +------------------------------ + +As of version 1.0.41 all the applications from the same snap will share the +same mount namespace. Applications from different snaps continue to use +separate mount namespaces. + ENVIRONMENT =========== @@ -94,6 +113,13 @@ `SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR`: Internal variable that should not be relied upon. +`SNAP_USER_DATA`: + Full path to the directory like /home/$LOGNAME/snap/$SNAP_NAME/$SNAP_REVISION. + + This directory is created by snap-confine on startup. This is a temporary + feature that will be merged into snapd's snap-run command. The set of directories + that can be created is confined with apparmor. + FILES ===== @@ -107,6 +133,41 @@ Description of the seccomp profile. +`/run/snapd/ns/`: + + Directory used to keep shared mount namespaces. + + `snap-confine` internally converts this directory to a private bind mount. + Semantically the behavior is identical to the following mount commands: + + mount --bind /run/snapd/ns /run/snapd/ns + mount --make-private /run/snapd/ns + +`/run/snapd/ns/.lock`: + + A `flock(2)`-based lock file acquired to create and convert + `/run/snapd/ns/` to a private bind mount. + +`/run/snapd/ns/$SNAP_NAME.lock`: + + A `flock(2)`-based lock file acquired to create or join the mount namespace + represented as `/run/snaps/ns/$SNAP_NAME.mnt`. + +`/run/snapd/ns/$SNAP_NAME.mnt`: + + This file can be either: + + - An empty file that may be seen before the mount namespace is preserved or + when the mount namespace is unmounted. + - A file belonging to the `nsfs` file system, representing a fully + populated mount namespace of a given snap. The file is bind mounted from + `/proc/self/ns/mnt` from the first process in any snap. + +`/proc/self/mountinfo`: + + This file is read to decide if `/run/snapd/ns/` needs to be created and + converted to a private bind mount, as described above. + Note that the apparmor profile is external to `snap-confine` and is loaded directly into the kernel. The actual apparmor profile is managed by `snapd`. diff -Nru snap-confine-1.0.38/docs/snap-discard-ns.5 snap-confine-1.0.41/docs/snap-discard-ns.5 --- snap-confine-1.0.38/docs/snap-discard-ns.5 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/docs/snap-discard-ns.5 2016-09-19 09:45:04.000000000 +0000 @@ -0,0 +1,73 @@ +.\" Man page generated from reStructuredText. +. +.TH SNAP-DISCARD-NS 5 "2016-09-19" "1.0.41" "snappy" +.SH NAME +snap-discard-ns \- internal tool for discarding preserved namespaces of snappy applications +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.INDENT 0.0 +.INDENT 3.5 +snap\-discard\-ns SNAP_NAME +.UNINDENT +.UNINDENT +.SH DESCRIPTION +.sp +The \fIsnap\-discard\-ns\fP is a program used internally by \fIsnapd\fP to discard a preserved +mount namespace of a particular snap. +.SH OPTIONS +.sp +The \fIsnap\-discard\-ns\fP program does not support any options. +.SH ENVIRONMENT +.sp +\fIsnap\-discard\-ns\fP responds to the following environment variables +.INDENT 0.0 +.TP +.B \fISNAP_CONFINE_DEBUG\fP: +When defined the program will print additional diagnostic information about +the actions being performed. All the output goes to stderr. +.UNINDENT +.SH FILES +.sp +\fIsnap\-discard\-ns\fP uses the following files: +.sp +\fI/run/snapd/ns/$SNAP_NAME.mnt\fP: +.INDENT 0.0 +.INDENT 3.5 +The preserved mount namespace that is unmounted by \fIsnap\-discard\-ns\fP\&. +.UNINDENT +.UNINDENT +.SH BUGS +.sp +Please report all bugs with \fI\%https://bugs.launchpad.net/snap\-confine/+filebug\fP +.SH AUTHOR +zygmunt.krynicki@canonical.com +.SH COPYRIGHT +Canonical Ltd. +.\" Generated by docutils manpage writer. +. diff -Nru snap-confine-1.0.38/docs/snap-discard-ns.rst snap-confine-1.0.41/docs/snap-discard-ns.rst --- snap-confine-1.0.38/docs/snap-discard-ns.rst 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/docs/snap-discard-ns.rst 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,53 @@ +================ + snap-discard-ns +================ + +------------------------------------------------------------------------ +internal tool for discarding preserved namespaces of snappy applications +------------------------------------------------------------------------ + +:Author: zygmunt.krynicki@canonical.com +:Date: 2016-09-19 +:Copyright: Canonical Ltd. +:Version: 1.0.41 +:Manual section: 5 +:Manual group: snappy + +SYNOPSIS +======== + + snap-discard-ns SNAP_NAME + +DESCRIPTION +=========== + +The `snap-discard-ns` is a program used internally by `snapd` to discard a preserved +mount namespace of a particular snap. + +OPTIONS +======= + +The `snap-discard-ns` program does not support any options. + +ENVIRONMENT +=========== + +`snap-discard-ns` responds to the following environment variables + +`SNAP_CONFINE_DEBUG`: + When defined the program will print additional diagnostic information about + the actions being performed. All the output goes to stderr. + +FILES +===== + +`snap-discard-ns` uses the following files: + +`/run/snapd/ns/$SNAP_NAME.mnt`: + + The preserved mount namespace that is unmounted by `snap-discard-ns`. + +BUGS +==== + +Please report all bugs with https://bugs.launchpad.net/snap-confine/+filebug diff -Nru snap-confine-1.0.38/docs/ubuntu-core-launcher.1 snap-confine-1.0.41/docs/ubuntu-core-launcher.1 --- snap-confine-1.0.38/docs/ubuntu-core-launcher.1 2016-07-15 14:01:17.000000000 +0000 +++ snap-confine-1.0.41/docs/ubuntu-core-launcher.1 2016-09-19 09:45:05.000000000 +0000 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH UBUNTU-CORE-LAUNCHER 1 "2016-07-15" "1.0.38" "snappy" +.TH UBUNTU-CORE-LAUNCHER 1 "2016-08-22" "1.0.40" "snappy" .SH NAME ubuntu-core-launcher \- internal tool for confining snappy applications . diff -Nru snap-confine-1.0.38/docs/ubuntu-core-launcher.rst snap-confine-1.0.41/docs/ubuntu-core-launcher.rst --- snap-confine-1.0.38/docs/ubuntu-core-launcher.rst 2016-07-15 14:00:00.000000000 +0000 +++ snap-confine-1.0.41/docs/ubuntu-core-launcher.rst 2016-09-19 09:41:13.000000000 +0000 @@ -7,9 +7,9 @@ ----------------------------------------------- :Author: zygmunt.krynicki@canonical.com -:Date: 2016-07-15 +:Date: 2016-08-22 :Copyright: Canonical Ltd. -:Version: 1.0.38 +:Version: 1.0.40 :Manual section: 1 :Manual group: snappy diff -Nru snap-confine-1.0.38/Makefile.am snap-confine-1.0.41/Makefile.am --- snap-confine-1.0.38/Makefile.am 2016-06-30 11:47:02.000000000 +0000 +++ snap-confine-1.0.41/Makefile.am 2016-09-19 09:41:13.000000000 +0000 @@ -1,2 +1,6 @@ SUBDIRS = src tests docs -EXTRA_DIST = PORTING README.md +EXTRA_DIST = PORTING README.md VERSION + +.PHONY: check-syntax +check-syntax: + shellcheck --format=gcc spread-tests/spread-prepare.sh diff -Nru snap-confine-1.0.38/Makefile.in snap-confine-1.0.41/Makefile.in --- snap-confine-1.0.38/Makefile.in 2016-07-15 14:01:09.000000000 +0000 +++ snap-confine-1.0.41/Makefile.in 2016-09-19 09:44:58.000000000 +0000 @@ -158,7 +158,7 @@ CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in COPYING \ - compile config.guess config.sub install-sh missing + compile config.guess config.sub depcomp install-sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -256,6 +256,7 @@ SECCOMP_LIBS = @SECCOMP_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SNAP_MOUNT_DIR = @SNAP_MOUNT_DIR@ STRIP = @STRIP@ UDEV_CFLAGS = @UDEV_CFLAGS@ UDEV_LIBS = @UDEV_LIBS@ @@ -312,7 +313,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src tests docs -EXTRA_DIST = PORTING README.md +EXTRA_DIST = PORTING README.md VERSION all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -785,6 +786,10 @@ .PRECIOUS: Makefile +.PHONY: check-syntax +check-syntax: + shellcheck --format=gcc spread-tests/spread-prepare.sh + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff -Nru snap-confine-1.0.38/src/classic.c snap-confine-1.0.41/src/classic.c --- snap-confine-1.0.38/src/classic.c 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/classic.c 2016-09-09 11:11:21.000000000 +0000 @@ -10,5 +10,6 @@ || access("/var/lib/dpkg/status", F_OK) == 0 || access("/var/lib/pacman", F_OK) == 0 || access("/var/lib/portage", F_OK) == 0 - || access("/var/lib/rpm", F_OK) == 0; + || access("/var/lib/rpm", F_OK) == 0 + || access("/sbin/procd", F_OK) == 0; } diff -Nru snap-confine-1.0.38/src/cleanup-funcs.c snap-confine-1.0.41/src/cleanup-funcs.c --- snap-confine-1.0.38/src/cleanup-funcs.c 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/cleanup-funcs.c 2016-09-19 09:41:32.000000000 +0000 @@ -18,6 +18,7 @@ #include "cleanup-funcs.h" #include +#include void sc_cleanup_string(char **ptr) { @@ -42,3 +43,15 @@ seccomp_release(*ptr); } #endif // HAVE_SECCOMP + +void sc_cleanup_closedir(DIR ** ptr) +{ + if (*ptr != NULL) { + closedir(*ptr); + } +} + +void sc_cleanup_close(int *ptr) +{ + close(*ptr); +} diff -Nru snap-confine-1.0.38/src/cleanup-funcs.h snap-confine-1.0.41/src/cleanup-funcs.h --- snap-confine-1.0.38/src/cleanup-funcs.h 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/cleanup-funcs.h 2016-09-19 09:41:32.000000000 +0000 @@ -27,6 +27,8 @@ #ifdef HAVE_SECCOMP #include #endif // HAVE_SECCOMP +#include +#include /** * Free a dynamically allocated string. @@ -62,4 +64,20 @@ void sc_cleanup_seccomp_release(scmp_filter_ctx * ptr); #endif // HAVE_SECCOMP +/** + * Close an open directory with closedir(3) + * + * This function is designed to be used with + * __attribute__((cleanup(sc_cleanup_closedir))). + **/ +void sc_cleanup_closedir(DIR ** ptr); + +/** + * Close an open file descriptor with close(2) + * + * This function is designed to be used with + * __attribute__((cleanup(sc_cleanup_close))). + **/ +void sc_cleanup_close(int *ptr); + #endif diff -Nru snap-confine-1.0.38/src/cleanup-funcs-test.c snap-confine-1.0.41/src/cleanup-funcs-test.c --- snap-confine-1.0.38/src/cleanup-funcs-test.c 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/cleanup-funcs-test.c 2016-09-19 09:41:32.000000000 +0000 @@ -17,3 +17,25 @@ #include "cleanup-funcs.h" #include "cleanup-funcs.c" + +#include + +// Test that cleanup functions are applied as expected +static void test_cleanup_sanity() +{ + int called = 0; + void fn(int *ptr) { + called = 1; + } + { + int test __attribute__ ((cleanup(fn))); + test = 0; + test++; + } + g_assert_cmpint(called, ==, 1); +} + +static void __attribute__ ((constructor)) init() +{ + g_test_add_func("/cleanup/sanity", test_cleanup_sanity); +} diff -Nru snap-confine-1.0.38/src/Makefile.am snap-confine-1.0.41/src/Makefile.am --- snap-confine-1.0.38/src/Makefile.am 2016-07-01 12:11:15.000000000 +0000 +++ snap-confine-1.0.41/src/Makefile.am 2016-09-19 09:41:32.000000000 +0000 @@ -1,11 +1,41 @@ -libexec_PROGRAMS = snap-confine +libexec_PROGRAMS = snap-confine snap-discard-ns +if WITH_UNIT_TESTS noinst_PROGRAMS = snap-confine-unit-tests +endif + +snap_discard_ns_SOURCES = \ + ns-support.c \ + ns-support.h \ + user-support.c \ + user-support.h \ + utils.c \ + utils.h \ + secure-getenv.c \ + secure-getenv.h \ + cleanup-funcs.c \ + cleanup-funcs.h \ + mountinfo.c \ + mountinfo.h \ + snap-discard-ns.c +snap_discard_ns_CFLAGS = -Wall -Werror $(AM_CFLAGS) +snap_discard_ns_LDFLAGS = $(AM_LDFLAGS) +snap_discard_ns_LDADD = +snap_discard_ns_CFLAGS += $(SECCOMP_CFLAGS) +snap_discard_ns_LDADD += $(SECCOMP_LIBS) + +if APPARMOR +snap_discard_ns_CFLAGS += $(APPARMOR_CFLAGS) +snap_discard_ns_LDADD += $(APPARMOR_LIBS) +endif + snap_confine_SOURCES = \ main.c \ sc-main.c \ sc-main.h \ utils.c \ utils.h \ + secure-getenv.c \ + secure-getenv.h \ snap.c \ snap.h \ classic.c \ @@ -17,7 +47,15 @@ cleanup-funcs.c \ cleanup-funcs.h \ udev-support.c \ - udev-support.h + udev-support.h \ + user-support.c \ + user-support.h \ + quirks.c \ + quirks.h \ + mountinfo.c \ + mountinfo.h \ + ns-support.c \ + ns-support.h snap_confine_CFLAGS = -Wall -Werror $(AM_CFLAGS) snap_confine_LDFLAGS = $(AM_LDFLAGS) @@ -43,17 +81,27 @@ snap_confine_LDADD += $(APPARMOR_LIBS) endif +if WITH_UNIT_TESTS snap_confine_unit_tests_SOURCES = \ unit-tests-main.c \ + classic.c \ + classic.h \ + user-support.c \ + user-support.h \ + quirks.c \ + quirks.h \ unit-tests.c \ unit-tests.h \ utils-test.c \ cleanup-funcs-test.c \ mount-support-test.c \ - verify-executable-name-test.c + verify-executable-name-test.c \ + mountinfo-test.c \ + ns-support-test.c snap_confine_unit_tests_CFLAGS = $(snap_confine_CFLAGS) $(GLIB_CFLAGS) snap_confine_unit_tests_LDADD = $(snap_confine_LDADD) $(GLIB_LIBS) snap_confine_unit_tests_LDFLAGS = $(snap_confine_LDFLAGS) +endif # Force particular coding style on all source and header files. .PHONY: check-syntax @@ -69,7 +117,9 @@ .PHONY: check-unit-tests check-unit-tests: snap-confine-unit-tests +if WITH_UNIT_TESTS ./snap-confine-unit-tests +endif # Run check-syntax when checking @@ -78,28 +128,52 @@ .PHONY: fmt fmt: - for f in $(wildcard *.c) $(wildcard *.h); do \ + for f in $(wildcard $(srcdir)/*.c) $(wildcard $(srcdir)/*.h); do \ echo "Formatting $$f ... "; \ indent -linux "$$f"; \ done; -EXTRA_DIST = 80-snappy-assign.rules snappy-app-dev +EXTRA_DIST = 80-snappy-assign.rules snappy-app-dev snap-confine.apparmor.in + +snap-confine.apparmor: snap-confine.apparmor.in Makefile + sed -e 's,[@]LIBEXECDIR[@],$(libexecdir),g' -e 's,[@]SNAP_MOUNT_DIR[@],$(SNAP_MOUNT_DIR),' <$< >$@ # NOTE: This makes distcheck fail but it is required for udev, so go figure. # http://www.gnu.org/software/automake/manual/automake.html#Hard_002dCoded-Install-Paths # -# Install udev rules -install-data-local: +# Install udev rules and the apparmor profile +# +# NOTE: the funky make functions here just convert /foo/bar/froz into foo.bar.froz +# The inner subst replaces slashes with dots and the outer patsubst strips the leading dot +# +# NOTE: The 'void' directory *has to* be chmod 000 +install-data-local: snap-confine.apparmor install -d -m 755 $(DESTDIR)$(shell pkg-config udev --variable=udevdir)/rules.d install -m 644 $(srcdir)/80-snappy-assign.rules $(DESTDIR)$(shell pkg-config udev --variable=udevdir)/rules.d + install -d -m 755 $(DESTDIR)/etc/apparmor.d/ + install -m 644 snap-confine.apparmor $(DESTDIR)/etc/apparmor.d/$(patsubst .%,%,$(subst /,.,$(libexecdir))).snap-confine + install -d -m 000 $(DESTDIR)/var/lib/snapd/void # Install support script for udev rules install-exec-local: install -d -m 755 $(DESTDIR)$(shell pkg-config udev --variable=udevdir) install -m 755 $(srcdir)/snappy-app-dev $(DESTDIR)$(shell pkg-config udev --variable=udevdir) -# Ensure that snap-confine is +s (setuid) install-exec-hook: +if CAPS_OVER_SETUID +# Ensure that snap-confine has CAP_SYS_ADMIN capabilitiy + setcap cap_sys_admin=pe $(DESTDIR)$(libexecdir)/snap-confine +else +# Ensure that snap-confine is +s (setuid) chmod 4755 $(DESTDIR)$(libexecdir)/snap-confine +endif install -d -m 755 $(DESTDIR)$(bindir) ln -sf $(libexecdir)/snap-confine $(DESTDIR)$(bindir)/ubuntu-core-launcher + +# The hack target helps devlopers work on snap-confine on their live system by +# installing a fresh copy of snap confine and the appropriate apparmor profile. +.PHONY: hack +hack: snap-confine snap-confine.apparmor + sudo install -D -m 4755 snap-confine $(DESTDIR)$(libexecdir)/snap-confine + sudo install -m 644 snap-confine.apparmor $(DESTDIR)/etc/apparmor.d/$(patsubst .%,%,$(subst /,.,$(libexecdir))).snap-confine + sudo apparmor_parser -r snap-confine.apparmor diff -Nru snap-confine-1.0.38/src/Makefile.in snap-confine-1.0.41/src/Makefile.in --- snap-confine-1.0.38/src/Makefile.in 2016-07-15 14:01:09.000000000 +0000 +++ snap-confine-1.0.41/src/Makefile.in 2016-09-19 09:44:58.000000000 +0000 @@ -88,16 +88,19 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -libexec_PROGRAMS = snap-confine$(EXEEXT) -noinst_PROGRAMS = snap-confine-unit-tests$(EXEEXT) -@SECCOMP_TRUE@am__append_1 = \ +libexec_PROGRAMS = snap-confine$(EXEEXT) snap-discard-ns$(EXEEXT) +@WITH_UNIT_TESTS_TRUE@noinst_PROGRAMS = \ +@WITH_UNIT_TESTS_TRUE@ snap-confine-unit-tests$(EXEEXT) +@APPARMOR_TRUE@am__append_1 = $(APPARMOR_CFLAGS) +@APPARMOR_TRUE@am__append_2 = $(APPARMOR_LIBS) +@SECCOMP_TRUE@am__append_3 = \ @SECCOMP_TRUE@ seccomp-support.c \ @SECCOMP_TRUE@ seccomp-support.h -@SECCOMP_TRUE@am__append_2 = $(SECCOMP_CFLAGS) -@SECCOMP_TRUE@am__append_3 = $(SECCOMP_LIBS) -@APPARMOR_TRUE@am__append_4 = $(APPARMOR_CFLAGS) -@APPARMOR_TRUE@am__append_5 = $(APPARMOR_LIBS) +@SECCOMP_TRUE@am__append_4 = $(SECCOMP_CFLAGS) +@SECCOMP_TRUE@am__append_5 = $(SECCOMP_LIBS) +@APPARMOR_TRUE@am__append_6 = $(APPARMOR_CFLAGS) +@APPARMOR_TRUE@am__append_7 = $(APPARMOR_LIBS) subdir = src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac @@ -111,18 +114,24 @@ am__installdirs = "$(DESTDIR)$(libexecdir)" PROGRAMS = $(libexec_PROGRAMS) $(noinst_PROGRAMS) am__snap_confine_SOURCES_DIST = main.c sc-main.c sc-main.h utils.c \ - utils.h snap.c snap.h classic.c classic.h mount-support.c \ - mount-support.h mount-support-nvidia.c mount-support-nvidia.h \ - cleanup-funcs.c cleanup-funcs.h udev-support.c udev-support.h \ - seccomp-support.c seccomp-support.h + utils.h secure-getenv.c secure-getenv.h snap.c snap.h \ + classic.c classic.h mount-support.c mount-support.h \ + mount-support-nvidia.c mount-support-nvidia.h cleanup-funcs.c \ + cleanup-funcs.h udev-support.c udev-support.h user-support.c \ + user-support.h quirks.c quirks.h mountinfo.c mountinfo.h \ + ns-support.c ns-support.h seccomp-support.c seccomp-support.h @SECCOMP_TRUE@am__objects_1 = snap_confine-seccomp-support.$(OBJEXT) am_snap_confine_OBJECTS = snap_confine-main.$(OBJEXT) \ snap_confine-sc-main.$(OBJEXT) snap_confine-utils.$(OBJEXT) \ + snap_confine-secure-getenv.$(OBJEXT) \ snap_confine-snap.$(OBJEXT) snap_confine-classic.$(OBJEXT) \ snap_confine-mount-support.$(OBJEXT) \ snap_confine-mount-support-nvidia.$(OBJEXT) \ snap_confine-cleanup-funcs.$(OBJEXT) \ - snap_confine-udev-support.$(OBJEXT) $(am__objects_1) + snap_confine-udev-support.$(OBJEXT) \ + snap_confine-user-support.$(OBJEXT) \ + snap_confine-quirks.$(OBJEXT) snap_confine-mountinfo.$(OBJEXT) \ + snap_confine-ns-support.$(OBJEXT) $(am__objects_1) snap_confine_OBJECTS = $(am_snap_confine_OBJECTS) am__DEPENDENCIES_1 = @SECCOMP_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) @@ -131,22 +140,44 @@ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3) snap_confine_LINK = $(CCLD) $(snap_confine_CFLAGS) $(CFLAGS) \ $(snap_confine_LDFLAGS) $(LDFLAGS) -o $@ -am_snap_confine_unit_tests_OBJECTS = \ - snap_confine_unit_tests-unit-tests-main.$(OBJEXT) \ - snap_confine_unit_tests-unit-tests.$(OBJEXT) \ - snap_confine_unit_tests-utils-test.$(OBJEXT) \ - snap_confine_unit_tests-cleanup-funcs-test.$(OBJEXT) \ - snap_confine_unit_tests-mount-support-test.$(OBJEXT) \ - snap_confine_unit_tests-verify-executable-name-test.$(OBJEXT) +am__snap_confine_unit_tests_SOURCES_DIST = unit-tests-main.c classic.c \ + classic.h user-support.c user-support.h quirks.c quirks.h \ + unit-tests.c unit-tests.h utils-test.c cleanup-funcs-test.c \ + mount-support-test.c verify-executable-name-test.c \ + mountinfo-test.c ns-support-test.c +@WITH_UNIT_TESTS_TRUE@am_snap_confine_unit_tests_OBJECTS = snap_confine_unit_tests-unit-tests-main.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-classic.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-user-support.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-quirks.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-unit-tests.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-utils-test.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-cleanup-funcs-test.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-mount-support-test.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-verify-executable-name-test.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-mountinfo-test.$(OBJEXT) \ +@WITH_UNIT_TESTS_TRUE@ snap_confine_unit_tests-ns-support-test.$(OBJEXT) snap_confine_unit_tests_OBJECTS = \ $(am_snap_confine_unit_tests_OBJECTS) am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ $(am__DEPENDENCIES_3) -snap_confine_unit_tests_DEPENDENCIES = $(am__DEPENDENCIES_4) \ - $(am__DEPENDENCIES_1) +@WITH_UNIT_TESTS_TRUE@snap_confine_unit_tests_DEPENDENCIES = \ +@WITH_UNIT_TESTS_TRUE@ $(am__DEPENDENCIES_4) \ +@WITH_UNIT_TESTS_TRUE@ $(am__DEPENDENCIES_1) snap_confine_unit_tests_LINK = $(CCLD) \ $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) \ $(snap_confine_unit_tests_LDFLAGS) $(LDFLAGS) -o $@ +am_snap_discard_ns_OBJECTS = snap_discard_ns-ns-support.$(OBJEXT) \ + snap_discard_ns-user-support.$(OBJEXT) \ + snap_discard_ns-utils.$(OBJEXT) \ + snap_discard_ns-secure-getenv.$(OBJEXT) \ + snap_discard_ns-cleanup-funcs.$(OBJEXT) \ + snap_discard_ns-mountinfo.$(OBJEXT) \ + snap_discard_ns-snap-discard-ns.$(OBJEXT) +snap_discard_ns_OBJECTS = $(am_snap_discard_ns_OBJECTS) +snap_discard_ns_DEPENDENCIES = $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_3) +snap_discard_ns_LINK = $(CCLD) $(snap_discard_ns_CFLAGS) $(CFLAGS) \ + $(snap_discard_ns_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -179,9 +210,11 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(snap_confine_SOURCES) $(snap_confine_unit_tests_SOURCES) +SOURCES = $(snap_confine_SOURCES) $(snap_confine_unit_tests_SOURCES) \ + $(snap_discard_ns_SOURCES) DIST_SOURCES = $(am__snap_confine_SOURCES_DIST) \ - $(snap_confine_unit_tests_SOURCES) + $(am__snap_confine_unit_tests_SOURCES_DIST) \ + $(snap_discard_ns_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -263,6 +296,7 @@ SECCOMP_LIBS = @SECCOMP_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SNAP_MOUNT_DIR = @SNAP_MOUNT_DIR@ STRIP = @STRIP@ UDEV_CFLAGS = @UDEV_CFLAGS@ UDEV_LIBS = @UDEV_LIBS@ @@ -318,31 +352,60 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -snap_confine_SOURCES = main.c sc-main.c sc-main.h utils.c utils.h \ - snap.c snap.h classic.c classic.h mount-support.c \ - mount-support.h mount-support-nvidia.c mount-support-nvidia.h \ - cleanup-funcs.c cleanup-funcs.h udev-support.c udev-support.h \ +snap_discard_ns_SOURCES = \ + ns-support.c \ + ns-support.h \ + user-support.c \ + user-support.h \ + utils.c \ + utils.h \ + secure-getenv.c \ + secure-getenv.h \ + cleanup-funcs.c \ + cleanup-funcs.h \ + mountinfo.c \ + mountinfo.h \ + snap-discard-ns.c + +snap_discard_ns_CFLAGS = -Wall -Werror $(AM_CFLAGS) $(SECCOMP_CFLAGS) \ $(am__append_1) +snap_discard_ns_LDFLAGS = $(AM_LDFLAGS) +snap_discard_ns_LDADD = $(SECCOMP_LIBS) $(am__append_2) +snap_confine_SOURCES = main.c sc-main.c sc-main.h utils.c utils.h \ + secure-getenv.c secure-getenv.h snap.c snap.h classic.c \ + classic.h mount-support.c mount-support.h \ + mount-support-nvidia.c mount-support-nvidia.h cleanup-funcs.c \ + cleanup-funcs.h udev-support.c udev-support.h user-support.c \ + user-support.h quirks.c quirks.h mountinfo.c mountinfo.h \ + ns-support.c ns-support.h $(am__append_3) # This is here to help fix rpmlint hardening issue. # https://en.opensuse.org/openSUSE:Packaging_checks#non-position-independent-executable snap_confine_CFLAGS = -Wall -Werror $(AM_CFLAGS) $(LIBUDEV_CFLAGS) \ - $(SUID_CFLAGS) $(am__append_2) $(am__append_4) + $(SUID_CFLAGS) $(am__append_4) $(am__append_6) snap_confine_LDFLAGS = $(AM_LDFLAGS) $(SUID_LDFLAGS) -snap_confine_LDADD = $(LIBUDEV_LIBS) $(am__append_3) $(am__append_5) -snap_confine_unit_tests_SOURCES = \ - unit-tests-main.c \ - unit-tests.c \ - unit-tests.h \ - utils-test.c \ - cleanup-funcs-test.c \ - mount-support-test.c \ - verify-executable-name-test.c - -snap_confine_unit_tests_CFLAGS = $(snap_confine_CFLAGS) $(GLIB_CFLAGS) -snap_confine_unit_tests_LDADD = $(snap_confine_LDADD) $(GLIB_LIBS) -snap_confine_unit_tests_LDFLAGS = $(snap_confine_LDFLAGS) -EXTRA_DIST = 80-snappy-assign.rules snappy-app-dev +snap_confine_LDADD = $(LIBUDEV_LIBS) $(am__append_5) $(am__append_7) +@WITH_UNIT_TESTS_TRUE@snap_confine_unit_tests_SOURCES = \ +@WITH_UNIT_TESTS_TRUE@ unit-tests-main.c \ +@WITH_UNIT_TESTS_TRUE@ classic.c \ +@WITH_UNIT_TESTS_TRUE@ classic.h \ +@WITH_UNIT_TESTS_TRUE@ user-support.c \ +@WITH_UNIT_TESTS_TRUE@ user-support.h \ +@WITH_UNIT_TESTS_TRUE@ quirks.c \ +@WITH_UNIT_TESTS_TRUE@ quirks.h \ +@WITH_UNIT_TESTS_TRUE@ unit-tests.c \ +@WITH_UNIT_TESTS_TRUE@ unit-tests.h \ +@WITH_UNIT_TESTS_TRUE@ utils-test.c \ +@WITH_UNIT_TESTS_TRUE@ cleanup-funcs-test.c \ +@WITH_UNIT_TESTS_TRUE@ mount-support-test.c \ +@WITH_UNIT_TESTS_TRUE@ verify-executable-name-test.c \ +@WITH_UNIT_TESTS_TRUE@ mountinfo-test.c \ +@WITH_UNIT_TESTS_TRUE@ ns-support-test.c + +@WITH_UNIT_TESTS_TRUE@snap_confine_unit_tests_CFLAGS = $(snap_confine_CFLAGS) $(GLIB_CFLAGS) +@WITH_UNIT_TESTS_TRUE@snap_confine_unit_tests_LDADD = $(snap_confine_LDADD) $(GLIB_LIBS) +@WITH_UNIT_TESTS_TRUE@snap_confine_unit_tests_LDFLAGS = $(snap_confine_LDFLAGS) +EXTRA_DIST = 80-snappy-assign.rules snappy-app-dev snap-confine.apparmor.in all: all-am .SUFFIXES: @@ -430,6 +493,10 @@ @rm -f snap-confine-unit-tests$(EXEEXT) $(AM_V_CCLD)$(snap_confine_unit_tests_LINK) $(snap_confine_unit_tests_OBJECTS) $(snap_confine_unit_tests_LDADD) $(LIBS) +snap-discard-ns$(EXEEXT): $(snap_discard_ns_OBJECTS) $(snap_discard_ns_DEPENDENCIES) $(EXTRA_snap_discard_ns_DEPENDENCIES) + @rm -f snap-discard-ns$(EXEEXT) + $(AM_V_CCLD)$(snap_discard_ns_LINK) $(snap_discard_ns_OBJECTS) $(snap_discard_ns_LDADD) $(LIBS) + mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -441,17 +508,34 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-mount-support-nvidia.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-mount-support.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-mountinfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-ns-support.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-quirks.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-sc-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-seccomp-support.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-secure-getenv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-snap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-udev-support.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-user-support.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine-utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-classic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-cleanup-funcs-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-mount-support-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-mountinfo-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-ns-support-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-quirks.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-unit-tests-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-unit-tests.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-user-support.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-utils-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_confine_unit_tests-verify-executable-name-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_discard_ns-cleanup-funcs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_discard_ns-mountinfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_discard_ns-ns-support.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_discard_ns-secure-getenv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_discard_ns-snap-discard-ns.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_discard_ns-user-support.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snap_discard_ns-utils.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -509,6 +593,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi` +snap_confine-secure-getenv.o: secure-getenv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-secure-getenv.o -MD -MP -MF $(DEPDIR)/snap_confine-secure-getenv.Tpo -c -o snap_confine-secure-getenv.o `test -f 'secure-getenv.c' || echo '$(srcdir)/'`secure-getenv.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-secure-getenv.Tpo $(DEPDIR)/snap_confine-secure-getenv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='secure-getenv.c' object='snap_confine-secure-getenv.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-secure-getenv.o `test -f 'secure-getenv.c' || echo '$(srcdir)/'`secure-getenv.c + +snap_confine-secure-getenv.obj: secure-getenv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-secure-getenv.obj -MD -MP -MF $(DEPDIR)/snap_confine-secure-getenv.Tpo -c -o snap_confine-secure-getenv.obj `if test -f 'secure-getenv.c'; then $(CYGPATH_W) 'secure-getenv.c'; else $(CYGPATH_W) '$(srcdir)/secure-getenv.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-secure-getenv.Tpo $(DEPDIR)/snap_confine-secure-getenv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='secure-getenv.c' object='snap_confine-secure-getenv.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-secure-getenv.obj `if test -f 'secure-getenv.c'; then $(CYGPATH_W) 'secure-getenv.c'; else $(CYGPATH_W) '$(srcdir)/secure-getenv.c'; fi` + snap_confine-snap.o: snap.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-snap.o -MD -MP -MF $(DEPDIR)/snap_confine-snap.Tpo -c -o snap_confine-snap.o `test -f 'snap.c' || echo '$(srcdir)/'`snap.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-snap.Tpo $(DEPDIR)/snap_confine-snap.Po @@ -593,6 +691,62 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-udev-support.obj `if test -f 'udev-support.c'; then $(CYGPATH_W) 'udev-support.c'; else $(CYGPATH_W) '$(srcdir)/udev-support.c'; fi` +snap_confine-user-support.o: user-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-user-support.o -MD -MP -MF $(DEPDIR)/snap_confine-user-support.Tpo -c -o snap_confine-user-support.o `test -f 'user-support.c' || echo '$(srcdir)/'`user-support.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-user-support.Tpo $(DEPDIR)/snap_confine-user-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user-support.c' object='snap_confine-user-support.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-user-support.o `test -f 'user-support.c' || echo '$(srcdir)/'`user-support.c + +snap_confine-user-support.obj: user-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-user-support.obj -MD -MP -MF $(DEPDIR)/snap_confine-user-support.Tpo -c -o snap_confine-user-support.obj `if test -f 'user-support.c'; then $(CYGPATH_W) 'user-support.c'; else $(CYGPATH_W) '$(srcdir)/user-support.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-user-support.Tpo $(DEPDIR)/snap_confine-user-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user-support.c' object='snap_confine-user-support.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-user-support.obj `if test -f 'user-support.c'; then $(CYGPATH_W) 'user-support.c'; else $(CYGPATH_W) '$(srcdir)/user-support.c'; fi` + +snap_confine-quirks.o: quirks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-quirks.o -MD -MP -MF $(DEPDIR)/snap_confine-quirks.Tpo -c -o snap_confine-quirks.o `test -f 'quirks.c' || echo '$(srcdir)/'`quirks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-quirks.Tpo $(DEPDIR)/snap_confine-quirks.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='quirks.c' object='snap_confine-quirks.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-quirks.o `test -f 'quirks.c' || echo '$(srcdir)/'`quirks.c + +snap_confine-quirks.obj: quirks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-quirks.obj -MD -MP -MF $(DEPDIR)/snap_confine-quirks.Tpo -c -o snap_confine-quirks.obj `if test -f 'quirks.c'; then $(CYGPATH_W) 'quirks.c'; else $(CYGPATH_W) '$(srcdir)/quirks.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-quirks.Tpo $(DEPDIR)/snap_confine-quirks.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='quirks.c' object='snap_confine-quirks.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-quirks.obj `if test -f 'quirks.c'; then $(CYGPATH_W) 'quirks.c'; else $(CYGPATH_W) '$(srcdir)/quirks.c'; fi` + +snap_confine-mountinfo.o: mountinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-mountinfo.o -MD -MP -MF $(DEPDIR)/snap_confine-mountinfo.Tpo -c -o snap_confine-mountinfo.o `test -f 'mountinfo.c' || echo '$(srcdir)/'`mountinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-mountinfo.Tpo $(DEPDIR)/snap_confine-mountinfo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mountinfo.c' object='snap_confine-mountinfo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-mountinfo.o `test -f 'mountinfo.c' || echo '$(srcdir)/'`mountinfo.c + +snap_confine-mountinfo.obj: mountinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-mountinfo.obj -MD -MP -MF $(DEPDIR)/snap_confine-mountinfo.Tpo -c -o snap_confine-mountinfo.obj `if test -f 'mountinfo.c'; then $(CYGPATH_W) 'mountinfo.c'; else $(CYGPATH_W) '$(srcdir)/mountinfo.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-mountinfo.Tpo $(DEPDIR)/snap_confine-mountinfo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mountinfo.c' object='snap_confine-mountinfo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-mountinfo.obj `if test -f 'mountinfo.c'; then $(CYGPATH_W) 'mountinfo.c'; else $(CYGPATH_W) '$(srcdir)/mountinfo.c'; fi` + +snap_confine-ns-support.o: ns-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-ns-support.o -MD -MP -MF $(DEPDIR)/snap_confine-ns-support.Tpo -c -o snap_confine-ns-support.o `test -f 'ns-support.c' || echo '$(srcdir)/'`ns-support.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-ns-support.Tpo $(DEPDIR)/snap_confine-ns-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ns-support.c' object='snap_confine-ns-support.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-ns-support.o `test -f 'ns-support.c' || echo '$(srcdir)/'`ns-support.c + +snap_confine-ns-support.obj: ns-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-ns-support.obj -MD -MP -MF $(DEPDIR)/snap_confine-ns-support.Tpo -c -o snap_confine-ns-support.obj `if test -f 'ns-support.c'; then $(CYGPATH_W) 'ns-support.c'; else $(CYGPATH_W) '$(srcdir)/ns-support.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-ns-support.Tpo $(DEPDIR)/snap_confine-ns-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ns-support.c' object='snap_confine-ns-support.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -c -o snap_confine-ns-support.obj `if test -f 'ns-support.c'; then $(CYGPATH_W) 'ns-support.c'; else $(CYGPATH_W) '$(srcdir)/ns-support.c'; fi` + snap_confine-seccomp-support.o: seccomp-support.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_CFLAGS) $(CFLAGS) -MT snap_confine-seccomp-support.o -MD -MP -MF $(DEPDIR)/snap_confine-seccomp-support.Tpo -c -o snap_confine-seccomp-support.o `test -f 'seccomp-support.c' || echo '$(srcdir)/'`seccomp-support.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine-seccomp-support.Tpo $(DEPDIR)/snap_confine-seccomp-support.Po @@ -621,6 +775,48 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-unit-tests-main.obj `if test -f 'unit-tests-main.c'; then $(CYGPATH_W) 'unit-tests-main.c'; else $(CYGPATH_W) '$(srcdir)/unit-tests-main.c'; fi` +snap_confine_unit_tests-classic.o: classic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-classic.o -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-classic.Tpo -c -o snap_confine_unit_tests-classic.o `test -f 'classic.c' || echo '$(srcdir)/'`classic.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-classic.Tpo $(DEPDIR)/snap_confine_unit_tests-classic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='classic.c' object='snap_confine_unit_tests-classic.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-classic.o `test -f 'classic.c' || echo '$(srcdir)/'`classic.c + +snap_confine_unit_tests-classic.obj: classic.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-classic.obj -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-classic.Tpo -c -o snap_confine_unit_tests-classic.obj `if test -f 'classic.c'; then $(CYGPATH_W) 'classic.c'; else $(CYGPATH_W) '$(srcdir)/classic.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-classic.Tpo $(DEPDIR)/snap_confine_unit_tests-classic.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='classic.c' object='snap_confine_unit_tests-classic.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-classic.obj `if test -f 'classic.c'; then $(CYGPATH_W) 'classic.c'; else $(CYGPATH_W) '$(srcdir)/classic.c'; fi` + +snap_confine_unit_tests-user-support.o: user-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-user-support.o -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-user-support.Tpo -c -o snap_confine_unit_tests-user-support.o `test -f 'user-support.c' || echo '$(srcdir)/'`user-support.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-user-support.Tpo $(DEPDIR)/snap_confine_unit_tests-user-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user-support.c' object='snap_confine_unit_tests-user-support.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-user-support.o `test -f 'user-support.c' || echo '$(srcdir)/'`user-support.c + +snap_confine_unit_tests-user-support.obj: user-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-user-support.obj -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-user-support.Tpo -c -o snap_confine_unit_tests-user-support.obj `if test -f 'user-support.c'; then $(CYGPATH_W) 'user-support.c'; else $(CYGPATH_W) '$(srcdir)/user-support.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-user-support.Tpo $(DEPDIR)/snap_confine_unit_tests-user-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user-support.c' object='snap_confine_unit_tests-user-support.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-user-support.obj `if test -f 'user-support.c'; then $(CYGPATH_W) 'user-support.c'; else $(CYGPATH_W) '$(srcdir)/user-support.c'; fi` + +snap_confine_unit_tests-quirks.o: quirks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-quirks.o -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-quirks.Tpo -c -o snap_confine_unit_tests-quirks.o `test -f 'quirks.c' || echo '$(srcdir)/'`quirks.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-quirks.Tpo $(DEPDIR)/snap_confine_unit_tests-quirks.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='quirks.c' object='snap_confine_unit_tests-quirks.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-quirks.o `test -f 'quirks.c' || echo '$(srcdir)/'`quirks.c + +snap_confine_unit_tests-quirks.obj: quirks.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-quirks.obj -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-quirks.Tpo -c -o snap_confine_unit_tests-quirks.obj `if test -f 'quirks.c'; then $(CYGPATH_W) 'quirks.c'; else $(CYGPATH_W) '$(srcdir)/quirks.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-quirks.Tpo $(DEPDIR)/snap_confine_unit_tests-quirks.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='quirks.c' object='snap_confine_unit_tests-quirks.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-quirks.obj `if test -f 'quirks.c'; then $(CYGPATH_W) 'quirks.c'; else $(CYGPATH_W) '$(srcdir)/quirks.c'; fi` + snap_confine_unit_tests-unit-tests.o: unit-tests.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-unit-tests.o -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-unit-tests.Tpo -c -o snap_confine_unit_tests-unit-tests.o `test -f 'unit-tests.c' || echo '$(srcdir)/'`unit-tests.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-unit-tests.Tpo $(DEPDIR)/snap_confine_unit_tests-unit-tests.Po @@ -691,6 +887,132 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-verify-executable-name-test.obj `if test -f 'verify-executable-name-test.c'; then $(CYGPATH_W) 'verify-executable-name-test.c'; else $(CYGPATH_W) '$(srcdir)/verify-executable-name-test.c'; fi` +snap_confine_unit_tests-mountinfo-test.o: mountinfo-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-mountinfo-test.o -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-mountinfo-test.Tpo -c -o snap_confine_unit_tests-mountinfo-test.o `test -f 'mountinfo-test.c' || echo '$(srcdir)/'`mountinfo-test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-mountinfo-test.Tpo $(DEPDIR)/snap_confine_unit_tests-mountinfo-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mountinfo-test.c' object='snap_confine_unit_tests-mountinfo-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-mountinfo-test.o `test -f 'mountinfo-test.c' || echo '$(srcdir)/'`mountinfo-test.c + +snap_confine_unit_tests-mountinfo-test.obj: mountinfo-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-mountinfo-test.obj -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-mountinfo-test.Tpo -c -o snap_confine_unit_tests-mountinfo-test.obj `if test -f 'mountinfo-test.c'; then $(CYGPATH_W) 'mountinfo-test.c'; else $(CYGPATH_W) '$(srcdir)/mountinfo-test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-mountinfo-test.Tpo $(DEPDIR)/snap_confine_unit_tests-mountinfo-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mountinfo-test.c' object='snap_confine_unit_tests-mountinfo-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-mountinfo-test.obj `if test -f 'mountinfo-test.c'; then $(CYGPATH_W) 'mountinfo-test.c'; else $(CYGPATH_W) '$(srcdir)/mountinfo-test.c'; fi` + +snap_confine_unit_tests-ns-support-test.o: ns-support-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-ns-support-test.o -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-ns-support-test.Tpo -c -o snap_confine_unit_tests-ns-support-test.o `test -f 'ns-support-test.c' || echo '$(srcdir)/'`ns-support-test.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-ns-support-test.Tpo $(DEPDIR)/snap_confine_unit_tests-ns-support-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ns-support-test.c' object='snap_confine_unit_tests-ns-support-test.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-ns-support-test.o `test -f 'ns-support-test.c' || echo '$(srcdir)/'`ns-support-test.c + +snap_confine_unit_tests-ns-support-test.obj: ns-support-test.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -MT snap_confine_unit_tests-ns-support-test.obj -MD -MP -MF $(DEPDIR)/snap_confine_unit_tests-ns-support-test.Tpo -c -o snap_confine_unit_tests-ns-support-test.obj `if test -f 'ns-support-test.c'; then $(CYGPATH_W) 'ns-support-test.c'; else $(CYGPATH_W) '$(srcdir)/ns-support-test.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_confine_unit_tests-ns-support-test.Tpo $(DEPDIR)/snap_confine_unit_tests-ns-support-test.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ns-support-test.c' object='snap_confine_unit_tests-ns-support-test.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_confine_unit_tests_CFLAGS) $(CFLAGS) -c -o snap_confine_unit_tests-ns-support-test.obj `if test -f 'ns-support-test.c'; then $(CYGPATH_W) 'ns-support-test.c'; else $(CYGPATH_W) '$(srcdir)/ns-support-test.c'; fi` + +snap_discard_ns-ns-support.o: ns-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-ns-support.o -MD -MP -MF $(DEPDIR)/snap_discard_ns-ns-support.Tpo -c -o snap_discard_ns-ns-support.o `test -f 'ns-support.c' || echo '$(srcdir)/'`ns-support.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-ns-support.Tpo $(DEPDIR)/snap_discard_ns-ns-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ns-support.c' object='snap_discard_ns-ns-support.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-ns-support.o `test -f 'ns-support.c' || echo '$(srcdir)/'`ns-support.c + +snap_discard_ns-ns-support.obj: ns-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-ns-support.obj -MD -MP -MF $(DEPDIR)/snap_discard_ns-ns-support.Tpo -c -o snap_discard_ns-ns-support.obj `if test -f 'ns-support.c'; then $(CYGPATH_W) 'ns-support.c'; else $(CYGPATH_W) '$(srcdir)/ns-support.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-ns-support.Tpo $(DEPDIR)/snap_discard_ns-ns-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ns-support.c' object='snap_discard_ns-ns-support.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-ns-support.obj `if test -f 'ns-support.c'; then $(CYGPATH_W) 'ns-support.c'; else $(CYGPATH_W) '$(srcdir)/ns-support.c'; fi` + +snap_discard_ns-user-support.o: user-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-user-support.o -MD -MP -MF $(DEPDIR)/snap_discard_ns-user-support.Tpo -c -o snap_discard_ns-user-support.o `test -f 'user-support.c' || echo '$(srcdir)/'`user-support.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-user-support.Tpo $(DEPDIR)/snap_discard_ns-user-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user-support.c' object='snap_discard_ns-user-support.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-user-support.o `test -f 'user-support.c' || echo '$(srcdir)/'`user-support.c + +snap_discard_ns-user-support.obj: user-support.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-user-support.obj -MD -MP -MF $(DEPDIR)/snap_discard_ns-user-support.Tpo -c -o snap_discard_ns-user-support.obj `if test -f 'user-support.c'; then $(CYGPATH_W) 'user-support.c'; else $(CYGPATH_W) '$(srcdir)/user-support.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-user-support.Tpo $(DEPDIR)/snap_discard_ns-user-support.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user-support.c' object='snap_discard_ns-user-support.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-user-support.obj `if test -f 'user-support.c'; then $(CYGPATH_W) 'user-support.c'; else $(CYGPATH_W) '$(srcdir)/user-support.c'; fi` + +snap_discard_ns-utils.o: utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-utils.o -MD -MP -MF $(DEPDIR)/snap_discard_ns-utils.Tpo -c -o snap_discard_ns-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-utils.Tpo $(DEPDIR)/snap_discard_ns-utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='snap_discard_ns-utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c + +snap_discard_ns-utils.obj: utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-utils.obj -MD -MP -MF $(DEPDIR)/snap_discard_ns-utils.Tpo -c -o snap_discard_ns-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-utils.Tpo $(DEPDIR)/snap_discard_ns-utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='snap_discard_ns-utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi` + +snap_discard_ns-secure-getenv.o: secure-getenv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-secure-getenv.o -MD -MP -MF $(DEPDIR)/snap_discard_ns-secure-getenv.Tpo -c -o snap_discard_ns-secure-getenv.o `test -f 'secure-getenv.c' || echo '$(srcdir)/'`secure-getenv.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-secure-getenv.Tpo $(DEPDIR)/snap_discard_ns-secure-getenv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='secure-getenv.c' object='snap_discard_ns-secure-getenv.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-secure-getenv.o `test -f 'secure-getenv.c' || echo '$(srcdir)/'`secure-getenv.c + +snap_discard_ns-secure-getenv.obj: secure-getenv.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-secure-getenv.obj -MD -MP -MF $(DEPDIR)/snap_discard_ns-secure-getenv.Tpo -c -o snap_discard_ns-secure-getenv.obj `if test -f 'secure-getenv.c'; then $(CYGPATH_W) 'secure-getenv.c'; else $(CYGPATH_W) '$(srcdir)/secure-getenv.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-secure-getenv.Tpo $(DEPDIR)/snap_discard_ns-secure-getenv.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='secure-getenv.c' object='snap_discard_ns-secure-getenv.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-secure-getenv.obj `if test -f 'secure-getenv.c'; then $(CYGPATH_W) 'secure-getenv.c'; else $(CYGPATH_W) '$(srcdir)/secure-getenv.c'; fi` + +snap_discard_ns-cleanup-funcs.o: cleanup-funcs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-cleanup-funcs.o -MD -MP -MF $(DEPDIR)/snap_discard_ns-cleanup-funcs.Tpo -c -o snap_discard_ns-cleanup-funcs.o `test -f 'cleanup-funcs.c' || echo '$(srcdir)/'`cleanup-funcs.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-cleanup-funcs.Tpo $(DEPDIR)/snap_discard_ns-cleanup-funcs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cleanup-funcs.c' object='snap_discard_ns-cleanup-funcs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-cleanup-funcs.o `test -f 'cleanup-funcs.c' || echo '$(srcdir)/'`cleanup-funcs.c + +snap_discard_ns-cleanup-funcs.obj: cleanup-funcs.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-cleanup-funcs.obj -MD -MP -MF $(DEPDIR)/snap_discard_ns-cleanup-funcs.Tpo -c -o snap_discard_ns-cleanup-funcs.obj `if test -f 'cleanup-funcs.c'; then $(CYGPATH_W) 'cleanup-funcs.c'; else $(CYGPATH_W) '$(srcdir)/cleanup-funcs.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-cleanup-funcs.Tpo $(DEPDIR)/snap_discard_ns-cleanup-funcs.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cleanup-funcs.c' object='snap_discard_ns-cleanup-funcs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-cleanup-funcs.obj `if test -f 'cleanup-funcs.c'; then $(CYGPATH_W) 'cleanup-funcs.c'; else $(CYGPATH_W) '$(srcdir)/cleanup-funcs.c'; fi` + +snap_discard_ns-mountinfo.o: mountinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-mountinfo.o -MD -MP -MF $(DEPDIR)/snap_discard_ns-mountinfo.Tpo -c -o snap_discard_ns-mountinfo.o `test -f 'mountinfo.c' || echo '$(srcdir)/'`mountinfo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-mountinfo.Tpo $(DEPDIR)/snap_discard_ns-mountinfo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mountinfo.c' object='snap_discard_ns-mountinfo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-mountinfo.o `test -f 'mountinfo.c' || echo '$(srcdir)/'`mountinfo.c + +snap_discard_ns-mountinfo.obj: mountinfo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-mountinfo.obj -MD -MP -MF $(DEPDIR)/snap_discard_ns-mountinfo.Tpo -c -o snap_discard_ns-mountinfo.obj `if test -f 'mountinfo.c'; then $(CYGPATH_W) 'mountinfo.c'; else $(CYGPATH_W) '$(srcdir)/mountinfo.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-mountinfo.Tpo $(DEPDIR)/snap_discard_ns-mountinfo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mountinfo.c' object='snap_discard_ns-mountinfo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-mountinfo.obj `if test -f 'mountinfo.c'; then $(CYGPATH_W) 'mountinfo.c'; else $(CYGPATH_W) '$(srcdir)/mountinfo.c'; fi` + +snap_discard_ns-snap-discard-ns.o: snap-discard-ns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-snap-discard-ns.o -MD -MP -MF $(DEPDIR)/snap_discard_ns-snap-discard-ns.Tpo -c -o snap_discard_ns-snap-discard-ns.o `test -f 'snap-discard-ns.c' || echo '$(srcdir)/'`snap-discard-ns.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-snap-discard-ns.Tpo $(DEPDIR)/snap_discard_ns-snap-discard-ns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='snap-discard-ns.c' object='snap_discard_ns-snap-discard-ns.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-snap-discard-ns.o `test -f 'snap-discard-ns.c' || echo '$(srcdir)/'`snap-discard-ns.c + +snap_discard_ns-snap-discard-ns.obj: snap-discard-ns.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -MT snap_discard_ns-snap-discard-ns.obj -MD -MP -MF $(DEPDIR)/snap_discard_ns-snap-discard-ns.Tpo -c -o snap_discard_ns-snap-discard-ns.obj `if test -f 'snap-discard-ns.c'; then $(CYGPATH_W) 'snap-discard-ns.c'; else $(CYGPATH_W) '$(srcdir)/snap-discard-ns.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/snap_discard_ns-snap-discard-ns.Tpo $(DEPDIR)/snap_discard_ns-snap-discard-ns.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='snap-discard-ns.c' object='snap_discard_ns-snap-discard-ns.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snap_discard_ns_CFLAGS) $(CFLAGS) -c -o snap_discard_ns-snap-discard-ns.obj `if test -f 'snap-discard-ns.c'; then $(CYGPATH_W) 'snap-discard-ns.c'; else $(CYGPATH_W) '$(srcdir)/snap-discard-ns.c'; fi` + ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am @@ -915,7 +1237,7 @@ .PHONY: check-unit-tests check-unit-tests: snap-confine-unit-tests - ./snap-confine-unit-tests +@WITH_UNIT_TESTS_TRUE@ ./snap-confine-unit-tests # Run check-syntax when checking # TODO: conver those to autotools-style tests later @@ -923,30 +1245,51 @@ .PHONY: fmt fmt: - for f in $(wildcard *.c) $(wildcard *.h); do \ + for f in $(wildcard $(srcdir)/*.c) $(wildcard $(srcdir)/*.h); do \ echo "Formatting $$f ... "; \ indent -linux "$$f"; \ done; +snap-confine.apparmor: snap-confine.apparmor.in Makefile + sed -e 's,[@]LIBEXECDIR[@],$(libexecdir),g' -e 's,[@]SNAP_MOUNT_DIR[@],$(SNAP_MOUNT_DIR),' <$< >$@ + # NOTE: This makes distcheck fail but it is required for udev, so go figure. # http://www.gnu.org/software/automake/manual/automake.html#Hard_002dCoded-Install-Paths # -# Install udev rules -install-data-local: +# Install udev rules and the apparmor profile +# +# NOTE: the funky make functions here just convert /foo/bar/froz into foo.bar.froz +# The inner subst replaces slashes with dots and the outer patsubst strips the leading dot +# +# NOTE: The 'void' directory *has to* be chmod 000 +install-data-local: snap-confine.apparmor install -d -m 755 $(DESTDIR)$(shell pkg-config udev --variable=udevdir)/rules.d install -m 644 $(srcdir)/80-snappy-assign.rules $(DESTDIR)$(shell pkg-config udev --variable=udevdir)/rules.d + install -d -m 755 $(DESTDIR)/etc/apparmor.d/ + install -m 644 snap-confine.apparmor $(DESTDIR)/etc/apparmor.d/$(patsubst .%,%,$(subst /,.,$(libexecdir))).snap-confine + install -d -m 000 $(DESTDIR)/var/lib/snapd/void # Install support script for udev rules install-exec-local: install -d -m 755 $(DESTDIR)$(shell pkg-config udev --variable=udevdir) install -m 755 $(srcdir)/snappy-app-dev $(DESTDIR)$(shell pkg-config udev --variable=udevdir) -# Ensure that snap-confine is +s (setuid) install-exec-hook: - chmod 4755 $(DESTDIR)$(libexecdir)/snap-confine +# Ensure that snap-confine has CAP_SYS_ADMIN capabilitiy +@CAPS_OVER_SETUID_TRUE@ setcap cap_sys_admin=pe $(DESTDIR)$(libexecdir)/snap-confine +# Ensure that snap-confine is +s (setuid) +@CAPS_OVER_SETUID_FALSE@ chmod 4755 $(DESTDIR)$(libexecdir)/snap-confine install -d -m 755 $(DESTDIR)$(bindir) ln -sf $(libexecdir)/snap-confine $(DESTDIR)$(bindir)/ubuntu-core-launcher +# The hack target helps devlopers work on snap-confine on their live system by +# installing a fresh copy of snap confine and the appropriate apparmor profile. +.PHONY: hack +hack: snap-confine snap-confine.apparmor + sudo install -D -m 4755 snap-confine $(DESTDIR)$(libexecdir)/snap-confine + sudo install -m 644 snap-confine.apparmor $(DESTDIR)/etc/apparmor.d/$(patsubst .%,%,$(subst /,.,$(libexecdir))).snap-confine + sudo apparmor_parser -r snap-confine.apparmor + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff -Nru snap-confine-1.0.38/src/mountinfo.c snap-confine-1.0.41/src/mountinfo.c --- snap-confine-1.0.38/src/mountinfo.c 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/mountinfo.c 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2016 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 . + */ + +#include "mountinfo.h" + +#include +#include +#include +#include + +struct mountinfo { + struct mountinfo_entry *first; +}; + +struct mountinfo_entry { + int mount_id; + int parent_id; + unsigned dev_major, dev_minor; + char *root; + char *mount_dir; + char *mount_opts; + char *optional_fields; + char *fs_type; + char *mount_source; + char *super_opts; + + struct mountinfo_entry *next; + // Buffer holding all of the text data above. + // + // The buffer must be the last element of the structure. It is allocated + // along with the structure itself and does not need to be freed + // separately. + char line_buf[0]; +}; + +/** + * Parse a single mountinfo entry (line). + * + * The format, described by Linux kernel documentation, is as follows: + * + * 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue + * (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) + * + * (1) mount ID: unique identifier of the mount (may be reused after umount) + * (2) parent ID: ID of parent (or of self for the top of the mount tree) + * (3) major:minor: value of st_dev for files on filesystem + * (4) root: root of the mount within the filesystem + * (5) mount point: mount point relative to the process's root + * (6) mount options: per mount options + * (7) optional fields: zero or more fields of the form "tag[:value]" + * (8) separator: marks the end of the optional fields + * (9) filesystem type: name of filesystem of the form "type[.subtype]" + * (10) mount source: filesystem specific information or "none" + * (11) super options: per super block options + **/ +static struct mountinfo_entry *parse_mountinfo_entry(const char *line) + __attribute__ ((nonnull(1))); + +/** + * Free a mountinfo structure and all its entries. + **/ +static void free_mountinfo(struct mountinfo *info) + __attribute__ ((nonnull(1))); + +/** + * Free a mountinfo entry. + **/ +static void free_mountinfo_entry(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +static void cleanup_fclose(FILE ** ptr); +static void cleanup_free(char **ptr); + +struct mountinfo_entry *first_mountinfo_entry(struct mountinfo *info) +{ + return info->first; +} + +struct mountinfo_entry *next_mountinfo_entry(struct mountinfo_entry + *entry) +{ + return entry->next; +} + +int mountinfo_entry_mount_id(struct mountinfo_entry *entry) +{ + return entry->mount_id; +} + +int mountinfo_entry_parent_id(struct mountinfo_entry *entry) +{ + return entry->parent_id; +} + +unsigned mountinfo_entry_dev_major(struct mountinfo_entry *entry) +{ + return entry->dev_major; +} + +unsigned mountinfo_entry_dev_minor(struct mountinfo_entry *entry) +{ + return entry->dev_minor; +} + +const char *mountinfo_entry_root(struct mountinfo_entry *entry) +{ + return entry->root; +} + +const char *mountinfo_entry_mount_dir(struct mountinfo_entry *entry) +{ + return entry->mount_dir; +} + +const char *mountinfo_entry_mount_opts(struct mountinfo_entry *entry) +{ + return entry->mount_opts; +} + +const char *mountinfo_entry_optional_fields(struct mountinfo_entry *entry) +{ + return entry->optional_fields; +} + +const char *mountinfo_entry_fs_type(struct mountinfo_entry *entry) +{ + return entry->fs_type; +} + +const char *mountinfo_entry_mount_source(struct mountinfo_entry *entry) +{ + return entry->mount_source; +} + +const char *mountinfo_entry_super_opts(struct mountinfo_entry *entry) +{ + return entry->super_opts; +} + +struct mountinfo *parse_mountinfo(const char *fname) +{ + struct mountinfo *info = calloc(1, sizeof *info); + if (info == NULL) { + return NULL; + } + if (fname == NULL) { + fname = "/proc/self/mountinfo"; + } + FILE *f __attribute__ ((cleanup(cleanup_fclose))) = fopen(fname, "rt"); + if (f == NULL) { + free(info); + return NULL; + } + char *line __attribute__ ((cleanup(cleanup_free))) = NULL; + size_t line_size = 0; + struct mountinfo_entry *entry, *last = NULL; + for (;;) { + errno = 0; + if (getline(&line, &line_size, f) == -1) { + if (errno != 0) { + free_mountinfo(info); + return NULL; + } + break; + }; + entry = parse_mountinfo_entry(line); + if (entry == NULL) { + free_mountinfo(info); + return NULL; + } + if (last != NULL) { + last->next = entry; + } else { + info->first = entry; + } + last = entry; + } + return info; +} + +static struct mountinfo_entry *parse_mountinfo_entry(const char *line) +{ + // NOTE: the mountinfo structure is allocated along with enough extra + // storage to hold the whole line we are parsing. This is used as backing + // store for all text fields. + // + // The idea is that since the line has a given length and we are only after + // set of substrings we can easily predict the amount of required space + // (after all, it is just a set of non-overlapping substrings) and append + // it to the allocated entry structure. + // + // The parsing code below, specifically parse_next_string_field(), uses + // this extra memory to hold data parsed from the original line. In the + // end, the result is similar to using strtok except that the source and + // destination buffers are separate. + struct mountinfo_entry *entry = + calloc(1, sizeof *entry + strlen(line) + 1); + if (entry == NULL) { + return NULL; + } + int nscanned; + int offset, total_offset = 0; + nscanned = sscanf(line, "%d %d %u:%u %n", + &entry->mount_id, &entry->parent_id, + &entry->dev_major, &entry->dev_minor, &offset); + if (nscanned != 4) + goto fail; + total_offset += offset; + int total_used = 0; + char *parse_next_string_field() { + char *field = &entry->line_buf[0] + total_used; + nscanned = sscanf(line + total_offset, "%s %n", field, &offset); + if (nscanned != 1) + return NULL; + total_offset += offset; + total_used += offset + 1; + return field; + } + if ((entry->root = parse_next_string_field()) == NULL) + goto fail; + if ((entry->mount_dir = parse_next_string_field()) == NULL) + goto fail; + if ((entry->mount_opts = parse_next_string_field()) == NULL) + goto fail; + entry->optional_fields = &entry->line_buf[0] + total_used++; + // NOTE: This ensures that optional_fields is never NULL. If this changes, + // must adjust all callers of parse_mountinfo_entry() accordingly. + strcpy(entry->optional_fields, ""); + for (;;) { + char *opt_field = parse_next_string_field(); + if (opt_field == NULL) + goto fail; + if (strcmp(opt_field, "-") == 0) { + break; + } + if (*entry->optional_fields) { + strcat(entry->optional_fields, " "); + } + strcat(entry->optional_fields, opt_field); + } + if ((entry->fs_type = parse_next_string_field()) == NULL) + goto fail; + if ((entry->mount_source = parse_next_string_field()) == NULL) + goto fail; + if ((entry->super_opts = parse_next_string_field()) == NULL) + goto fail; + return entry; + fail: + free(entry); + return NULL; +} + +void cleanup_mountinfo(struct mountinfo **ptr) +{ + if (*ptr != NULL) { + free_mountinfo(*ptr); + *ptr = NULL; + } +} + +static void free_mountinfo(struct mountinfo *info) +{ + struct mountinfo_entry *entry, *next; + for (entry = info->first; entry != NULL; entry = next) { + next = entry->next; + free_mountinfo_entry(entry); + } + free(info); +} + +static void free_mountinfo_entry(struct mountinfo_entry *entry) +{ + free(entry); +} + +static void cleanup_fclose(FILE ** ptr) +{ + fclose(*ptr); +} + +static void cleanup_free(char **ptr) +{ + free(*ptr); +} diff -Nru snap-confine-1.0.38/src/mountinfo.h snap-confine-1.0.41/src/mountinfo.h --- snap-confine-1.0.38/src/mountinfo.h 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/mountinfo.h 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2016 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 . + */ + +#ifndef SC_MOUNTINFO_H +#define SC_MOUNTINFO_H + +/** + * Structure describing entire /proc/self/mountinfo file + **/ +struct mountinfo; + +/** + * Structure describing a single entry in /proc/self/mountinfo + **/ +struct mountinfo_entry; + +/** + * Parse a file in according to mountinfo syntax. + * + * The argument can be used to parse an arbitrary file. NULL can be used to + * implicitly parse /proc/self/mountinfo, that is the mount information + * associated with the current process. + **/ +struct mountinfo *parse_mountinfo(const char *fname); + +/** + * Free a mountinfo structure. + * + * This function is designed to be used with __attribute__((cleanup)) so it + * takes a pointer to the freed object (which is also a pointer). + **/ +void cleanup_mountinfo(struct mountinfo **ptr) __attribute__ ((nonnull(1))); + +/** + * Get the first mountinfo entry. + * + * The returned value may be NULL if the parsed file contained no entries. The + * returned value is bound to the lifecycle of the whole mountinfo structure + * and should not be freed explicitly. + **/ +struct mountinfo_entry *first_mountinfo_entry(struct mountinfo *info) + __attribute__ ((nonnull(1))); + +/** + * Get the next mountinfo entry. + * + * The returned value is a pointer to the next mountinfo entry or NULL if this + * was the last entry. The returned value is bound to the lifecycle of the + * whole mountinfo structure and should not be freed explicitly. + **/ +struct mountinfo_entry *next_mountinfo_entry(struct mountinfo_entry + *entry) + __attribute__ ((nonnull(1))); + +/** + * Get the mount identifier of a given mount entry. + **/ +int mountinfo_entry_mount_id(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +/** + * Get the parent mount identifier of a given mount entry. + **/ +int mountinfo_entry_parent_id(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +unsigned mountinfo_entry_dev_major(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +unsigned mountinfo_entry_dev_minor(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +/** + * Get the root directory of a given mount entry. + **/ +const char *mountinfo_entry_root(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +/** + * Get the mount point of a given mount entry. + **/ +const char *mountinfo_entry_mount_dir(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +/** + * Get the mount options of a given mount entry. + **/ +const char *mountinfo_entry_mount_opts(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +/** + * Get optional tagged data associated of a given mount entry. + * + * The return value is a string (possibly empty but never NULL) in the format + * tag[:value]. Known tags are: + * + * "shared:X": + * mount is shared in peer group X + * "master:X": + * mount is slave to peer group X + * "propagate_from:X" + * mount is slave and receives propagation from peer group X (*) + * "unbindable": + * mount is unbindable + * + * (*) X is the closest dominant peer group under the process's root. + * If X is the immediate master of the mount, or if there's no dominant peer + * group under the same root, then only the "master:X" field is present and not + * the "propagate_from:X" field. + **/ +const char *mountinfo_entry_optional_fields(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +/** + * Get the file system type of a given mount entry. + **/ +const char *mountinfo_entry_fs_type(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +/** + * Get the source of a given mount entry. + **/ +const char *mountinfo_entry_mount_source(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +/** + * Get the super block options of a given mount entry. + **/ +const char *mountinfo_entry_super_opts(struct mountinfo_entry *entry) + __attribute__ ((nonnull(1))); + +#endif diff -Nru snap-confine-1.0.38/src/mountinfo-test.c snap-confine-1.0.41/src/mountinfo-test.c --- snap-confine-1.0.38/src/mountinfo-test.c 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/mountinfo-test.c 2016-09-19 09:41:13.000000000 +0000 @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2016 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 . + * + */ + +#include "mountinfo.h" +#include "mountinfo.c" + +#include + +static void test_parse_mountinfo_entry__sysfs() +{ + const char *line = + "19 25 0:18 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw"; + struct mountinfo_entry *entry = parse_mountinfo_entry(line); + g_assert_nonnull(entry); + g_test_queue_destroy((GDestroyNotify) free_mountinfo_entry, entry); + g_assert_cmpint(entry->mount_id, ==, 19); + g_assert_cmpint(entry->parent_id, ==, 25); + g_assert_cmpint(entry->dev_major, ==, 0); + g_assert_cmpint(entry->dev_minor, ==, 18); + g_assert_cmpstr(entry->root, ==, "/"); + g_assert_cmpstr(entry->mount_dir, ==, "/sys"); + g_assert_cmpstr(entry->mount_opts, ==, + "rw,nosuid,nodev,noexec,relatime"); + g_assert_cmpstr(entry->optional_fields, ==, "shared:7"); + g_assert_cmpstr(entry->fs_type, ==, "sysfs"); + g_assert_cmpstr(entry->mount_source, ==, "sysfs"); + g_assert_cmpstr(entry->super_opts, ==, "rw"); + g_assert_null(entry->next); +} + +// Parse the /run/snapd/ns bind mount (over itself) +// Note that /run is itself a tmpfs mount point. +static void test_parse_mountinfo_entry__snapd_ns() +{ + const char *line = + "104 23 0:19 /snapd/ns /run/snapd/ns rw,nosuid,noexec,relatime - tmpfs tmpfs rw,size=99840k,mode=755"; + struct mountinfo_entry *entry = parse_mountinfo_entry(line); + g_assert_nonnull(entry); + g_test_queue_destroy((GDestroyNotify) free_mountinfo_entry, entry); + g_assert_cmpint(entry->mount_id, ==, 104); + g_assert_cmpint(entry->parent_id, ==, 23); + g_assert_cmpint(entry->dev_major, ==, 0); + g_assert_cmpint(entry->dev_minor, ==, 19); + g_assert_cmpstr(entry->root, ==, "/snapd/ns"); + g_assert_cmpstr(entry->mount_dir, ==, "/run/snapd/ns"); + g_assert_cmpstr(entry->mount_opts, ==, "rw,nosuid,noexec,relatime"); + g_assert_cmpstr(entry->optional_fields, ==, ""); + g_assert_cmpstr(entry->fs_type, ==, "tmpfs"); + g_assert_cmpstr(entry->mount_source, ==, "tmpfs"); + g_assert_cmpstr(entry->super_opts, ==, "rw,size=99840k,mode=755"); + g_assert_null(entry->next); +} + +static void test_parse_mountinfo_entry__snapd_mnt() +{ + const char *line = + "256 104 0:3 mnt:[4026532509] /run/snapd/ns/hello-world.mnt rw - nsfs nsfs rw"; + struct mountinfo_entry *entry = parse_mountinfo_entry(line); + g_assert_nonnull(entry); + g_test_queue_destroy((GDestroyNotify) free_mountinfo_entry, entry); + g_assert_cmpint(entry->mount_id, ==, 256); + g_assert_cmpint(entry->parent_id, ==, 104); + g_assert_cmpint(entry->dev_major, ==, 0); + g_assert_cmpint(entry->dev_minor, ==, 3); + g_assert_cmpstr(entry->root, ==, "mnt:[4026532509]"); + g_assert_cmpstr(entry->mount_dir, ==, "/run/snapd/ns/hello-world.mnt"); + g_assert_cmpstr(entry->mount_opts, ==, "rw"); + g_assert_cmpstr(entry->optional_fields, ==, ""); + g_assert_cmpstr(entry->fs_type, ==, "nsfs"); + g_assert_cmpstr(entry->mount_source, ==, "nsfs"); + g_assert_cmpstr(entry->super_opts, ==, "rw"); + g_assert_null(entry->next); +} + +static void test_parse_mountinfo_entry__garbage() +{ + const char *line = "256 104 0:3"; + struct mountinfo_entry *entry = parse_mountinfo_entry(line); + g_assert_null(entry); +} + +static void test_parse_mountinfo_entry__no_tags() +{ + const char *line = + "1 2 3:4 root mount-dir mount-opts - fs-type mount-source super-opts"; + struct mountinfo_entry *entry = parse_mountinfo_entry(line); + g_assert_nonnull(entry); + g_test_queue_destroy((GDestroyNotify) free_mountinfo_entry, entry); + g_assert_cmpint(entry->mount_id, ==, 1); + g_assert_cmpint(entry->parent_id, ==, 2); + g_assert_cmpint(entry->dev_major, ==, 3); + g_assert_cmpint(entry->dev_minor, ==, 4); + g_assert_cmpstr(entry->root, ==, "root"); + g_assert_cmpstr(entry->mount_dir, ==, "mount-dir"); + g_assert_cmpstr(entry->mount_opts, ==, "mount-opts"); + g_assert_cmpstr(entry->optional_fields, ==, ""); + g_assert_cmpstr(entry->fs_type, ==, "fs-type"); + g_assert_cmpstr(entry->mount_source, ==, "mount-source"); + g_assert_cmpstr(entry->super_opts, ==, "super-opts"); + g_assert_null(entry->next); +} + +static void test_parse_mountinfo_entry__one_tag() +{ + const char *line = + "1 2 3:4 root mount-dir mount-opts tag:1 - fs-type mount-source super-opts"; + struct mountinfo_entry *entry = parse_mountinfo_entry(line); + g_assert_nonnull(entry); + g_test_queue_destroy((GDestroyNotify) free_mountinfo_entry, entry); + g_assert_cmpint(entry->mount_id, ==, 1); + g_assert_cmpint(entry->parent_id, ==, 2); + g_assert_cmpint(entry->dev_major, ==, 3); + g_assert_cmpint(entry->dev_minor, ==, 4); + g_assert_cmpstr(entry->root, ==, "root"); + g_assert_cmpstr(entry->mount_dir, ==, "mount-dir"); + g_assert_cmpstr(entry->mount_opts, ==, "mount-opts"); + g_assert_cmpstr(entry->optional_fields, ==, "tag:1"); + g_assert_cmpstr(entry->fs_type, ==, "fs-type"); + g_assert_cmpstr(entry->mount_source, ==, "mount-source"); + g_assert_cmpstr(entry->super_opts, ==, "super-opts"); + g_assert_null(entry->next); +} + +static void test_parse_mountinfo_entry__two_tags() +{ + const char *line = + "1 2 3:4 root mount-dir mount-opts tag:1 tag:2 - fs-type mount-source super-opts"; + struct mountinfo_entry *entry = parse_mountinfo_entry(line); + g_assert_nonnull(entry); + g_test_queue_destroy((GDestroyNotify) free_mountinfo_entry, entry); + g_assert_cmpint(entry->mount_id, ==, 1); + g_assert_cmpint(entry->parent_id, ==, 2); + g_assert_cmpint(entry->dev_major, ==, 3); + g_assert_cmpint(entry->dev_minor, ==, 4); + g_assert_cmpstr(entry->root, ==, "root"); + g_assert_cmpstr(entry->mount_dir, ==, "mount-dir"); + g_assert_cmpstr(entry->mount_opts, ==, "mount-opts"); + g_assert_cmpstr(entry->optional_fields, ==, "tag:1 tag:2"); + g_assert_cmpstr(entry->fs_type, ==, "fs-type"); + g_assert_cmpstr(entry->mount_source, ==, "mount-source"); + g_assert_cmpstr(entry->super_opts, ==, "super-opts"); + g_assert_null(entry->next); +} + +static void test_accessor_funcs() +{ + const char *line = + "256 104 0:3 mnt:[4026532509] /run/snapd/ns/hello-world.mnt rw - nsfs nsfs rw"; + struct mountinfo_entry *entry = parse_mountinfo_entry(line); + g_assert_nonnull(entry); + g_test_queue_destroy((GDestroyNotify) free_mountinfo_entry, entry); + g_assert_cmpint(mountinfo_entry_mount_id(entry), ==, 256); + g_assert_cmpint(mountinfo_entry_parent_id(entry), ==, 104); + g_assert_cmpint(mountinfo_entry_dev_major(entry), ==, 0); + g_assert_cmpint(mountinfo_entry_dev_minor(entry), ==, 3); + + g_assert_cmpstr(mountinfo_entry_root(entry), ==, "mnt:[4026532509]"); + g_assert_cmpstr(mountinfo_entry_mount_dir(entry), ==, + "/run/snapd/ns/hello-world.mnt"); + g_assert_cmpstr(mountinfo_entry_mount_opts(entry), ==, "rw"); + g_assert_cmpstr(mountinfo_entry_optional_fields(entry), ==, ""); + g_assert_cmpstr(mountinfo_entry_fs_type(entry), ==, "nsfs"); + g_assert_cmpstr(mountinfo_entry_mount_source(entry), ==, "nsfs"); + g_assert_cmpstr(mountinfo_entry_super_opts(entry), ==, "rw"); +} + +static void __attribute__ ((constructor)) init() +{ + g_test_add_func("/mountinfo/parse_mountinfo_entry/sysfs", + test_parse_mountinfo_entry__sysfs); + g_test_add_func("/mountinfo/parse_mountinfo_entry/snapd-ns", + test_parse_mountinfo_entry__snapd_ns); + g_test_add_func("/mountinfo/parse_mountinfo_entry/snapd-mnt", + test_parse_mountinfo_entry__snapd_mnt); + g_test_add_func("/mountinfo/parse_mountinfo_entry/garbage", + test_parse_mountinfo_entry__garbage); + g_test_add_func("/mountinfo/parse_mountinfo_entry/no_tags", + test_parse_mountinfo_entry__no_tags); + g_test_add_func("/mountinfo/parse_mountinfo_entry/one_tags", + test_parse_mountinfo_entry__one_tag); + g_test_add_func("/mountinfo/parse_mountinfo_entry/two_tags", + test_parse_mountinfo_entry__two_tags); + g_test_add_func("/mountinfo/accessor_funcs", test_accessor_funcs); +} diff -Nru snap-confine-1.0.38/src/mount-support.c snap-confine-1.0.41/src/mount-support.c --- snap-confine-1.0.38/src/mount-support.c 2016-07-15 13:44:50.000000000 +0000 +++ snap-confine-1.0.41/src/mount-support.c 2016-09-19 09:41:32.000000000 +0000 @@ -17,28 +17,38 @@ #include "config.h" #include "mount-support.h" -#include +#include +#include +#include +#include +#include #include #include -#include +#include #include #include -#include #include -#include -#include -#include -#include +#include +#include -#include "utils.h" -#include "snap.h" #include "classic.h" -#include "mount-support-nvidia.h" #include "cleanup-funcs.h" +#include "mount-support-nvidia.h" +#include "quirks.h" +#include "snap.h" +#include "utils.h" #define MAX_BUF 1000 -void setup_private_mount(const char *security_tag) +/*! + * The void directory. + * + * Snap confine moves to that directory in case it cannot retain the current + * working directory across the pivot_root call. + **/ +#define SC_VOID_DIR "/var/lib/snapd/void" + +static void setup_private_mount(const char *security_tag) { uid_t uid = getuid(); gid_t gid = getgid(); @@ -102,7 +112,7 @@ } } -void setup_private_pts() +static void setup_private_pts() { // See https://www.kernel.org/doc/Documentation/filesystems/devpts.txt // @@ -169,11 +179,71 @@ } } -void setup_snappy_os_mounts() +// Bind mount the snap mount directory. Unlike other directories above the +// location of the mount directory on the host filesystem may not match the +// location in the chroot. In the chroot the directory is always /snap. On +// the host it is SNAP_MOUNT_DIR. +static void sc_bind_mount_snap_mount_dir(const char *rootfs_dir) +{ + const char *src = SNAP_MOUNT_DIR; + char dst[512]; + must_snprintf(dst, sizeof dst, "%s%s", rootfs_dir, SNAP_MOUNT_DIR); + debug("bind mounting %s to %s", src, dst); + if (mount(src, dst, NULL, MS_BIND | MS_REC | MS_SLAVE, NULL) != 0) { + die("cannot bind mount %s to %s", src, dst); + } +} + +// Use pivot_root to "chroot" into a given directory. +// +// Q: Why are we using something as esoteric as pivot_root(2)? +// A: 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(2) 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. +static void sc_pivot_to_new_rootfs(const char *rootfs_dir) +{ + int old_rootfs_fd, new_rootfs_fd; + + old_rootfs_fd = open("/", O_DIRECTORY | O_PATH | O_CLOEXEC); + if (old_rootfs_fd == -1) { + die("cannot open old root file system directory"); + } + new_rootfs_fd = + open(rootfs_dir, O_DIRECTORY | O_PATH | O_NOFOLLOW | O_CLOEXEC); + if (new_rootfs_fd == -1) { + die("cannot open new root file system directory"); + } + if (fchdir(new_rootfs_fd) == -1) { + die("cannot move to new root file system directory"); + } + debug("using pivot_root to move into %s", rootfs_dir); + if (syscall(SYS_pivot_root, ".", ".") == -1) { + die("cannot pivot_root to the new root filesystem"); + } + if (fchdir(old_rootfs_fd) == -1) { + die("cannot move to the old root file system directory"); + } + if (umount2(".", MNT_DETACH) == -1) { + die("cannot detach old root file system directory"); + } + if (fchdir(new_rootfs_fd) == -1) { + die("cannot move to the new root file system directory"); + } + close(old_rootfs_fd); + close(new_rootfs_fd); +} + +static void setup_snappy_os_mounts() { debug("%s", __func__); char rootfs_dir[MAX_BUF] = { 0 }; - // Create a temporary directory that will become the root directory of this +// 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. // @@ -184,7 +254,7 @@ 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"; + const char *core_snap_dir = SNAP_MOUNT_DIR "/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, @@ -197,16 +267,21 @@ "/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 + "/root", // because that is $HOME for services "/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 "/run", // to get /run with sockets and what not +#ifdef MERGED_USR +#else "/media", // access to the users removable devices +#endif // MERGED_USR "/lib/modules", // access to the modules of the running kernel + "/usr/src", // FIXME: move to SecurityMounts in system-trace interface + "/var/log", // FIXME: move to SecurityMounts in log-observe interface }; for (int i = 0; i < sizeof(source_mounts) / sizeof *source_mounts; i++) { const char *src = source_mounts[i]; @@ -225,6 +300,7 @@ die("cannot bind mount %s to %s", src, dst); } } + sc_bind_mount_snap_mount_dir(rootfs_dir); // Since we mounted /etc from the host above, we need to put // /etc/alternatives from the os snap back. // https://bugs.launchpad.net/snap-confine/+bug/1580018 @@ -246,22 +322,7 @@ sc_mkdir_hostfs_if_missing(); sc_bind_mount_hostfs(rootfs_dir); 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"); - } + sc_pivot_to_new_rootfs(rootfs_dir); // 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 @@ -271,22 +332,20 @@ setenv("PATH", "/usr/sbin:/usr/bin:/sbin:/bin:/usr/games", 1); } -void setup_slave_mount_namespace() -{ - // unshare() and CLONE_NEWNS require linux >= 2.6.16 and glibc >= 2.14 - // if using an older glibc, you'd need -D_BSD_SOURCE or -D_SVID_SORUCE. - if (unshare(CLONE_NEWNS) < 0) { - die("unable to set up mount namespace"); - } - // make our "/" a rslave of the real "/". this means that - // mounts from the host "/" get propagated to our namespace - // (i.e. we see new media mounts) - if (mount("none", "/", NULL, MS_REC | MS_SLAVE, NULL) != 0) { - die("can not make make / rslave"); - } -} - -void sc_setup_mount_profiles(const char *security_tag) +/** + * Setup mount profiles as described by snapd. + * + * This function reads /var/lib/snapd/mount/$security_tag.fstab as a fstab(5) file + * and executes the mount requests described there. + * + * Currently only bind mounts are allowed. All bind mounts are read only by + * default though the `rw` flag can be used. + * + * This function is called with the rootfs being "consistent" so that it is + * either the core snap on an all-snap system or the core snap + punched holes + * on a classic system. + **/ +static void sc_setup_mount_profiles(const char *security_tag) { debug("%s: %s", __FUNCTION__, security_tag); @@ -353,9 +412,9 @@ if (offset >= fulllen) return NULL; - while (path[offset] != '\0' && offset < fulllen) + while (offset < fulllen && path[offset] != '\0') offset++; - while (path[offset] == '\0' && offset < fulllen) + while (offset < fulllen && path[offset] == '\0') offset++; *offsetp = offset; @@ -393,3 +452,46 @@ return true; return false; } + +void sc_populate_mount_ns(const char *security_tag) +{ + // Get the current working directory before we start fiddling with + // mounts and possibly pivot_root. At the end of the whole process, we + // will try to re-locate to the same directory (if possible). + char *vanilla_cwd __attribute__ ((cleanup(sc_cleanup_string))) = NULL; + vanilla_cwd = get_current_dir_name(); + if (vanilla_cwd == NULL) { + die("cannot get the current working directory"); + } + // Make our "/" a rslave of the real "/". this means that mounts from the + // host "/" get propagated to our namespace (i.e. we see new media mounts). + if (mount("none", "/", NULL, MS_REC | MS_SLAVE, NULL) != 0) { + die("can not make make / rslave"); + } + // do the mounting if run on a non-native snappy system + if (is_running_on_classic_distribution()) { + setup_snappy_os_mounts(); + } + // set up private mounts + setup_private_mount(security_tag); + + // set up private /dev/pts + setup_private_pts(); + + // setup quirks for specific snaps + sc_setup_quirks(); + + // setup the security backend bind mounts + sc_setup_mount_profiles(security_tag); + + // Try to re-locate back to vanilla working directory. This can fail + // because that directory is no longer present. + if (chdir(vanilla_cwd) != 0) { + debug("cannot remain in %s, moving to the void directory", + vanilla_cwd); + if (chdir(SC_VOID_DIR) != 0) { + die("cannot change directory to %s", SC_VOID_DIR); + } + debug("successfully moved to %s", SC_VOID_DIR); + } +} diff -Nru snap-confine-1.0.38/src/mount-support.h snap-confine-1.0.41/src/mount-support.h --- snap-confine-1.0.38/src/mount-support.h 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/mount-support.h 2016-09-19 09:41:32.000000000 +0000 @@ -18,24 +18,19 @@ #ifndef SNAP_MOUNT_SUPPORT_H #define SNAP_MOUNT_SUPPORT_H -void setup_private_mount(const char *security_tag); -void setup_private_pts(); -void setup_snappy_os_mounts(); -void setup_slave_mount_namespace(); - /** - * Setup mount profiles as described by snapd. - * - * This function reads /var/lib/snapd/mount/$security_tag.fstab as a fstab(5) file - * and executes the mount requests described there. + * Assuming a new mountspace, populate it accordingly. * - * Currently only bind mounts are allowed. All bind mounts are read only by - * default though the `rw` flag can be used. + * This function performs many internal tasks: + * - prepares and chroots into the core snap (on classic systems) + * - creates private /tmp + * - creates private /dev/pts + * - applies quirks for specific snaps (like LXD) + * - processes mount profiles * - * This function is called with the rootfs being "consistent" so that it is - * either the core snap on an all-snap system or the core snap + punched holes - * on a classic system. + * The function will also try to preserve the current working directory but if + * this is impossible it will chdir to SC_VOID_DIR. **/ -void sc_setup_mount_profiles(const char *security_tag); +void sc_populate_mount_ns(const char *security_tag); #endif diff -Nru snap-confine-1.0.38/src/mount-support-nvidia.c snap-confine-1.0.41/src/mount-support-nvidia.c --- snap-confine-1.0.38/src/mount-support-nvidia.c 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/mount-support-nvidia.c 2016-09-19 09:41:32.000000000 +0000 @@ -18,6 +18,7 @@ #include "config.h" #include "mount-support-nvidia.h" +#include #include #include #include @@ -27,8 +28,9 @@ #include #include -#include "utils.h" +#include "classic.h" #include "cleanup-funcs.h" +#include "utils.h" #ifdef NVIDIA_ARCH @@ -187,39 +189,56 @@ #endif // ifdef NVIDIA_ARCH #ifdef NVIDIA_UBUNTU + +struct sc_nvidia_driver { + int major_version; + int minor_version; +}; + +#define SC_NVIDIA_DRIVER_VERSION_FILE "/sys/module/nvidia/version" +#define SC_LIBGL_DIR "/var/lib/snapd/lib/gl" + +static void sc_probe_nvidia_driver(struct sc_nvidia_driver *driver) +{ + FILE *file __attribute__ ((cleanup(sc_cleanup_file))) = NULL; + debug("opening file describing nvidia driver version"); + file = fopen(SC_NVIDIA_DRIVER_VERSION_FILE, "rt"); + if (file == NULL) { + if (errno == ENOENT) { + debug("nvidia driver version file doesn't exist"); + driver->major_version = 0; + driver->minor_version = 0; + return; + } + die("cannot open file describing nvidia driver version"); + } + // Driver version format is MAJOR.MINOR where both MAJOR and MINOR are + // integers. We can use sscanf to parse this data. + if (fscanf + (file, "%d.%d", &driver->major_version, + &driver->minor_version) != 2) { + die("cannot parse nvidia driver version string"); + } + debug("parsed nvidia driver version: %d.%d", driver->major_version, + driver->minor_version); +} + 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:; + struct sc_nvidia_driver driver; + sc_probe_nvidia_driver(&driver); + if (driver.major_version != 0) { // 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; - + char src[PATH_MAX], dst[PATH_MAX]; + must_snprintf(src, sizeof src, "/usr/lib/nvidia-%d", + driver.major_version); + must_snprintf(dst, sizeof dst, "%s%s", rootfs_dir, + SC_LIBGL_DIR); 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); + 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 diff -Nru snap-confine-1.0.38/src/mount-support-nvidia.h snap-confine-1.0.41/src/mount-support-nvidia.h --- snap-confine-1.0.38/src/mount-support-nvidia.h 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/mount-support-nvidia.h 2016-09-19 09:41:32.000000000 +0000 @@ -18,6 +18,31 @@ #ifndef SNAP_CONFINE_MOUNT_SUPPORT_NVIDIA_H #define SNAP_CONFINE_MOUNT_SUPPORT_NVIDIA_H +/** + * Make the Nvidia driver from the classic distribution available in the snap + * execution environment. + * + * This function may be a no-op, depending on build-time configuration options. + * If enabled the behavior differs from one distribution to another because of + * differences in classic packaging and perhaps version of the Nvidia driver. + * This function is designed to be called before pivot_root() switched the root + * filesystem. + * + * On Ubuntu, there are several versions of the binary Nvidia driver. The + * drivers are all installed in /usr/lib/nvidia-$MAJOR_VERSION where + * MAJOR_VERSION is an integer like 304, 331, 340, 346, 352 or 361. The driver + * is located by inspecting /sys/modules/nvidia/version which contains the + * string "$MAJOR_VERSION.$MINOR_VERSION". The appropriate directory is then + * bind mounted to /var/lib/snapd/lib/gl relative relative to the location of + * the root filesystem directory provided as an argument. + * + * On Arch another approach is used. Because the actual driver installs a + * number of shared objects into /usr/lib, they cannot be bind mounted + * directly. Instead a tmpfs is mounted on /var/lib/snapd/lib/gl. The tmpfs is + * subsequently populated with symlinks that point to a number of files in the + * /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); #endif diff -Nru snap-confine-1.0.38/src/ns-support.c snap-confine-1.0.41/src/ns-support.c --- snap-confine-1.0.38/src/ns-support.c 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/ns-support.c 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2016 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 . + * + */ + +#include "ns-support.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_APPARMOR +#include +#endif // ifdef HAVE_APPARMOR + +#include "utils.h" +#include "user-support.h" +#include "mountinfo.h" +#include "cleanup-funcs.h" + +/** + * Flag indicating that a sanity timeout has expired. + **/ +static volatile sig_atomic_t sanity_timeout_expired = 0; + +/** + * Signal handler for SIGALRM that sets sanity_timeout_expired flag to 1. + **/ +static void sc_SIGALRM_handler(int signum) +{ + sanity_timeout_expired = 1; +} + +/** + * Enable a sanity-check timeout. + * + * The timeout is based on good-old alarm(2) and is intended to break a + * suspended system call, such as flock, after a few seconds. The built-in + * timeout is primed for three seconds. After that any sleeping system calls + * are interrupted and a flag is set. + * + * The call should be paired with sc_disable_sanity_check_timeout() that + * disables the alarm and acts on the flag, aborting the process if the timeout + * gets exceeded. + **/ +static void sc_enable_sanity_timeout() +{ + sanity_timeout_expired = 0; + struct sigaction act = {.sa_handler = sc_SIGALRM_handler }; + if (sigemptyset(&act.sa_mask) < 0) { + die("cannot initialize POSIX signal set"); + } + // NOTE: we are using sigaction so that we can explicitly control signal + // flags and *not* pass the SA_RESTART flag. The intent is so that any + // system call we may be sleeping on to get interrupted. + act.sa_flags = 0; + if (sigaction(SIGALRM, &act, NULL) < 0) { + die("cannot install signal handler for SIGALRM"); + } + alarm(3); + debug("sanity timeout initialized and set for three seconds"); +} + +/** + * Disable sanity-check timeout and abort the process if it expired. + * + * This call has to be paired with sc_enable_sanity_timeout(), see the function + * description for more details. + **/ +static void sc_disable_sanity_timeout() +{ + if (sanity_timeout_expired) { + die("sanity timeout expired"); + } + alarm(0); + struct sigaction act = {.sa_handler = SIG_DFL }; + if (sigemptyset(&act.sa_mask) < 0) { + die("cannot initialize POSIX signal set"); + } + if (sigaction(SIGALRM, &act, NULL) < 0) { + die("cannot uninstall signal handler for SIGALRM"); + } + debug("sanity timeout reset and disabled"); +} + +/*! + * The void directory. + * + * Snap confine moves to that directory in case it cannot retain the current + * working directory across the pivot_root call. + **/ +#define SC_VOID_DIR "/var/lib/snapd/void" + +/** + * Directory where snap-confine keeps namespace files. + **/ +#define SC_NS_DIR "/run/snapd/ns" + +/** + * Effective value of SC_NS_DIR. + * + * We use 'const char *' so we can update sc_ns_dir in the testsuite + **/ +static const char *sc_ns_dir = SC_NS_DIR; + +/** + * Name of the lock file associated with SC_NS_DIR. + * and a given group identifier (typically SNAP_NAME). + **/ +#define SC_NS_LOCK_FILE ".lock" + +/** + * Name of the preserved mount namespace associated with SC_NS_DIR + * and a given group identifier (typically SNAP_NAME). + **/ +#define SC_NS_MNT_FILE ".mnt" + +/** + * Read /proc/self/mountinfo and check if /run/snapd/ns is a private bind mount. + * + * We do this because /run/snapd/ns cannot be shared with any other peers as per: + * https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt + **/ +static bool sc_is_ns_group_dir_private() +{ + struct mountinfo *info + __attribute__ ((cleanup(cleanup_mountinfo))) = NULL; + info = parse_mountinfo(NULL); + if (info == NULL) { + die("cannot parse /proc/self/mountinfo"); + } + struct mountinfo_entry *entry = first_mountinfo_entry(info); + while (entry != NULL) { + const char *mount_dir = mountinfo_entry_mount_dir(entry); + const char *optional_fields = + mountinfo_entry_optional_fields(entry); + if (strcmp(mount_dir, sc_ns_dir) == 0 + && strcmp(optional_fields, "") == 0) { + // If /run/snapd/ns has no optional fields, we know it is mounted + // private and there is nothing else to do. + return true; + } + entry = next_mountinfo_entry(entry); + } + return false; +} + +void sc_initialize_ns_groups() +{ + debug("creating namespace group directory %s", sc_ns_dir); + mkpath(sc_ns_dir); + debug("opening namespace group directory %s", sc_ns_dir); + int dir_fd __attribute__ ((cleanup(sc_cleanup_close))) = -1; + dir_fd = open(sc_ns_dir, O_DIRECTORY | O_PATH | O_CLOEXEC | O_NOFOLLOW); + if (dir_fd < 0) { + die("cannot open namespace group directory"); + } + debug("opening lock file for group directory"); + int lock_fd __attribute__ ((cleanup(sc_cleanup_close))) = -1; + lock_fd = openat(dir_fd, + SC_NS_LOCK_FILE, + O_CREAT | O_RDWR | O_CLOEXEC | O_NOFOLLOW, 0600); + if (lock_fd < 0) { + die("cannot open lock file for namespace group directory"); + } + debug("locking the namespace group directory"); + sc_enable_sanity_timeout(); + if (flock(lock_fd, LOCK_EX) < 0) { + die("cannot acquire exclusive lock for namespace group directory"); + } + sc_disable_sanity_timeout(); + if (!sc_is_ns_group_dir_private()) { + debug + ("bind mounting the namespace group directory over itself"); + if (mount(sc_ns_dir, sc_ns_dir, NULL, MS_BIND | MS_REC, NULL) < + 0) { + die("cannot bind mount namespace group directory over itself"); + } + debug + ("making the namespace group directory mount point private"); + if (mount(NULL, sc_ns_dir, NULL, MS_PRIVATE, NULL) < 0) { + die("cannot make the namespace group directory mount point private"); + } + } else { + debug + ("namespace group directory does not require intialization"); + } + debug("unlocking the namespace group directory"); + if (flock(lock_fd, LOCK_UN) < 0) { + die("cannot release lock for namespace control directory"); + } +} + +struct sc_ns_group { + // Name of the namespace group ($SNAP_NAME). + char *name; + // Descriptor to the namespace group control directory. This descriptor is + // opened with O_PATH|O_DIRECTORY so it's only used for openat() calls. + int dir_fd; + // Descriptor to a namespace-specific lock file (i.e. $SNAP_NAME.lock). + int lock_fd; + // Descriptor to an eventfd that is used to notify the child that it can + // now complete its job and exit. + int event_fd; + // Identifier of the child process that is used during the one-time (per + // group) initialization and capture process. + pid_t child; + // Flag set when this process created a fresh namespace should populate it. + bool should_populate; +}; + +static struct sc_ns_group *sc_alloc_ns_group() +{ + struct sc_ns_group *group = calloc(1, sizeof *group); + if (group == NULL) { + die("cannot allocate memory for namespace group"); + } + group->dir_fd = -1; + group->lock_fd = -1; + group->event_fd = -1; + // Redundant with calloc but some functions check for the non-zero value so + // I'd like to keep this explicit in the code. + group->child = 0; + return group; +} + +struct sc_ns_group *sc_open_ns_group(const char *group_name) +{ + struct sc_ns_group *group = sc_alloc_ns_group(); + debug("opening namespace group directory %s", sc_ns_dir); + group->dir_fd = + open(sc_ns_dir, O_DIRECTORY | O_PATH | O_CLOEXEC | O_NOFOLLOW); + if (group->dir_fd < 0) { + die("cannot open directory for namespace group %s", group_name); + } + char lock_fname[PATH_MAX]; + must_snprintf(lock_fname, sizeof lock_fname, "%s%s", group_name, + SC_NS_LOCK_FILE); + debug("opening lock file for namespace group %s", group_name); + group->lock_fd = + openat(group->dir_fd, lock_fname, + O_CREAT | O_RDWR | O_CLOEXEC | O_NOFOLLOW, 0600); + if (group->lock_fd < 0) { + die("cannot open lock file for namespace group %s", group_name); + } + group->name = strdup(group_name); + if (group->name == NULL) { + die("cannot duplicate namespace group name %s", group_name); + } + return group; +} + +void sc_close_ns_group(struct sc_ns_group *group) +{ + debug("releasing resources associated wih namespace group %s", + group->name); + close(group->dir_fd); + close(group->lock_fd); + close(group->event_fd); + free(group->name); + free(group); +} + +void sc_lock_ns_mutex(struct sc_ns_group *group) +{ + if (group->lock_fd < 0) { + die("precondition failed: we don't have an open file descriptor for the mutex file"); + } + debug("acquiring exclusive lock for namespace group %s", group->name); + sc_enable_sanity_timeout(); + if (flock(group->lock_fd, LOCK_EX) < 0) { + die("cannot acquire exclusive lock for namespace group %s", + group->name); + } + sc_disable_sanity_timeout(); + debug("acquired exclusive lock for namespace group %s", group->name); +} + +void sc_unlock_ns_mutex(struct sc_ns_group *group) +{ + if (group->lock_fd < 0) { + die("precondition failed: we don't have an open file descriptor for the mutex file"); + } + debug("releasing lock for namespace group %s", group->name); + if (flock(group->lock_fd, LOCK_UN) < 0) { + die("cannot release lock for namespace group %s", group->name); + } + debug("released lock for namespace group %s", group->name); +} + +void sc_create_or_join_ns_group(struct sc_ns_group *group) +{ + // Open the mount namespace file. + char mnt_fname[PATH_MAX]; + must_snprintf(mnt_fname, sizeof mnt_fname, "%s%s", group->name, + SC_NS_MNT_FILE); + int mnt_fd __attribute__ ((cleanup(sc_cleanup_close))) = -1; + // NOTE: There is no O_EXCL here because the file can be around but + // doesn't have to be a mounted namespace. + // + // If the mounted namespace is discarded with + // sc_discard_preserved_ns_group() it will revert to a regular file. If + // snap-confine is killed for whatever reason after the file is created but + // before the file is bind-mounted it will also be a regular file. + mnt_fd = + openat(group->dir_fd, mnt_fname, + O_CREAT | O_RDONLY | O_CLOEXEC | O_NOFOLLOW, 0600); + if (mnt_fd < 0) { + die("cannot open mount namespace file for namespace group %s", + group->name); + } + // Check if we got an nsfs-based file or a regular file. This can be + // reliably tested because nsfs has an unique filesystem type NSFS_MAGIC. + // We can just ensure that this is the case thanks to fstatfs. + struct statfs buf; + if (fstatfs(mnt_fd, &buf) < 0) { + die("cannot perform fstatfs() on an mount namespace file descriptor"); + } + if (buf.f_type == NSFS_MAGIC) { + char *vanilla_cwd __attribute__ ((cleanup(sc_cleanup_string))) = + NULL; + vanilla_cwd = get_current_dir_name(); + if (vanilla_cwd == NULL) { + die("cannot get the current working directory"); + } + debug + ("attempting to re-associate the mount namespace with the namespace group %s", + group->name); + if (setns(mnt_fd, CLONE_NEWNS) < 0) { + die("cannot re-associate the mount namespace with namespace group %s", group->name); + } + debug + ("successfully re-associated the mount namespace with the namespace group %s", + group->name); + // Try to re-locate back to vanilla working directory. This can fail + // because that directory is no longer present. + if (chdir(vanilla_cwd) != 0) { + debug + ("cannot remain in %s, moving to the void directory", + vanilla_cwd); + if (chdir(SC_VOID_DIR) != 0) { + die("cannot change directory to %s", + SC_VOID_DIR); + } + debug("successfully moved to %s", SC_VOID_DIR); + } + return; + } + debug("initializing new namespace group %s", group->name); + // Create a new namespace and ask the caller to populate it. + // For rationale of forking see this: + // https://lists.linuxfoundation.org/pipermail/containers/2013-August/033386.html + // + // The eventfd created here is used to synchronize the child and the parent + // processes. It effectively tells the child to perform the capture + // operation. + group->event_fd = eventfd(0, EFD_CLOEXEC); + if (group->event_fd < 0) { + die("cannot create eventfd for mount namespace capture"); + } + debug("forking support process for mount namespace capture"); + // Store the PID of the "parent" process. This done instead of calls to + // getppid() because then we can reliably track the PID of the parent even + // if the child process is re-parented. + pid_t parent = getpid(); + // Glibc defines pid as a signed 32bit integer. There's no standard way to + // print pid's portably so this is the best we can do. + pid_t pid = fork(); + debug("forked support process has pid %d", (int)pid); + if (pid < 0) { + die("cannot fork support process for mount namespace capture"); + } + if (pid == 0) { + // This is the child process which will capture the mount namespace. + // + // It will do so by bind-mounting the SC_NS_MNT_FILE after the parent + // process calls unshare() and finishes setting up the namespace + // completely. +#ifdef HAVE_APPARMOR + // Change the hat to a sub-profile that has limited permissions + // necessary to accomplish the capture of the mount namespace. + debug + ("changing apparmor hat of the support process for mount namespace capture"); + if (aa_change_hat("mount-namespace-capture-helper", 0) < 0) { + die("cannot change apparmor hat of the support process for mount namespace capture"); + } +#endif + // Configure the child to die as soon as the parent dies. In an odd + // case where the parent is killed then we don't want to complete our + // task or wait for anything. + if (prctl(PR_SET_PDEATHSIG, SIGINT, 0, 0, 0) < 0) { + die("cannot set parent process death notification signal to SIGINT"); + } + // Check that parent process is still alive. If this is the case then + // we can *almost* reliably rely on the PR_SET_PDEATHSIG signal to wake + // us up from eventfd_read() below. In the rare case that the PID numbers + // overflow and the now-dead parent PID is recycled we will still hang + // forever on the read from eventfd below. + debug("ensuring that parent process is still alive"); + if (kill(parent, 0) < 0) { + switch (errno) { + case ESRCH: + debug("parent process has already terminated"); + abort(); + default: + die("cannot ensure that parent process is still alive"); + break; + } + } + if (fchdir(group->dir_fd) < 0) { + die("cannot move process for mount namespace capture to namespace group directory"); + } + debug + ("waiting for a eventfd data from the parent process to continue"); + eventfd_t value = 0; + sc_enable_sanity_timeout(); + if (eventfd_read(group->event_fd, &value) < 0) { + die("cannot read expected data from eventfd"); + } + sc_disable_sanity_timeout(); + debug + ("capturing mount namespace of process %d in namespace group %s", + (int)parent, group->name); + char src[PATH_MAX]; + char dst[PATH_MAX]; + must_snprintf(src, sizeof src, "/proc/%d/ns/mnt", (int)parent); + must_snprintf(dst, sizeof dst, "%s%s", group->name, + SC_NS_MNT_FILE); + if (mount(src, dst, NULL, MS_BIND, NULL) < 0) { + die("cannot bind-mount the mount namespace file %s -> %s", src, dst); + } + debug + ("successfully captured mount namespace in namespace group %s", + group->name); + exit(0); + } else { + group->child = pid; + // Unshare the mount namespace and set a flag instructing the caller that + // the namespace is pristine and needs to be populated now. + debug("unsharing the mount namespace"); + if (unshare(CLONE_NEWNS) < 0) { + die("cannot unshare the mount namespace"); + } + group->should_populate = true; + } +} + +bool sc_should_populate_ns_group(struct sc_ns_group *group) +{ + return group->should_populate; +} + +void sc_preserve_populated_ns_group(struct sc_ns_group *group) +{ + if (group->child == 0) { + die("precondition failed: we don't have a support process for mount namespace capture"); + } + if (group->event_fd < 0) { + die("precondition failed: we don't have an eventfd for mount namespace capture"); + } + debug + ("asking support process for mount namespace capture (pid: %d) to perform the capture", + group->child); + if (eventfd_write(group->event_fd, 1) < 0) { + die("cannot write eventfd"); + } + debug + ("waiting for the support process for mount namespace capture to exit"); + int status = 0; + errno = 0; + if (waitpid(group->child, &status, 0) < 0) { + die("cannot wait for the support process for mount namespace capture"); + } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + die("support process for mount namespace capture exited abnormally"); + } + debug("support process for mount namespace capture exited normally"); + group->child = 0; +} + +void sc_discard_preserved_ns_group(struct sc_ns_group *group) +{ + // Remember the current working directory + int old_dir_fd __attribute__ ((cleanup(sc_cleanup_close))) = -1; + old_dir_fd = open(".", O_PATH | O_DIRECTORY | O_CLOEXEC); + if (old_dir_fd < 0) { + die("cannot open current directory"); + } + // Move to the mount namespace directory (/run/snapd/ns) + if (fchdir(group->dir_fd) < 0) { + die("cannot move to namespace group directory"); + } + // Unmount ${group_name}.mnt which holds the preserved namespace + char mnt_fname[PATH_MAX]; + must_snprintf(mnt_fname, sizeof mnt_fname, "%s%s", group->name, + SC_NS_MNT_FILE); + debug("unmounting preserved mount namespace file %s", mnt_fname); + if (umount2(mnt_fname, UMOUNT_NOFOLLOW) < 0) { + // EINVAL is returned when there's nothing to unmount (no bind-mount). + // Instead of checking for this explicitly (which is always racy) we + // just unmount and check the return code. + if (errno != EINVAL) { + die("cannot unmount preserved mount namespace file %s", + mnt_fname); + } + } + // Get back to the original directory + if (fchdir(old_dir_fd) < 0) { + die("cannot move back to original directory"); + } +} diff -Nru snap-confine-1.0.38/src/ns-support.h snap-confine-1.0.41/src/ns-support.h --- snap-confine-1.0.38/src/ns-support.h 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/ns-support.h 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2016 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 . + * + */ + +#ifndef SNAP_NAMESPACE_SUPPORT +#define SNAP_NAMESPACE_SUPPORT + +#include + +/** + * Initialize namespace sharing. + * + * This function must be called once in each process that wishes to create or + * join a namespace group. + * + * It is responsible for bind mounting the control directory over itself and + * making it private (unsharing it with all the other peers) so that it can be + * used for storing preserved namespaces as bind-mounted files from the nsfs + * filesystem (namespace filesystem). + * + * This function acquires a flock(2)-based lock to ensure that no other instance + * of snap-confine attempts to do this concurrently. If a process dies for any + * reason then the lock is released and other instances of snap-confine can + * complete the initialization. + * + * This function inspects /proc/self/mountinfo to determine if the directory + * where namespaces are kept (/run/snapd/ns) is correctly prepared as described + * above. + * + * For more details see namespaces(7). + **/ +void sc_initialize_ns_groups(); + +/** + * Data required to manage namespaces amongst a group of processes. + */ +struct sc_ns_group; + +/** + * Open a namespace group. + * + * This will open and keep file descriptors for /run/snapd/ns/ as well as for + * /run/snapd/ns/${group_name}.lock. The lock file is created if necessary but + * is not locked until sc_lock_ns_mutex() is called. + */ +struct sc_ns_group *sc_open_ns_group(const char *group_name); + +/** + * Close namespace group. + * + * This will close all of the open file descriptors and release allocated memory. + */ +void sc_close_ns_group(struct sc_ns_group *group); + +/** + * Acquire exclusive lock to the namespace group. + * + * This will attempt to acquire an flock-based exclusive lock on the file + * descriptor associated with /run/snapd/ns/${group_name}.lock. If the process + * is killed while the lock is held the lock is automatically released by the + * kernel. + * + * The following methods should be called only while holding the lock: + * - sc_create_or_join_ns_group() + * - sc_should_populate_ns_group() + * - sc_preserve_populated_ns_group() + * - sc_discard_preserved_ns_group() + **/ +void sc_lock_ns_mutex(struct sc_ns_group *group); + +/** + * Release lock to the namespace group. + * + * This will attempt to release a flock-based lock on the file descriptor + * associated with /run/snapd/ns/${group_name}.lock. + **/ +void sc_unlock_ns_mutex(struct sc_ns_group *group); + +/** + * Join the mount namespace associated with this group if one exists. + * + * Technically the function opens /run/snapd/ns/${group_name}.mnt and tries to + * use setns() with the obtained file descriptor. If the call succeeds then the + * function returns and subsequent call to sc_should_populate_ns_group() will + * return false. + * + * If the call fails then an eventfd is constructed and a support process is + * forked. The child process waits until data is written to the eventfd (this + * can be done by calling sc_preserve_populated_ns_group()). In the meantime + * the parent process unshares the mount namespace and sets a flag so that + * sc_should_populate_ns_group() returns true. + * + * @returns true if the mount namespace needs to be populated + **/ +void sc_create_or_join_ns_group(struct sc_ns_group *group); + +/** + * Check if the namespace needs to be populated. + * + * If the return value is true then at this stage the namespace is already + * unshared. The caller should perform any mount operations that are desired + * and then proceed to call sc_preserve_populated_ns_group(). + **/ +bool sc_should_populate_ns_group(struct sc_ns_group *group); + +/** + * Preserve prepared namespace group. + * + * This function signals the child support process for namespace capture to + * perform the capture and shut down. It must be called after the call to + * sc_create_or_join_ns_group() and only when sc_should_populate_ns_group() + * returns true. + * + * Technically this function writes to an eventfd that causes the child process + * to wake up, bind mount /proc/$ppid/ns/mnt to /run/snapd/ns/${group_name}.mnt + * and then exit. The parent process (the caller) then collects the child + * process and returns. + **/ +void sc_preserve_populated_ns_group(struct sc_ns_group *group); + +/** + * Discard the preserved namespace group. + * + * This function unmounts the bind-mounted files representing the kernel mount + * namespace. + **/ +void sc_discard_preserved_ns_group(struct sc_ns_group *group); + +#endif diff -Nru snap-confine-1.0.38/src/ns-support-test.c snap-confine-1.0.41/src/ns-support-test.c --- snap-confine-1.0.38/src/ns-support-test.c 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/ns-support-test.c 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2016 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 . + * + */ + +#include "ns-support.h" +#include "ns-support.c" + +#include "cleanup-funcs.h" + +#include +#include // for NSFS_MAGIC +#include + +#include +#include + +// Set alternate namespace directory +static void sc_set_ns_dir(const char *dir) +{ + sc_ns_dir = dir; +} + +// Shell-out to "rm -rf -- $dir" as long as $dir is in /tmp. +static void rm_rf_tmp(const char *dir) +{ + // Sanity check, don't remove anything that's not in the temporary + // directory. This is here to prevent unintended data loss. + if (!g_str_has_prefix(dir, "/tmp/")) + die("refusing to remove: %s", dir); + const gchar *working_directory = NULL; + gchar **argv = NULL; + gchar **envp = NULL; + GSpawnFlags flags = G_SPAWN_SEARCH_PATH; + GSpawnChildSetupFunc child_setup = NULL; + gpointer user_data = NULL; + gchar **standard_output = NULL; + gchar **standard_error = NULL; + gint exit_status = 0; + GError *error = NULL; + + argv = calloc(5, sizeof *argv); + if (argv == NULL) + die("cannot allocate command argument array"); + argv[0] = g_strdup("rm"); + if (argv[0] == NULL) + die("cannot allocate memory"); + argv[1] = g_strdup("-rf"); + if (argv[1] == NULL) + die("cannot allocate memory"); + argv[2] = g_strdup("--"); + if (argv[2] == NULL) + die("cannot allocate memory"); + argv[3] = g_strdup(dir); + if (argv[3] == NULL) + die("cannot allocate memory"); + argv[4] = NULL; + g_assert_true(g_spawn_sync + (working_directory, argv, envp, flags, child_setup, + user_data, standard_output, standard_error, &exit_status, + &error)); + g_assert_true(g_spawn_check_exit_status(exit_status, NULL)); + if (error != NULL) { + g_test_message("cannot remove temporary directory: %s\n", + error->message); + g_error_free(error); + } + g_free(argv[0]); + g_free(argv[1]); + g_free(argv[2]); + g_free(argv[3]); + g_free(argv); +} + +// Check that rm_rf_tmp doesn't remove things outside of /tmp +static void test_rm_rf_tmp() +{ + if (access("/nonexistent", F_OK) == 0) { + g_test_message + ("/nonexistent exists but this test doesn't want it to"); + g_test_fail(); + return; + } + if (g_test_subprocess()) { + rm_rf_tmp("/nonexistent"); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); +} + +// Use temporary directory for namespace groups. +// +// The directory is automatically reset to the real value at the end of the +// test. +static const char *sc_test_use_fake_ns_dir() +{ + char *ns_dir = NULL; + if (g_test_subprocess()) { + // Check if the environment variable is set. If so then someone is already + // managing the temporary directory and we should not create a new one. + ns_dir = getenv("SNAP_CONFINE_NS_DIR"); + g_assert_nonnull(ns_dir); + } else { + ns_dir = g_dir_make_tmp(NULL, NULL); + g_assert_nonnull(ns_dir); + g_test_queue_free(ns_dir); + g_assert_cmpint(setenv("SNAP_CONFINE_NS_DIR", ns_dir, 0), ==, + 0); + g_test_queue_destroy((GDestroyNotify) unsetenv, + "SNAP_CONFINE_NS_DIR"); + g_test_queue_destroy((GDestroyNotify) rm_rf_tmp, ns_dir); + } + g_test_queue_destroy((GDestroyNotify) sc_set_ns_dir, SC_NS_DIR); + sc_set_ns_dir(ns_dir); + return ns_dir; +} + +// Check that allocating a namespace group sets up internal data structures to +// safe values. +static void test_sc_alloc_ns_group() +{ + struct sc_ns_group *group = NULL; + group = sc_alloc_ns_group(); + g_test_queue_free(group); + g_assert_nonnull(group); + g_assert_cmpint(group->dir_fd, ==, -1); + g_assert_cmpint(group->lock_fd, ==, -1); + g_assert_cmpint(group->event_fd, ==, -1); + g_assert_cmpint(group->child, ==, 0); + g_assert_cmpint(group->should_populate, ==, false); + g_assert_null(group->name); +} + +// Initialize a namespace group. +// +// The group is automatically destroyed at the end of the test. +static struct sc_ns_group *sc_test_open_ns_group(const char *group_name) +{ + // Initialize a namespace group + struct sc_ns_group *group = NULL; + if (group_name == NULL) { + group_name = "test-group"; + } + group = sc_open_ns_group(group_name); + g_test_queue_destroy((GDestroyNotify) sc_close_ns_group, group); + // Check if the returned group data looks okay + g_assert_nonnull(group); + g_assert_cmpint(group->dir_fd, !=, -1); + g_assert_cmpint(group->lock_fd, !=, -1); + g_assert_cmpint(group->event_fd, ==, -1); + g_assert_cmpint(group->child, ==, 0); + g_assert_cmpint(group->should_populate, ==, false); + g_assert_cmpstr(group->name, ==, group_name); + return group; +} + +// Check that initializing a namespace group creates the appropriate +// filesystem structure and obtains open file descriptors for the lock. +static void test_sc_open_ns_group() +{ + const char *ns_dir = sc_test_use_fake_ns_dir(); + struct sc_ns_group *group = sc_test_open_ns_group(NULL); + // Check that the group directory exists + g_assert_true(g_file_test + (ns_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)); + // Check that the lock file exists + char *lock_file __attribute__ ((cleanup(sc_cleanup_string))) = NULL; + lock_file = + g_strdup_printf("%s/%s%s", ns_dir, group->name, SC_NS_LOCK_FILE); + g_assert_true(g_file_test + (lock_file, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)); +} + +static void test_sc_lock_ns_mutex_precondition() +{ + sc_test_use_fake_ns_dir(); + if (g_test_subprocess()) { + struct sc_ns_group *group = sc_alloc_ns_group(); + g_test_queue_free(group); + // Try to lock the mutex, this should abort because we never opened the + // lock file and don't have a valid file descriptor. + sc_lock_ns_mutex(group); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); +} + +static void test_sc_unlock_ns_mutex_precondition() +{ + sc_test_use_fake_ns_dir(); + if (g_test_subprocess()) { + struct sc_ns_group *group = sc_alloc_ns_group(); + g_test_queue_free(group); + // Try to unlock the mutex, this should abort because we never opened the + // lock file and don't have a valid file descriptor. + sc_unlock_ns_mutex(group); + return; + } + g_test_trap_subprocess(NULL, 0, 0); + g_test_trap_assert_failed(); +} + +// Check that locking a namespace actually flock's the mutex with LOCK_EX +static void test_sc_lock_unlock_ns_mutex() +{ + const char *ns_dir = sc_test_use_fake_ns_dir(); + struct sc_ns_group *group = sc_test_open_ns_group(NULL); + // Lock the namespace group mutex + sc_lock_ns_mutex(group); + // Construct the name of the lock file + char *lock_file __attribute__ ((cleanup(sc_cleanup_string))) = NULL; + lock_file = + g_strdup_printf("%s/%s%s", ns_dir, group->name, SC_NS_LOCK_FILE); + // Open the lock file again to obtain a separate file descriptor. + // According to flock(2) locks are associated with an open file table entry + // so this descriptor will be separate and can compete for the same lock. + int lock_fd __attribute__ ((cleanup(sc_cleanup_close))) = -1; + lock_fd = open(lock_file, O_RDWR | O_CLOEXEC | O_NOFOLLOW); + g_assert_cmpint(lock_fd, !=, -1); + // The non-blocking lock operation should fail with EWOULDBLOCK as the lock + // file is locked by sc_nlock_ns_mutex() already. + int err = flock(lock_fd, LOCK_EX | LOCK_NB); + int saved_errno = errno; + g_assert_cmpint(err, ==, -1); + g_assert_cmpint(saved_errno, ==, EWOULDBLOCK); + // Unlock the namespace group mutex + sc_unlock_ns_mutex(group); + // Re-attempt the locking operation. This time it should succeed. + err = flock(lock_fd, LOCK_EX | LOCK_NB); + g_assert_cmpint(err, ==, 0); +} + +static void unmount_dir(void *dir) +{ + umount(dir); +} + +static void test_sc_is_ns_group_dir_private() +{ + if (geteuid() != 0) { + g_test_skip("this test needs to run as root"); + return; + } + const char *ns_dir = sc_test_use_fake_ns_dir(); + g_test_queue_destroy(unmount_dir, (char *)ns_dir); + + if (g_test_subprocess()) { + // The temporary directory should not be private initially + g_assert_false(sc_is_ns_group_dir_private()); + + /// do what "mount --bind /foo /foo; mount --make-private /foo" does. + int err; + err = mount(ns_dir, ns_dir, NULL, MS_BIND, NULL); + g_assert_cmpint(err, ==, 0); + err = mount(NULL, ns_dir, NULL, MS_PRIVATE, NULL); + g_assert_cmpint(err, ==, 0); + + // The temporary directory should now be private + g_assert_true(sc_is_ns_group_dir_private()); + return; + } + g_test_trap_subprocess(NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDERR); + g_test_trap_assert_passed(); +} + +static void test_sc_initialize_ns_groups() +{ + if (geteuid() != 0) { + g_test_skip("this test needs to run as root"); + return; + } + // NOTE: this is g_test_subprocess aware! + const char *ns_dir = sc_test_use_fake_ns_dir(); + g_test_queue_destroy(unmount_dir, (char *)ns_dir); + if (g_test_subprocess()) { + // Initialize namespace groups using a fake directory. + sc_initialize_ns_groups(); + + // Check that the fake directory is now a private mount. + g_assert_true(sc_is_ns_group_dir_private()); + + // Check that the lock file did not leak unclosed. + + // Construct the name of the lock file + char *lock_file __attribute__ ((cleanup(sc_cleanup_string))) = + NULL; + lock_file = + g_strdup_printf("%s/%s", sc_ns_dir, SC_NS_LOCK_FILE); + // Attempt to open and lock the lock file. + int lock_fd __attribute__ ((cleanup(sc_cleanup_close))) = -1; + lock_fd = open(lock_file, O_RDWR | O_CLOEXEC | O_NOFOLLOW); + g_assert_cmpint(lock_fd, !=, -1); + // The non-blocking lock operation should not fail + int err = flock(lock_fd, LOCK_EX | LOCK_NB); + g_assert_cmpint(err, ==, 0); + return; + } + g_test_trap_subprocess(NULL, 0, G_TEST_SUBPROCESS_INHERIT_STDERR); + g_test_trap_assert_passed(); +} + +// Sanity check, ensure that the namespace filesystem identifier is what we +// expect, aka NSFS_MAGIC. +static void test_nsfs_fs_id() +{ + struct statfs buf; + int err = statfs("/proc/self/ns/mnt", &buf); + g_assert_cmpint(err, ==, 0); + g_assert_cmpint(buf.f_type, ==, NSFS_MAGIC); +} + +static void test_sc_enable_sanity_timeout() +{ + if (g_test_subprocess()) { + sc_enable_sanity_timeout(); + debug("waiting..."); + usleep(4 * G_USEC_PER_SEC); + debug("woke up"); + sc_disable_sanity_timeout(); + return; + } + g_test_trap_subprocess(NULL, 5 * G_USEC_PER_SEC, + G_TEST_SUBPROCESS_INHERIT_STDERR); + g_test_trap_assert_failed(); +} + +static void __attribute__ ((constructor)) init() +{ + g_test_add_func("/internal/rm_rf_tmp", test_rm_rf_tmp); + g_test_add_func("/ns/sc_enable_sanity_timeout", + test_sc_enable_sanity_timeout); + g_test_add_func("/ns/sc_alloc_ns_group", test_sc_alloc_ns_group); + g_test_add_func("/ns/sc_init_ns_group", test_sc_open_ns_group); + g_test_add_func("/ns/sc_lock_unlock_ns_mutex", + test_sc_lock_unlock_ns_mutex); + g_test_add_func("/ns/sc_lock_ns_mutex/precondition", + test_sc_lock_ns_mutex_precondition); + g_test_add_func("/ns/sc_unlock_ns_mutex/precondition", + test_sc_unlock_ns_mutex_precondition); + g_test_add_func("/ns/nsfs_fs_id", test_nsfs_fs_id); + g_test_add_func("/system/ns/sc_is_ns_group_dir_private", + test_sc_is_ns_group_dir_private); + g_test_add_func("/system/ns/sc_initialize_ns_groups", + test_sc_initialize_ns_groups); +} diff -Nru snap-confine-1.0.38/src/quirks.c snap-confine-1.0.41/src/quirks.c --- snap-confine-1.0.38/src/quirks.c 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/quirks.c 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2016 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 . + * + */ +#include "config.h" +#include "quirks.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "cleanup-funcs.h" +#include "classic.h" +// XXX: for smaller patch, this should be in utils.h later +#include "user-support.h" + +/** + * Mount a tmpfs at a given directory. + * + * The empty tmpfs is used as a substrate to create additional directories and + * then bind mounts to other destinations. + * + * It is useful to poke unexpected holes in the read-only core snap. + **/ +static void sc_quirk_setup_tmpfs(const char *dirname) +{ + debug("mounting tmpfs at %s", dirname); + if (mount("none", dirname, "tmpfs", MS_NODEV | MS_NOSUID, NULL) != 0) { + die("cannot mount tmpfs at %s", dirname); + }; +} + +/** + * Create an empty directory and bind mount something there. + * + * The empty directory is created at destdir. The bind mount is + * done from srcdir to destdir. The bind mount is performed with + * caller-defined flags. + **/ +static void sc_quirk_mkdir_bind(const char *src_dir, const char *dest_dir, + unsigned flags) +{ + flags |= MS_BIND; + debug("creating empty directory at %s", dest_dir); + mkpath(dest_dir); + debug("bind mounting %s -> %s with flags %#x", src_dir, dest_dir, + flags); + if (mount(src_dir, dest_dir, NULL, flags, NULL) != 0) { + die("cannot bind mount %s -> %s with flags %#x", src_dir, + dest_dir, flags); + } +} + +/** + * Create a writable mimic directory based on reference directory. + * + * The mimic directory is a tmpfs populated with bind mounts to the (possibly + * read only) directories in the reference directory. While all the read-only + * content stays read-only the actual mimic directory is writable so additional + * content can be placed there. + * + * Flags are forwarded to sc_quirk_mkdir_bind() + **/ +static void sc_quirk_create_writable_mimic(const char *mimic_dir, + const char *ref_dir, unsigned flags) +{ + debug("creating writable mimic directory %s based on %s", mimic_dir, + ref_dir); + sc_quirk_setup_tmpfs(mimic_dir); + debug("bind-mounting all the files from the reference directory"); + DIR *dirp __attribute__ ((cleanup(sc_cleanup_closedir))) = NULL; + dirp = opendir(ref_dir); + if (dirp == NULL) { + die("cannot open reference directory %s", ref_dir); + } + struct dirent *entryp = NULL; + do { + char src_name[PATH_MAX * 2]; + char dest_name[PATH_MAX * 2]; + // Set errno to zero, if readdir fails it will not only return null but + // set errno to a non-zero value. This is how we can differentiate + // end-of-directory from an actual error. + errno = 0; + entryp = readdir(dirp); + if (entryp == NULL && errno != 0) { + die("cannot read another directory entry"); + } + if (entryp == NULL) { + break; + } + if (strcmp(entryp->d_name, ".") == 0 + || strcmp(entryp->d_name, "..") == 0) { + continue; + } + if (entryp->d_type != DT_DIR && entryp->d_type != DT_REG) { + die("unsupported entry type of file %s (%d)", + entryp->d_name, entryp->d_type); + } + must_snprintf(src_name, sizeof src_name, "%s/%s", ref_dir, + entryp->d_name); + must_snprintf(dest_name, sizeof dest_name, "%s/%s", mimic_dir, + entryp->d_name); + sc_quirk_mkdir_bind(src_name, dest_name, flags); + } while (entryp != NULL); +} + +/** + * Setup a quirk for LXD. + * + * An existing LXD snap relies on pre-chroot behavior to access /var/lib/lxd + * while in devmode. Since that directory doesn't exist in the core snap the + * quirk punches a custom hole so that this directory shows the hostfs content + * if such directory exists on the host. + * + * See: https://bugs.launchpad.net/snap-confine/+bug/1613845 + **/ +static void sc_setup_lxd_quirk() +{ + const char *hostfs_lxd_dir = SC_HOSTFS_DIR "/var/lib/lxd"; + if (access(hostfs_lxd_dir, F_OK) == 0) { + const char *lxd_dir = "/var/lib/lxd"; + debug("setting up quirk for LXD (see LP: #1613845)"); + sc_quirk_mkdir_bind(hostfs_lxd_dir, lxd_dir, + MS_REC | MS_SLAVE | MS_NODEV | MS_NOSUID | + MS_NOEXEC); + } +} + +void sc_setup_quirks() +{ + // because /var/lib/snapd is essential let's move it to /tmp/snapd for a sec + char snapd_tmp[] = "/tmp/snapd.quirks_XXXXXX"; + if (mkdtemp(snapd_tmp) == 0) { + die("cannot create temporary directory for /var/lib/snapd mount point"); + } + if (mount("/var/lib/snapd", snapd_tmp, NULL, MS_MOVE, NULL) + != 0) { + die("cannot move /var/lib/snapd to %s", snapd_tmp); + } + // now let's make /var/lib the vanilla /var/lib from the core snap + sc_quirk_create_writable_mimic("/var/lib", + "/snap/ubuntu-core/current/var/lib", + MS_RDONLY | MS_REC | MS_SLAVE | MS_NODEV + | MS_NOSUID); + // now let's move /var/lib/snapd (that was originally there) back + if (umount("/var/lib/snapd") != 0) { + die("cannot unmount /var/lib/snapd"); + } + if (mount(snapd_tmp, "/var/lib/snapd", NULL, MS_MOVE, NULL) + != 0) { + die("cannot move %s to /var/lib/snapd", snapd_tmp); + } + if (rmdir(snapd_tmp) != 0) { + die("cannot remove %s", snapd_tmp); + } + // We are now ready to apply any quirks that relate to /var/lib + sc_setup_lxd_quirk(); +} diff -Nru snap-confine-1.0.38/src/quirks.h snap-confine-1.0.41/src/quirks.h --- snap-confine-1.0.38/src/quirks.h 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/quirks.h 2016-09-09 11:11:21.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 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 . + * + */ + +#ifndef SNAP_QUIRKS_H +#define SNAP_QUIRKS_H + +/** + * Setup various quirks that have to exists for now. + * + * This function applies non-standard tweaks that are required + * because of requirement to stay compatible with certain snaps + * that were tested with pre-chroot layout. + **/ +void sc_setup_quirks(); + +#endif diff -Nru snap-confine-1.0.38/src/sc-main.c snap-confine-1.0.41/src/sc-main.c --- snap-confine-1.0.38/src/sc-main.c 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/sc-main.c 2016-09-19 15:46:03.000000000 +0000 @@ -35,6 +35,10 @@ #endif // ifdef HAVE_SECCOMP #include "udev-support.h" #include "cleanup-funcs.h" +#include "user-support.h" +#include "ns-support.h" +#include "quirks.h" +#include "secure-getenv.h" int sc_main(int argc, char **argv) { @@ -64,11 +68,13 @@ if (!verify_security_tag(security_tag)) die("security tag %s not allowed", security_tag); +#ifndef CAPS_OVER_SETUID // this code always needs to run as root for the cgroup/udev setup, // however for the tests we allow it to run as non-root if (geteuid() != 0 && secure_getenv("SNAP_CONFINE_NO_ROOT") == NULL) { die("need to run as root or suid"); } +#endif #ifdef HAVE_SECCOMP scmp_filter_ctx seccomp_ctx __attribute__ ((cleanup(sc_cleanup_seccomp_release))) = NULL; @@ -76,53 +82,27 @@ #endif // ifdef HAVE_SECCOMP if (geteuid() == 0) { - - // ensure we run in our own slave mount namespace, this will - // create a new mount namespace and make it a slave of "/" - // - // Note that this means that no mount actions inside our - // namespace are propagated to the main "/". We need this - // both for the private /tmp we create and for the bind - // mounts we do on a classic distribution system - // - // This also means you can't run an automount daemon unter - // this launcher - setup_slave_mount_namespace(); - - // Get the current working directory before we start fiddling with - // mounts and possibly pivot_root. At the end of the whole process, we - // will try to re-locate to the same directory (if possible). - char *vanilla_cwd __attribute__ ((cleanup(sc_cleanup_string))) = - NULL; - vanilla_cwd = get_current_dir_name(); - if (vanilla_cwd == NULL) { - die("cannot get the current working directory"); + const char *group_name = getenv("SNAP_NAME"); + if (group_name == NULL) { + die("SNAP_NAME is not set"); } - // do the mounting if run on a non-native snappy system - if (is_running_on_classic_distribution()) { - setup_snappy_os_mounts(); + sc_initialize_ns_groups(); + struct sc_ns_group *group = NULL; + group = sc_open_ns_group(group_name); + sc_lock_ns_mutex(group); + sc_create_or_join_ns_group(group); + if (sc_should_populate_ns_group(group)) { + sc_populate_mount_ns(security_tag); + sc_preserve_populated_ns_group(group); } - // set up private mounts - setup_private_mount(security_tag); - - // set up private /dev/pts - setup_private_pts(); - - // this needs to happen as root + sc_unlock_ns_mutex(group); + sc_close_ns_group(group); struct snappy_udev udev_s; if (snappy_udev_init(security_tag, &udev_s) == 0) setup_devices_cgroup(security_tag, &udev_s); snappy_udev_cleanup(&udev_s); - // setup the security backend bind mounts - sc_setup_mount_profiles(security_tag); - - // Try to re-locate back to vanilla working directory. This can fail - // because that directory is no longer present. - if (chdir(vanilla_cwd) != 0) { - die("cannot remain in %s, please run this snap from another location", vanilla_cwd); - } - // the rest does not so temporarily drop privs back to calling + // The rest does not so temporarily drop privs back to calling // user (we'll permanently drop after loading seccomp) if (setegid(real_gid) != 0) die("setegid failed"); @@ -134,8 +114,10 @@ if (real_uid != 0 && getegid() == 0) die("dropping privs did not work"); } - // https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement + // Ensure that the user data path exists. + setup_user_data(); + // https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement #ifdef HAVE_APPARMOR int rc = 0; // set apparmor rules diff -Nru snap-confine-1.0.38/src/seccomp-support.c snap-confine-1.0.41/src/seccomp-support.c --- snap-confine-1.0.38/src/seccomp-support.c 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/seccomp-support.c 2016-09-19 15:46:03.000000000 +0000 @@ -36,6 +36,7 @@ #include #include "utils.h" +#include "secure-getenv.h" #define sc_map_add(X) sc_map_add_kvp(#X, X) @@ -99,7 +100,6 @@ ENTRY e; ENTRY *ep = NULL; scmp_datum_t val = 0; - scmp_datum_t *val_p = NULL; errno = 0; e.key = s; @@ -107,6 +107,7 @@ die("hsearch_r failed"); if (ep != NULL) { + scmp_datum_t *val_p = NULL; val_p = ep->data; val = *val_p; } else @@ -189,6 +190,14 @@ sc_map_add(SOCK_PACKET); // man 2 prctl +#ifndef PR_CAP_AMBIENT +#define PR_CAP_AMBIENT 47 +#define PR_CAP_AMBIENT_IS_SET 1 +#define PR_CAP_AMBIENT_RAISE 2 +#define PR_CAP_AMBIENT_LOWER 3 +#define PR_CAP_AMBIENT_CLEAR_ALL 4 +#endif // PR_CAP_AMBIENT + sc_map_add(PR_CAP_AMBIENT); sc_map_add(PR_CAP_AMBIENT_RAISE); sc_map_add(PR_CAP_AMBIENT_LOWER); @@ -224,7 +233,13 @@ sc_map_add(PR_SET_MM_ENV_END); sc_map_add(PR_SET_MM_AUXV); sc_map_add(PR_SET_MM_EXE_FILE); +#ifndef PR_MPX_ENABLE_MANAGEMENT +#define PR_MPX_ENABLE_MANAGEMENT 43 +#endif // PR_MPX_ENABLE_MANAGEMENT sc_map_add(PR_MPX_ENABLE_MANAGEMENT); +#ifndef PR_MPX_DISABLE_MANAGEMENT +#define PR_MPX_DISABLE_MANAGEMENT 44 +#endif // PR_MPX_DISABLE_MANAGEMENT sc_map_add(PR_MPX_DISABLE_MANAGEMENT); sc_map_add(PR_SET_NAME); sc_map_add(PR_GET_NAME); @@ -237,9 +252,15 @@ sc_map_add(PR_GET_SECCOMP); sc_map_add(PR_SET_SECUREBITS); sc_map_add(PR_GET_SECUREBITS); +#ifndef PR_SET_THP_DISABLE +#define PR_SET_THP_DISABLE 41 +#endif // PR_SET_THP_DISABLE sc_map_add(PR_SET_THP_DISABLE); sc_map_add(PR_TASK_PERF_EVENTS_DISABLE); sc_map_add(PR_TASK_PERF_EVENTS_ENABLE); +#ifndef PR_GET_THP_DISABLE +#define PR_GET_THP_DISABLE 42 +#endif // PR_GET_THP_DISABLE sc_map_add(PR_GET_THP_DISABLE); sc_map_add(PR_GET_TID_ADDRESS); sc_map_add(PR_SET_TIMERSLACK); diff -Nru snap-confine-1.0.38/src/secure-getenv.c snap-confine-1.0.41/src/secure-getenv.c --- snap-confine-1.0.38/src/secure-getenv.c 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/secure-getenv.c 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 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 . + * + */ +#include "secure-getenv.h" + +#include +#include + +#ifndef HAVE_SECURE_GETENV +char *secure_getenv(const char *name) +{ + unsigned long secure = getauxval(AT_SECURE); + if (secure != 0) { + return NULL; + } + return getenv(name); +} +#endif // ! HAVE_SECURE_GETENV diff -Nru snap-confine-1.0.38/src/secure-getenv.h snap-confine-1.0.41/src/secure-getenv.h --- snap-confine-1.0.38/src/secure-getenv.h 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/secure-getenv.h 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 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 . + * + */ +#ifndef SNAP_CONFINE_SECURE_GETENV_H +#define SNAP_CONFINE_SECURE_GETENV_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef HAVE_SECURE_GETENV +/** + * Secure version of getenv() + * + * This version returns NULL if the process is running within a secure context. + * This is exactly the same as the GNU extension to the standard library. It is + * only used when glibc is not available. + **/ +char *secure_getenv(const char *name) + __attribute__ ((nonnull(1), warn_unused_result)); +#endif // ! HAVE_SECURE_GETENV + +#endif diff -Nru snap-confine-1.0.38/src/snap-confine.apparmor.in snap-confine-1.0.41/src/snap-confine.apparmor.in --- snap-confine-1.0.38/src/snap-confine.apparmor.in 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/snap-confine.apparmor.in 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,279 @@ +# Author: Jamie Strandboge +#include + +@LIBEXECDIR@/snap-confine (attach_disconnected) { + # We run privileged, so be fanatical about what we include and don't use + # any abstractions + /etc/ld.so.cache r, + /lib/@{multiarch}/ld-*.so mr, + # libc, you are funny + /lib/@{multiarch}/libc{,-[0-9]*}.so* mr, + /lib/@{multiarch}/libpthread{,-[0-9]*}.so* mr, + /lib/@{multiarch}/librt{,-[0-9]*}.so* mr, + /lib/@{multiarch}/libgcc_s.so* mr, + # normal libs in order + /lib/@{multiarch}/libapparmor.so* mr, + /lib/@{multiarch}/libcgmanager.so* mr, + /lib/@{multiarch}/libnih.so* mr, + /lib/@{multiarch}/libnih-dbus.so* mr, + /lib/@{multiarch}/libdbus-1.so* mr, + /lib/@{multiarch}/libudev.so* mr, + /usr/lib/@{multiarch}/libseccomp.so* mr, + /lib/@{multiarch}/libseccomp.so* mr, + + @LIBEXECDIR@/snap-confine r, + + /dev/null rw, + /dev/full rw, + /dev/zero rw, + /dev/random r, + /dev/urandom r, + /dev/pts/[0-9]* rw, + + # cgroups + capability sys_admin, + capability dac_override, + /sys/fs/cgroup/devices/snap{,py}.*/ w, + /sys/fs/cgroup/devices/snap{,py}.*/tasks w, + /sys/fs/cgroup/devices/snap{,py}.*/devices.{allow,deny} w, + + # querying udev + /etc/udev/udev.conf r, + /sys/devices/**/uevent r, + /lib/udev/snappy-app-dev ixr, # drop + /run/udev/** rw, + /{,usr/}bin/tr ixr, + /usr/lib/locale/** r, + /usr/lib/@{multiarch}/gconv/gconv-modules r, + /usr/lib/@{multiarch}/gconv/gconv-modules.cache r, + + # priv dropping + capability setuid, + capability setgid, + + # changing profile + @{PROC}/[0-9]*/attr/exec w, + + # Don't allow changing profile to unconfined or profiles that start with + # '/'. Use 'unsafe' to support snap-exec on armhf and its reliance on + # the environment for determining the capabilities of the architecture. + # 'unsafe' is ok here because the kernel will have already cleared the + # environment as part of launching snap-confine with + # CAP_SYS_ADMIN. + change_profile unsafe /** -> [^u/]**, + change_profile unsafe /** -> u[^n]**, + change_profile unsafe /** -> un[^c]**, + change_profile unsafe /** -> unc[^o]**, + change_profile unsafe /** -> unco[^n]**, + change_profile unsafe /** -> uncon[^f]**, + change_profile unsafe /** -> unconf[^i]**, + change_profile unsafe /** -> unconfi[^n]**, + change_profile unsafe /** -> unconfin[^e]**, + change_profile unsafe /** -> unconfine[^d]**, + change_profile unsafe /** -> unconfined?**, + + # allow changing to a few not caught above + change_profile unsafe /** -> {u,un,unc,unco,uncon,unconf,unconfi,unconfin,unconfine}, + + # LP: #1446794 - when this bug is fixed, change the above to: + # deny change_profile unsafe /** -> {unconfined,/**}, + # change_profile unsafe /** -> **, + + # reading seccomp filters + /{tmp/snap.rootfs_*/,}var/lib/snapd/seccomp/profiles/* r, + + # reading mount profiles + /{tmp/snap.rootfs_*/,}var/lib/snapd/mount/*.fstab r, + + # set up snap-specific private /tmp dir + capability chown, + /{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 + # Workaround for LP: #1584456 on older kernels that mistakenly think + # /dev/pts/ptmx needs a trailing '/' + mount options=(rw bind) /{tmp/snap.rootfs_*/,}dev/pts/ptmx/ -> /{tmp/snap.rootfs_*/,}dev/ptmx/, + + # for running snaps on classic + mount options=(rw rslave) -> /, + /tmp/snap.rootfs_*/snap/ r, + /tmp/snap.rootfs_*/snap/** r, + @SNAP_MOUNT_DIR@/ r, + @SNAP_MOUNT_DIR@/** r, + + # mount calls to setup the pivot_root based chroot with the core snap as + # the root filesystem. + mount options=(rw bind) @SNAP_MOUNT_DIR@/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) /root/ -> /tmp/snap.rootfs_*/root/, + mount options=(rw rbind) /proc/ -> /tmp/snap.rootfs_*/proc/, + mount options=(rw rbind) @SNAP_MOUNT_DIR@/ -> /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/, + mount options=(rw rbind) /run/ -> /tmp/snap.rootfs_*/run/, + mount options=(rw rbind) /media/ -> /tmp/snap.rootfs_*/media/, + mount options=(rw rbind) {/usr,}/lib/modules/ -> /tmp/snap.rootfs_*/lib/modules/, + mount options=(rw rbind) /var/log/ -> /tmp/snap.rootfs_*/var/log/, + mount options=(rw rbind) /usr/src/ -> /tmp/snap.rootfs_*/usr/src/, + mount options=(rw bind) @SNAP_MOUNT_DIR@/ubuntu-core/*/etc/alternatives/ -> /tmp/snap.rootfs_*/etc/alternatives/, + + # Allow to mkdir /var/lib/snapd/hostfs + /var/lib/snapd/hostfs/ rw, + # Allow to mount / as hostfs in the chroot + mount options=(ro bind) / -> /tmp/snap.rootfs_*/var/lib/snapd/hostfs/, + + # NOTE: at this stage the /snap directory is stable as we have called + # pivot_root already. + + # Support mount profiles via the content interface + mount options=(rw bind) /snap/*/** -> /snap/*/*/**, + mount options=(ro bind) /snap/*/** -> /snap/*/*/**, + # But we don't want anyone to touch /snap/bin + audit deny mount /snap/bin/** -> /**, + audit deny mount /** -> /snap/bin/**, + # Allow the content interface to bind fonts from the host filesystem + mount options=(ro bind) /var/lib/snapd/hostfs/usr/share/fonts/ -> /snap/*/*/**, + + # nvidia handling, glob needs /usr/** and the launcher must be + # able to bind mount the nvidia dir + /sys/module/nvidia/version r, + /usr/** r, + mount options=(rw bind) /usr/lib/nvidia-*/ -> /{tmp/snap.rootfs_*/,}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, + umount /, + + # for creating the user data directories: ~/snap, ~/snap/ and + # ~/snap// + / r, + @{HOMEDIRS}/ r, + # These should both have 'owner' match but due to LP: #1466234, we can't + # yet + @{HOME}/ r, + @{HOME}/snap/{,*/,*/*/} rw, + + # for creating the user shared memory directories + /{dev,run}/{,shm/} r, + # This should both have 'owner' match but due to LP: #1466234, we can't yet + /{dev,run}/shm/{,*/,*/*/} rw, + + # Workaround https://launchpad.net/bugs/359338 until upstream handles + # stacked filesystems generally. + # encrypted ~/.Private and old-style encrypted $HOME + @{HOME}/.Private/ r, + @{HOME}/.Private/** mrixwlk, + # new-style encrypted $HOME + @{HOMEDIRS}/.ecryptfs/*/.Private/ r, + @{HOMEDIRS}/.ecryptfs/*/.Private/** mrixwlk, + + # Allow snap-confine to move to the void + /var/lib/snapd/void/ r, + + # Support for the quirk system + /var/ r, + /var/lib/ r, + /var/lib/** rw, + /tmp/ r, + /tmp/snapd.quirks_*/ rw, + mount options=(move) /var/lib/snapd/ -> /tmp/snapd.quirks_*/, + mount fstype=tmpfs options=(rw nodev nosuid) none -> /var/lib/, + mount options=(ro rbind) /snap/ubuntu-core/*/var/lib/** -> /var/lib/**, + umount /var/lib/snapd/, + mount options=(move) /tmp/snapd.quirks_*/ -> /var/lib/snapd/, + + # support for the LXD quirk + mount options=(rw rbind nodev nosuid noexec) /var/lib/snapd/hostfs/var/lib/lxd/ -> /var/lib/lxd/, + /var/lib/lxd/ w, + /var/lib/snapd/hostfs/var/lib/lxd r, + + # support for the mount namespace sharing + mount options=(rw rbind) /run/snapd/ns/ -> /run/snapd/ns/, + mount options=(private) -> /run/snapd/ns/, + / rw, + /run/ rw, + /run/snapd/ rw, + /run/snapd/ns/ rw, + /run/snapd/ns/*.lock rwk, + /run/snapd/ns/*.mnt rw, + ptrace (tracedby) peer=@LIBEXECDIR@/snap-confine//mount-namespace-capture-helper, + owner @{PROC}/*/mountinfo r, + capability sys_chroot, + capability sys_admin, + signal (send, receive) set=(abrt) peer=@LIBEXECDIR@/snap-confine, + signal (send) set=(int) peer=@LIBEXECDIR@/snap-confine//mount-namespace-capture-helper, + signal (send, receive) set=(alrm, exists) peer=@LIBEXECDIR@/snap-confine, + signal (receive) set=(exists) peer=@LIBEXECDIR@/snap-confine//mount-namespace-capture-helper, + + ^mount-namespace-capture-helper (attach_disconnected) { + # We run privileged, so be fanatical about what we include and don't use + # any abstractions + /etc/ld.so.cache r, + /lib/@{multiarch}/ld-*.so mr, + # libc, you are funny + /lib/@{multiarch}/libc{,-[0-9]*}.so* mr, + /lib/@{multiarch}/libpthread{,-[0-9]*}.so* mr, + /lib/@{multiarch}/librt{,-[0-9]*}.so* mr, + /lib/@{multiarch}/libgcc_s.so* mr, + # normal libs in order + /lib/@{multiarch}/libapparmor.so* mr, + /lib/@{multiarch}/libcgmanager.so* mr, + /lib/@{multiarch}/libnih.so* mr, + /lib/@{multiarch}/libnih-dbus.so* mr, + /lib/@{multiarch}/libdbus-1.so* mr, + /lib/@{multiarch}/libudev.so* mr, + /usr/lib/@{multiarch}/libseccomp.so* mr, + /lib/@{multiarch}/libseccomp.so* mr, + + @LIBEXECDIR@/snap-confine r, + + /dev/null rw, + /dev/full rw, + /dev/zero rw, + /dev/random r, + /dev/urandom r, + + capability sys_ptrace, + capability sys_admin, + # This allows us to read and bind mount the namespace file + / r, + @{PROC}/ r, + @{PROC}/*/ r, + @{PROC}/*/ns/ r, + @{PROC}/*/ns/mnt r, + /run/ r, + /run/snapd/ r, + /run/snapd/ns/ r, + /run/snapd/ns/*.mnt rw, + # NOTE: the source name is / even though we map /proc/123/ns/mnt + mount options=(rw bind) / -> /run/snapd/ns/*.mnt, + # This is the SIGALRM that we send and receive if a timeout expires + signal (send, receive) set=(alrm) peer=@LIBEXECDIR@/snap-confine//mount-namespace-capture-helper, + # Those two rules are exactly the same but we don't know if the parent process is still alive + # and hence has the appropriate label or is already dead and hence has no label. + signal (send) set=(exists) peer=@LIBEXECDIR@/snap-confine, + signal (send) set=(exists) peer=unconfined, + # This is so that we can abort + signal (send, receive) set=(abrt) peer=@LIBEXECDIR@/snap-confine//mount-namespace-capture-helper, + # This is the signal we get if snap-confine dies (we subscribe to it with prctl) + signal (receive) set=(int) peer=@LIBEXECDIR@/snap-confine, + # This allows snap-confine to be killed from the outside. + signal (receive) peer=unconfined, + # This allows snap-confine to wait for us + ptrace (trace, tracedby) peer=@LIBEXECDIR@/snap-confine, + } + + # Allow snap-confine to be killed + signal (receive) peer=unconfined, +} diff -Nru snap-confine-1.0.38/src/snap-discard-ns.c snap-confine-1.0.41/src/snap-discard-ns.c --- snap-confine-1.0.38/src/snap-discard-ns.c 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/snap-discard-ns.c 2016-09-19 09:41:32.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * 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 . + * + */ + +#include "utils.h" +#include "ns-support.h" + +int main(int argc, char **argv) +{ + if (argc != 2) + die("Usage: %s snap-name", argv[0]); + const char *snap_name = argv[1]; + struct sc_ns_group *group = sc_open_ns_group(snap_name); + sc_lock_ns_mutex(group); + sc_discard_preserved_ns_group(group); + sc_unlock_ns_mutex(group); + sc_close_ns_group(group); + return 0; +} diff -Nru snap-confine-1.0.38/src/unit-tests.c snap-confine-1.0.41/src/unit-tests.c --- snap-confine-1.0.38/src/unit-tests.c 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/unit-tests.c 2016-09-19 09:41:32.000000000 +0000 @@ -30,6 +30,7 @@ int sc_run_unit_tests(int *argc, char ***argv) { g_test_init(argc, argv, NULL); + g_test_set_nonfatal_assertions(); g_test_add_func("/Simple Test Case", simple_test_case); return g_test_run(); } diff -Nru snap-confine-1.0.38/src/user-support.c snap-confine-1.0.41/src/user-support.c --- snap-confine-1.0.38/src/user-support.c 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/user-support.c 2016-09-19 09:41:41.000000000 +0000 @@ -0,0 +1,111 @@ +/* + * 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 . + * + */ +#include "config.h" +#include "user-support.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +// TODO: rename and move to utils.h +void mkpath(const char *const path) +{ + // If asked to create an empty path, return immediately. + if (strlen(path) == 0) { + return; + } + // We're going to use strtok_r, which needs to modify the path, so + // we'll make a copy of it. + char *path_copy = strdup(path); + if (path_copy == NULL) { + die("failed to create user data directory"); + } + // Open flags to use while we walk the user data path: + // - Don't follow symlinks + // - Don't allow child access to file descriptor + // - Only open a directory (fail otherwise) + int open_flags = O_NOFOLLOW | O_CLOEXEC | O_DIRECTORY; + + // We're going to create each path segment via openat/mkdirat calls + // instead of mkdir calls, to avoid following symlinks and placing the + // user data directory somewhere we never intended for it to go. The + // first step is to get an initial file descriptor. + int fd = AT_FDCWD; + if (path_copy[0] == '/') { + fd = open("/", open_flags); + if (fd < 0) { + free(path_copy); + die("failed to create user data directory"); + } + } + // strtok_r needs a pointer to keep track of where it is in the string. + char *path_walker; + + // Initialize tokenizer and obtain first path segment. + char *path_segment = strtok_r(path_copy, "/", &path_walker); + while (path_segment) { + // Try to create the directory. It's okay if it already + // existed, but any other error is fatal. + if (mkdirat(fd, path_segment, 0755) < 0 && errno != EEXIST) { + close(fd); // we die regardless of return code + free(path_copy); + die("failed to create user data directory"); + } + // Open the parent directory we just made (and close the + // previous one) so we can continue down the path. + int previous_fd = fd; + fd = openat(fd, path_segment, open_flags); + if (close(previous_fd) != 0) { + free(path_copy); + die("could not close path segment"); + } + if (fd < 0) { + free(path_copy); + die("failed to create user data directory"); + } + // Obtain the next path segment. + path_segment = strtok_r(NULL, "/", &path_walker); + } + + // Close the descriptor for the final directory in the path. + if (close(fd) != 0) { + free(path_copy); + die("could not close final directory"); + } + + free(path_copy); +} + +void setup_user_data() +{ + const char *user_data = getenv("SNAP_USER_DATA"); + + if (user_data == NULL) + return; + // Only support absolute paths. + if (user_data[0] != '/') { + die("user data directory must be an absolute path"); + } + + mkpath(user_data); +} diff -Nru snap-confine-1.0.38/src/user-support.h snap-confine-1.0.41/src/user-support.h --- snap-confine-1.0.38/src/user-support.h 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/src/user-support.h 2016-09-19 09:41:41.000000000 +0000 @@ -0,0 +1,24 @@ +/* + * 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 . + * + */ + +#ifndef SNAP_CONFINE_USER_SUPPORT_H +#define SNAP_CONFINE_USER_SUPPORT_H + +void setup_user_data(); +void mkpath(const char *const path); + +#endif diff -Nru snap-confine-1.0.38/src/utils.c snap-confine-1.0.41/src/utils.c --- snap-confine-1.0.38/src/utils.c 2016-07-15 11:47:37.000000000 +0000 +++ snap-confine-1.0.41/src/utils.c 2016-09-19 09:41:41.000000000 +0000 @@ -76,7 +76,7 @@ int must_snprintf(char *str, size_t size, const char *format, ...) { - int n = -1; + int n; va_list va; va_start(va, format); diff -Nru snap-confine-1.0.38/tests/Makefile.in snap-confine-1.0.41/tests/Makefile.in --- snap-confine-1.0.38/tests/Makefile.in 2016-07-15 14:01:09.000000000 +0000 +++ snap-confine-1.0.41/tests/Makefile.in 2016-09-19 09:44:58.000000000 +0000 @@ -379,6 +379,7 @@ SECCOMP_LIBS = @SECCOMP_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ +SNAP_MOUNT_DIR = @SNAP_MOUNT_DIR@ STRIP = @STRIP@ UDEV_CFLAGS = @UDEV_CFLAGS@ UDEV_LIBS = @UDEV_LIBS@ diff -Nru snap-confine-1.0.38/VERSION snap-confine-1.0.41/VERSION --- snap-confine-1.0.38/VERSION 1970-01-01 00:00:00.000000000 +0000 +++ snap-confine-1.0.41/VERSION 2016-09-20 08:42:55.000000000 +0000 @@ -0,0 +1 @@ +1.0.41