tests: check for relabeling rather than overlay

Instead of checking for overlayfs, let's explicitly check for our
ability to relabel files since we now have a `libtest` function to do
this. Also port that logic to `libostreetest`.

Note that overlayfs *does* allow manipulating user xattrs. So ideally,
we should break down `OSTREE_NO_XATTRS` further to distinguish between
tests that use bare repos from other modes.

We check the current directory instead of `/` so that developers can
just point `TEST_TMPDIR` to a non-overlayfs mount point when hacking
from a container.

Closes: #1170
Approved by: cgwalters
This commit is contained in:
Jonathan Lebon 2017-09-28 18:57:33 +00:00 committed by Atomic Bot
parent 8fe4536257
commit a06bd82cd4
4 changed files with 140 additions and 49 deletions

View File

@ -72,6 +72,68 @@ ot_test_setup_repo (GCancellable *cancellable,
return g_steal_pointer (&ret_repo);
}
/* Determine whether we're able to relabel files. Needed for bare tests. */
gboolean
ot_check_relabeling (gboolean *can_relabel,
GError **error)
{
g_auto(GLnxTmpfile) tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, ".", O_RDWR | O_CLOEXEC, &tmpf, error))
return FALSE;
g_autoptr(GError) local_error = NULL;
g_autoptr(GBytes) bytes = glnx_fgetxattr_bytes (tmpf.fd, "security.selinux", &local_error);
if (!bytes)
{
/* libglnx preserves errno */
if (G_IN_SET (errno, ENOTSUP, ENODATA))
{
*can_relabel = FALSE;
return TRUE;
}
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
gsize data_len;
const guint8 *data = g_bytes_get_data (bytes, &data_len);
if (fsetxattr (tmpf.fd, "security.selinux", data, data_len, 0) < 0)
{
if (errno == ENOTSUP)
{
*can_relabel = FALSE;
return TRUE;
}
return glnx_throw_errno_prefix (error, "fsetxattr");
}
*can_relabel = TRUE;
return TRUE;
}
/* Determine whether the filesystem supports getting/setting user xattrs. */
gboolean
ot_check_user_xattrs (gboolean *has_user_xattrs,
GError **error)
{
g_auto(GLnxTmpfile) tmpf = { 0, };
if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, ".", O_RDWR | O_CLOEXEC, &tmpf, error))
return FALSE;
if (fsetxattr (tmpf.fd, "user.test", "novalue", strlen ("novalue"), 0) < 0)
{
if (errno == ENOTSUP)
{
*has_user_xattrs = FALSE;
return TRUE;
}
return glnx_throw_errno_prefix (error, "fsetxattr");
}
*has_user_xattrs = TRUE;
return TRUE;
}
OstreeSysroot *
ot_test_setup_sysroot (GCancellable *cancellable,
GError **error)
@ -79,22 +141,19 @@ ot_test_setup_sysroot (GCancellable *cancellable,
if (!ot_test_run_libtest ("setup_os_repository \"archive\" \"syslinux\"", error))
return FALSE;
struct statfs stbuf;
{ g_autoptr(GString) buf = g_string_new ("mutable-deployments");
if (statfs ("/", &stbuf) < 0)
return glnx_null_throw_errno (error);
/* Keep this in sync with the overlayfs bits in libtest.sh */
#ifndef OVERLAYFS_SUPER_MAGIC
#define OVERLAYFS_SUPER_MAGIC 0x794c7630
#endif
if (stbuf.f_type == OVERLAYFS_SUPER_MAGIC)
{
g_print ("libostreetest: detected overlayfs\n");
g_string_append (buf, ",no-xattrs");
}
/* Make sure deployments are mutable */
g_setenv ("OSTREE_SYSROOT_DEBUG", buf->str, TRUE);
}
g_autoptr(GString) buf = g_string_new ("mutable-deployments");
gboolean can_relabel;
if (!ot_check_relabeling (&can_relabel, error))
return FALSE;
if (!can_relabel)
{
g_print ("libostreetest: can't relabel, turning off xattrs\n");
g_string_append (buf, ",no-xattrs");
}
/* Make sure deployments are mutable */
g_setenv ("OSTREE_SYSROOT_DEBUG", buf->str, TRUE);
g_autoptr(GFile) sysroot_path = g_file_new_for_path ("sysroot");
return ostree_sysroot_new (sysroot_path);

View File

@ -31,6 +31,12 @@ gboolean ot_test_run_libtest (const char *cmd, GError **error);
OstreeRepo *ot_test_setup_repo (GCancellable *cancellable,
GError **error);
gboolean ot_check_relabeling (gboolean *can_relabel,
GError **error);
gboolean ot_check_user_xattrs (gboolean *has_user_xattrs,
GError **error);
OstreeSysroot *ot_test_setup_sysroot (GCancellable *cancellable,
GError **error);

View File

@ -70,16 +70,50 @@ chmod -R u+w "${test_tmpdir}"
export TEST_GPG_KEYHOME=${test_tmpdir}/gpghome
export OSTREE_GPG_HOME=${test_tmpdir}/gpghome/trusted
# See comment in ot-builtin-commit.c and https://github.com/ostreedev/ostree/issues/758
# Also keep this in sync with the bits in libostreetest.c
echo evaluating for overlayfs...
case $(stat -f --printf '%T' /) in
overlayfs)
echo "overlayfs found; enabling OSTREE_NO_XATTRS"
export OSTREE_SYSROOT_DEBUG="${OSTREE_SYSROOT_DEBUG},no-xattrs"
export OSTREE_NO_XATTRS=1 ;;
*) ;;
esac
assert_has_setfattr() {
if ! which setfattr 2>/dev/null; then
fatal "no setfattr available to determine xattr support"
fi
}
_have_selinux_relabel=''
have_selinux_relabel() {
assert_has_setfattr
if test "${_have_selinux_relabel}" = ''; then
pushd ${test_tmpdir}
echo testlabel > testlabel.txt
selinux_xattr=security.selinux
if getfattr --encoding=base64 -n ${selinux_xattr} testlabel.txt >label.txt 2>err.txt; then
label=$(grep -E -e "^${selinux_xattr}=" < label.txt |sed -e "s,${selinux_xattr}=,,")
if setfattr -n ${selinux_xattr} -v ${label} testlabel.txt 2>err.txt; then
echo "SELinux enabled in $(pwd), and have privileges to relabel"
_have_selinux_relabel=yes
else
sed -e 's/^/# /' < err.txt >&2
echo "Found SELinux label, but unable to set (Unprivileged Docker?)"
_have_selinux_relabel=no
fi
else
sed -e 's/^/# /' < err.txt >&2
echo "Unable to retrieve SELinux label, assuming disabled"
_have_selinux_relabel=no
fi
popd
fi
test ${_have_selinux_relabel} = yes
}
# just globally turn off xattrs if we can't manipulate security xattrs; this is
# the case for overlayfs -- really, we should only enforce this for tests that
# use bare repos; separate from other tests that should check for user xattrs
# support
# see https://github.com/ostreedev/ostree/issues/758
# and https://github.com/ostreedev/ostree/pull/1217
echo -n checking for xattrs...
if ! have_selinux_relabel; then
export OSTREE_SYSROOT_DEBUG="${OSTREE_SYSROOT_DEBUG},no-xattrs"
export OSTREE_NO_XATTRS=1
fi
echo done
if test -n "${OT_TESTS_DEBUG:-}"; then
@ -516,12 +550,9 @@ os_repository_new_commit ()
cd ${test_tmpdir}
}
# Usage: if ! skip_one_without_user_xattrs; then ... more tests ...; fi
_have_user_xattrs=''
have_user_xattrs() {
if ! which setfattr 2>/dev/null; then
fatal "no setfattr available to determine xattr support"
fi
assert_has_setfattr
if test "${_have_user_xattrs}" = ''; then
touch test-xattrs
if setfattr -n user.testvalue -v somevalue test-xattrs 2>/dev/null; then
@ -533,6 +564,8 @@ have_user_xattrs() {
fi
test ${_have_user_xattrs} = yes
}
# Usage: if ! skip_one_without_user_xattrs; then ... more tests ...; fi
skip_one_without_user_xattrs () {
if ! have_user_xattrs; then
echo "ok # SKIP - this test requires xattr support"
@ -554,21 +587,8 @@ skip_without_user_xattrs () {
# https://github.com/ostreedev/ostree/pull/759
# https://github.com/ostreedev/ostree/pull/1217
skip_without_no_selinux_or_relabel () {
cd ${test_tmpdir}
echo testlabel > testlabel.txt
selinux_xattr=security.selinux
if getfattr --encoding=base64 -n ${selinux_xattr} testlabel.txt >label.txt 2>err.txt; then
label=$(grep -E -e "^${selinux_xattr}=" < label.txt |sed -e "s,${selinux_xattr}=,,")
if setfattr -n ${selinux_xattr} -v ${label} testlabel.txt 2>err.txt; then
echo "SELinux enabled in $(pwd), and have privileges to relabel"
return 0
else
sed -e 's/^/# /' < err.txt >&2
skip "Found SELinux label, but unable to set (Unprivileged Docker?)"
fi
else
sed -e 's/^/# /' < err.txt >&2
skip "Unable to retrieve SELinux label, assuming disabled"
if ! have_selinux_relabel; then
skip "this test requires xattr support"
fi
}

View File

@ -262,14 +262,20 @@ test_devino_cache_xattrs (void)
g_assert_no_error (error);
g_assert (ret);
gboolean on_overlay;
ret = ot_check_for_overlay (&on_overlay, &error);
gboolean can_relabel;
ret = ot_check_relabeling (&can_relabel, &error);
g_assert_no_error (error);
g_assert (ret);
if (on_overlay)
gboolean has_user_xattrs;
ret = ot_check_user_xattrs (&has_user_xattrs, &error);
g_assert_no_error (error);
g_assert (ret);
/* we need both because we're bare and our tests target user xattrs */
if (!can_relabel || !has_user_xattrs)
{
g_test_skip ("overlayfs detected");
g_test_skip ("this test requires full xattr support");
return;
}