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

Rework devino caching to support invalidation if metadata changes #1170

Closed
wants to merge 8 commits into from
91 changes: 75 additions & 16 deletions tests/libostreetest.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,29 +72,88 @@ 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 */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm...not explicitly. I think it likely mostly works today, but I'm certain that e.g. glnx_null_throw_errno_prefix() might invoke malloc() which can definitely make system calls... if we want to make that guarantee I think we'll need something more like systemd's _PROTECT_ERRNO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I forgot we do save it.

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)
{
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);
Expand Down
6 changes: 6 additions & 0 deletions tests/libostreetest.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
76 changes: 48 additions & 28 deletions tests/libtest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,44 @@ 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
_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
Expand Down Expand Up @@ -516,12 +544,15 @@ os_repository_new_commit ()
cd ${test_tmpdir}
}

# Usage: if ! skip_one_without_user_xattrs; then ... more tests ...; fi
_have_user_xattrs=''
have_user_xattrs() {
assert_has_setfattr() {
if ! which setfattr 2>/dev/null; then
fatal "no setfattr available to determine xattr support"
fi
}

_have_user_xattrs=''
have_user_xattrs() {
assert_has_setfattr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor, but maybe move the assertion below the test so we don't call it every time?

if test "${_have_user_xattrs}" = ''; then
touch test-xattrs
if setfattr -n user.testvalue -v somevalue test-xattrs 2>/dev/null; then
Expand All @@ -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"
Expand All @@ -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
}

Expand Down
8 changes: 4 additions & 4 deletions tests/test-basic-c.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,14 @@ 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)
if (!can_relabel)
{
g_test_skip ("overlayfs detected");
g_test_skip ("this test requires full xattr support");
return;
}

Expand Down