Try to preserve current working directory #48

Merged
merged 6 commits into from Jun 24, 2016
@@ -0,0 +1,21 @@
+summary: Regression check for https://bugs.launchpad.net/snap-confine/+bug/1595444
+# This is blacklisted on debian because we first have to get the dpkg-vendor patches
+systems: [-debian-8]
+execute: |
+ echo "Having installed the snapd-hacker-toolbelt snap"
+ snap list | grep -q snapd-hacker-toolbelt || snap install snapd-hacker-toolbelt
+
+ echo "We can go to a location that is available in all snaps (/tmp)"
+ echo "We can run the 'cwd' tool from busybox and it reports /tmp"
+ [ "$(cd /tmp && /snap/bin/snapd-hacker-toolbelt.busybox pwd)" = "/tmp" ]
+
+ echo "But if we go to a location that is not available to snaps (e.g. $HOME/.cache)"
+ echo "Then the same 'cwd' tool refuses to run the snap"
+ mkdir -p "$HOME/.cache/"
+ cd "$HOME/.cache" || exit 1
+ # pwd doesn't run
+ [ "$(/snap/bin/snapd-hacker-toolbelt.busybox pwd)" = "" ]
+ # there's an accurate error message
+ [ "$(/snap/bin/snapd-hacker-toolbelt.busybox pwd 2>&1)" = "cannot remain in $HOME/.cache, please run this snap from another location. errmsg: No such file or directory" ]
+ # snap-confine returns an error code on exit
+ ! /snap/bin/snapd-hacker-toolbelt.busybox pwd
View
@@ -19,30 +19,37 @@ prepare: |
echo "Spread is running as $(id)"
[ "$REUSE_PROJECT" != 1 ] || exit 0
release_ID="$( . /etc/os-release && echo "${ID:-linux}" )"
-
case $release_ID in
ubuntu)
# apt update is hanging on security.ubuntu.com with IPv6.
sysctl -w net.ipv6.conf.all.disable_ipv6=1
trap "sysctl -w net.ipv6.conf.all.disable_ipv6=0" EXIT
;;
debian)
+ echo "deb http://ftp.de.debian.org/debian sid main" > /etc/apt/sources.list.d/snappy.list
;;
esac
case $release_ID in
ubuntu|debian)
- apt-get purge -y snap-confine || true
apt-get update
apt-get install --quiet -y fakeroot
+ # Build a local copy of snap-confine
apt-get install --quiet -y autoconf automake autotools-dev debhelper dh-apparmor dh-autoreconf indent libapparmor-dev libseccomp-dev libudev-dev pkg-config shellcheck udev
test -d /home/test || adduser --quiet --disabled-password --gecos '' test
chown test.test -R ..
sudo -i -u test /bin/sh -c "cd $PWD && DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -tc -b -Zgzip"
dpkg -i ../snap-confine_*.deb || apt-get -f install -y
dpkg -i ../ubuntu-core-launcher_*.deb || apt-get -f install -y
rm -f ../snap-confine_*.deb ../ubuntu-core-launcher_*.deb
+ # Install snapd (testes require it)
+ apt-get install -y snapd
;;
esac
+ # Install the core snap
+ snap list | grep -q ubuntu-core || snap install ubuntu-core
+
suites:
spread-tests/:
summary: Full-system tests for snap-confine
+ spread-tests/regression/:
+ summary: Regression tests for past bug-fixes
View
@@ -10,7 +10,9 @@ snap_confine_SOURCES = \
mount-support.c \
mount-support.h \
mount-support-nvidia.c \
- mount-support-nvidia.h
+ mount-support-nvidia.h \
+ cleanup-funcs.c \
+ cleanup-funcs.h
snap_confine_CFLAGS = -Wall -Werror $(AM_CFLAGS)
snap_confine_LDFLAGS = $(AM_LDFLAGS)
snap_confine_LDADD =
View
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+
+void sc_cleanup_string(char **ptr)
+{
+ free(*ptr);
+}
View
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SNAP_CONFINE_CLEANUP_FUNCS_H
+#define SNAP_CONFINE_CLEANUP_FUNCS_H
+
+/**
+ * Free a dynamically allocated string.
+ *
+ * This function is designed to be used with
+ * __attribute__((cleanup(sc_cleanup_string))).
+ **/
+void sc_cleanup_string(char **ptr);
+
+#endif
View
@@ -32,6 +32,7 @@
#include "seccomp-support.h"
#include "udev-support.h"
#endif // ifdef STRICT_CONFINEMENT
+#include "cleanup-funcs.h"
int main(int argc, char **argv)
{
@@ -86,6 +87,15 @@ int main(int argc, char **argv)
// 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");
+ }
// do the mounting if run on a non-native snappy system
if (is_running_on_classic_distribution()) {
setup_snappy_os_mounts();
@@ -104,6 +114,11 @@ int main(int argc, char **argv)
snappy_udev_cleanup(&udev_s);
#endif // ifdef STRICT_CONFINEMENT
+ // 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);
+ }
@jdstrand

jdstrand Jun 24, 2016

Contributor

Since we are die()ing, LGTM with the get_current_dir_name() change.

// the rest does not so temporarily drop privs back to calling
// user (we'll permanently drop after loading seccomp)
if (setegid(real_gid) != 0)
@@ -78,11 +78,6 @@ static const char *nvidia_globs[] = {
static const size_t nvidia_globs_len =
sizeof nvidia_globs / sizeof *nvidia_globs;
-static void cleanup_string(char **ptr)
-{
- free(*ptr);
-}
-
// Populate libgl_dir with a symlink farm to files matching glob_list.
//
// The symbolic links are made in one of two ways. If the library found is a
@@ -113,7 +108,8 @@ static void sc_populate_libgl_with_hostfs_symlinks(const char *libgl_dir,
char symlink_name[512];
char symlink_target[512];
const char *pathname = glob_res.gl_pathv[i];
- char *pathname_copy __attribute__ ((cleanup(cleanup_string))) =
+ char *pathname_copy
+ __attribute__ ((cleanup(sc_cleanup_string))) =
strdup(pathname);
char *filename = basename(pathname_copy);
struct stat stat_buf;