Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd: add helpers for mounting / unmounting #2827

Merged
merged 9 commits into from Mar 1, 2017
51 changes: 50 additions & 1 deletion cmd/Makefile.am
Expand Up @@ -70,6 +70,8 @@ libsnap_confine_private_a_SOURCES = \
libsnap-confine-private/cleanup-funcs.h \
libsnap-confine-private/error.c \
libsnap-confine-private/error.h \
libsnap-confine-private/fault-injection.c \
libsnap-confine-private/fault-injection.h \
libsnap-confine-private/mount-opt.c \
libsnap-confine-private/mount-opt.h \
libsnap-confine-private/mountinfo.c \
Expand Down Expand Up @@ -104,8 +106,18 @@ libsnap_confine_private_unit_tests_SOURCES = \
libsnap-confine-private/utils-test.c
libsnap_confine_private_unit_tests_CFLAGS = $(GLIB_CFLAGS)
libsnap_confine_private_unit_tests_LDADD = $(GLIB_LIBS)
libsnap_confine_private_unit_tests_LDADD += -lcap
libsnap_confine_private_unit_tests_CFLAGS += -D_ENABLE_FAULT_INJECTION

# XXX: This injects a dependency on libcap in a way that makes automake happy
# and allows us to link libcap statically. We need to link in libcap statically
# as at this time adding runtime dependencies to snap-confine is tricky.

libsnap-confine-private/unit-tests$(EXEEXT): $(libsnap_confine_private_unit_tests_OBJECTS) $(libsnap_confine_private_unit_tests_DEPENDENCIES) $(EXTRA_libsnap_confine_private_unit_tests_DEPENDENCIES) libsnap-confine-private/$(am__dirstamp)
@rm -f libsnap-confine-private/unit-tests$(EXEEXT)
$(AM_V_CCLD)$(libsnap_confine_private_unit_tests_LINK) $(libsnap_confine_private_unit_tests_OBJECTS) $(libsnap_confine_private_unit_tests_LDADD) $(LIBS)

libsnap-confine-private/unit-tests$(EXEEXT): LIBS += -Wl,-Bstatic -lcap -Wl,-Bdynamic

endif

##
Expand All @@ -117,6 +129,14 @@ noinst_PROGRAMS += decode-mount-opts/decode-mount-opts
decode_mount_opts_decode_mount_opts_SOURCES = \
decode-mount-opts/decode-mount-opts.c
decode_mount_opts_decode_mount_opts_LDADD = libsnap-confine-private.a
# XXX: this makes automake generate decode_mount_opts_decode_mount_opts_LINK
decode_mount_opts_decode_mount_opts_CFLAGS = -D_fake

decode-mount-opts/decode-mount-opts$(EXEEXT): $(decode_mount_opts_decode_mount_opts_OBJECTS) $(decode_mount_opts_decode_mount_opts_DEPENDENCIES) $(EXTRA_decode_mount_opts_decode_mount_opts_DEPENDENCIES) libsnap-confine-private/$(am__dirstamp)
@rm -f decode-mount-opts/decode-mount-opts$(EXEEXT)
$(AM_V_CCLD)$(decode_mount_opts_decode_mount_opts_LINK) $(decode_mount_opts_decode_mount_opts_OBJECTS) $(decode_mount_opts_decode_mount_opts_LDADD) $(LIBS)

decode-mount-opts/decode-mount-opts$(EXEEXT): LIBS += -Wl,-Bstatic -lcap -Wl,-Bdynamic

##
## snap-confine
Expand Down Expand Up @@ -186,6 +206,12 @@ snap_confine_snap_confine_LDADD = libsnap-confine-private.a
snap_confine_snap_confine_CFLAGS += $(LIBUDEV_CFLAGS)
snap_confine_snap_confine_LDADD += $(LIBUDEV_LIBS)

snap-confine/snap-confine$(EXEEXT): $(snap_confine_snap_confine_OBJECTS) $(snap_confine_snap_confine_DEPENDENCIES) $(EXTRA_snap_confine_snap_confine_DEPENDENCIES) libsnap-confine-private/$(am__dirstamp)
@rm -f snap-confine/snap-confine$(EXEEXT)
$(AM_V_CCLD)$(snap_confine_snap_confine_LINK) $(snap_confine_snap_confine_OBJECTS) $(snap_confine_snap_confine_LDADD) $(LIBS)

snap-confine/snap-confine$(EXEEXT): LIBS += -Wl,-Bstatic -lcap -Wl,-Bdynamic

# This is here to help fix rpmlint hardening issue.
# https://en.opensuse.org/openSUSE:Packaging_checks#non-position-independent-executable
snap_confine_snap_confine_CFLAGS += $(SUID_CFLAGS)
Expand All @@ -204,6 +230,21 @@ snap_confine_snap_confine_CFLAGS += $(APPARMOR_CFLAGS)
snap_confine_snap_confine_LDADD += $(APPARMOR_LIBS)
endif

# an extra build that has additional debugging enabled at compile time

noinst_PROGRAMS += snap-confine/snap-confine-debug
snap_confine_snap_confine_debug_SOURCES = $(snap_confine_snap_confine_SOURCES)
snap_confine_snap_confine_debug_CFLAGS = $(snap_confine_snap_confine_CFLAGS)
snap_confine_snap_confine_debug_LDFLAGS = $(snap_confine_snap_confine_LDFLAGS)
snap_confine_snap_confine_debug_LDADD = $(snap_confine_snap_confine_LDADD)
snap_confine_snap_confine_debug_CFLAGS += -DSNAP_CONFINE_DEBUG_BUILD=1

snap-confine/snap-confine-debug$(EXEEXT): $(snap_confine_snap_confine_debug_OBJECTS) $(snap_confine_snap_confine_debug_DEPENDENCIES) $(EXTRA_snap_confine_snap_confine_debug_DEPENDENCIES) libsnap-confine-private/$(am__dirstamp)
@rm -f snap-confine/snap-confine-debug$(EXEEXT)
$(AM_V_CCLD)$(snap_confine_snap_confine_debug_LINK) $(snap_confine_snap_confine_debug_OBJECTS) $(snap_confine_snap_confine_debug_LDADD) $(LIBS)

snap-confine/snap-confine-debug$(EXEEXT): LIBS += -Wl,-Bstatic -lcap -Wl,-Bdynamic

if WITH_UNIT_TESTS
noinst_PROGRAMS += snap-confine/snap-confine-unit-tests
snap_confine_snap_confine_unit_tests_SOURCES = \
Expand All @@ -220,6 +261,14 @@ snap_confine_snap_confine_unit_tests_SOURCES = \
snap_confine_snap_confine_unit_tests_CFLAGS = $(snap_confine_snap_confine_CFLAGS) $(GLIB_CFLAGS)
snap_confine_snap_confine_unit_tests_LDADD = $(snap_confine_snap_confine_LDADD) $(GLIB_LIBS)
snap_confine_snap_confine_unit_tests_LDFLAGS = $(snap_confine_snap_confine_LDFLAGS)


snap-confine/snap-confine-unit-tests$(EXEEXT): $(snap_confine_snap_confine_unit_tests_OBJECTS) $(snap_confine_snap_confine_unit_tests_DEPENDENCIES) $(EXTRA_snap_confine_snap_confine_unit_tests_DEPENDENCIES) libsnap-confine-private/$(am__dirstamp)
@rm -f snap-confine/snap-confine-unit-tests$(EXEEXT)
$(AM_V_CCLD)$(snap_confine_snap_confine_unit_tests_LINK) $(snap_confine_snap_confine_unit_tests_OBJECTS) $(snap_confine_snap_confine_unit_tests_LDADD) $(LIBS)

snap-confine/snap-confine-unit-tests$(EXEEXT): LIBS += -Wl,-Bstatic -lcap -Wl,-Bdynamic

endif

snap-confine/%.5: snap-confine/%.rst
Expand Down
46 changes: 46 additions & 0 deletions cmd/libsnap-confine-private/mount-opt-test.c
Expand Up @@ -18,7 +18,9 @@
#include "mount-opt.h"
#include "mount-opt.c"

#include <errno.h>
#include <sys/mount.h>

#include <glib.h>

static void test_sc_mount_opt2str()
Expand Down Expand Up @@ -203,9 +205,53 @@ static void test_sc_umount_cmd()
"umount --force --lazy --expire --no-follow /mnt/foo");
}

static void test_sc_do_mount()
{
if (g_test_subprocess()) {
bool broken_mount(struct sc_fault_state *state, void *ptr) {
errno = EACCES;
return true;
}
sc_break("mount", broken_mount);
sc_do_mount("/foo", "/bar", "ext4", MS_RDONLY, NULL);

g_test_message("expected sc_do_mount not to return");
sc_reset_faults();
g_test_fail();
return;
}
g_test_trap_subprocess(NULL, 0, 0);
g_test_trap_assert_failed();
g_test_trap_assert_stderr
("cannot perform operation: mount -t ext4 -o ro /foo /bar: Permission denied\n");
}

static void test_sc_do_umount()
{
if (g_test_subprocess()) {
bool broken_umount(struct sc_fault_state *state, void *ptr) {
errno = EACCES;
return true;
}
sc_break("umount", broken_umount);
sc_do_umount("/foo", MNT_DETACH);

g_test_message("expected sc_do_umount not to return");
sc_reset_faults();
g_test_fail();
return;
}
g_test_trap_subprocess(NULL, 0, 0);
g_test_trap_assert_failed();
g_test_trap_assert_stderr
("cannot perform operation: umount --lazy /foo: Permission denied\n");
}

static void __attribute__ ((constructor)) init()
{
g_test_add_func("/mount/sc_mount_opt2str", test_sc_mount_opt2str);
g_test_add_func("/mount/sc_mount_cmd", test_sc_mount_cmd);
g_test_add_func("/mount/sc_umount_cmd", test_sc_umount_cmd);
g_test_add_func("/mount/sc_do_mount", test_sc_do_mount);
g_test_add_func("/mount/sc_do_umount", test_sc_do_umount);
}
83 changes: 82 additions & 1 deletion cmd/libsnap-confine-private/mount-opt.c
Expand Up @@ -17,14 +17,17 @@

#include "mount-opt.h"

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>

#include "utils.h"
#include "fault-injection.h"
#include "privs.h"
#include "string-utils.h"
#include "utils.h"

const char *sc_mount_opt2str(char *buf, size_t buf_size, unsigned long flags)
{
Expand Down Expand Up @@ -241,3 +244,81 @@ const char *sc_umount_cmd(char *buf, size_t buf_size, const char *target,

return buf;
}

void sc_do_mount(const char *source, const char *target,
const char *fs_type, unsigned long mountflags,
const void *data)
{
char buf[10000];
const char *mount_cmd = NULL;

void ensure_mount_cmd() {
if (mount_cmd != NULL) {
return;
}
mount_cmd = sc_mount_cmd(buf, sizeof buf, source,
target, fs_type, mountflags, data);
}

if (sc_is_debug_enabled()) {
#ifdef SNAP_CONFINE_DEBUG_BUILD
ensure_mount_cmd();
#else
mount_cmd = "(disabled) use debug build to see details";
#endif
debug("performing operation: %s", mount_cmd);
}
if (sc_faulty("mount", NULL)
|| mount(source, target, fs_type, mountflags, data) < 0) {
// Save errno as ensure can clobber it.
int saved_errno = errno;

// Drop privileges so that we can compute our nice error message
// without risking an attack on one of the string functions there.
sc_privs_drop();

// Compute the equivalent mount command.
ensure_mount_cmd();

// Restore errno and die.
errno = saved_errno;
die("cannot perform operation: %s", mount_cmd);
}
}

void sc_do_umount(const char *target, int flags)
{
char buf[10000];
const char *umount_cmd = NULL;

void ensure_umount_cmd() {
if (umount_cmd != NULL) {
return;
}
umount_cmd = sc_umount_cmd(buf, sizeof buf, target, flags);
}

if (sc_is_debug_enabled()) {
#ifdef SNAP_CONFINE_DEBUG_BUILD
ensure_umount_cmd();
#else
umount_cmd = "(disabled) use debug build to see details";
#endif
debug("performing operation: %s", umount_cmd);
}
if (sc_faulty("umount", NULL) || umount2(target, flags) < 0) {
// Save errno as ensure can clobber it.
int saved_errno = errno;

// Drop privileges so that we can compute our nice error message
// without risking an attack on one of the string functions there.
sc_privs_drop();

// Compute the equivalent umount command.
ensure_umount_cmd();

// Restore errno and die.
errno = saved_errno;
die("cannot perform operation: %s", umount_cmd);
}
}
12 changes: 12 additions & 0 deletions cmd/libsnap-confine-private/mount-opt.h
Expand Up @@ -60,4 +60,16 @@ const char *sc_mount_cmd(char *buf, size_t buf_size, const char *source, const c
const char *sc_umount_cmd(char *buf, size_t buf_size, const char *target,
int flags);

/**
* A thin wrapper around mount(2) with logging and error checks.
**/
void sc_do_mount(const char *source, const char *target,
const char *fs_type, unsigned long mountflags,
const void *data);

/**
* A thin wrapper around umount(2) with logging and error checks.
**/
void sc_do_umount(const char *target, int flags);

#endif // SNAP_CONFINE_MOUNT_OPT_H
1 change: 1 addition & 0 deletions cmd/snap-confine/mount-support.c
Expand Up @@ -33,6 +33,7 @@

#include "../libsnap-confine-private/classic.h"
#include "../libsnap-confine-private/cleanup-funcs.h"
#include "../libsnap-confine-private/mount-opt.h"
#include "../libsnap-confine-private/snap.h"
#include "../libsnap-confine-private/string-utils.h"
#include "../libsnap-confine-private/utils.h"
Expand Down