tests: check for relabeling rather than overlay
authorJonathan Lebon <jlebon@redhat.com>
Thu, 28 Sep 2017 18:57:33 +0000 (18:57 +0000)
committerAtomic Bot <atomic-devel@projectatomic.io>
Sat, 30 Sep 2017 00:05:07 +0000 (00:05 +0000)
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

tests/libostreetest.c
tests/libostreetest.h
tests/libtest.sh
tests/test-basic-c.c

index 6186a73a1393a683acae1c03cabf7ee8b68a32d7..496ff74071dc2e33f626b77cb6c307c5ac38244f 100644 (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);
index d5512d553e626506001ecf0f872c778dd0a9342b..0273334adce0ad64a45082e2bbf016f8dd3681b5 100644 (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);
 
index 6993629d6d0bc13a33e7a0c2841151ccc3b412b1..a0c0e36f7d9c7539bf958ed3771c7824bba09308 100755 (executable)
@@ -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
 }
 
index 163774f32601cf047adcf7f0aa7b5bcacabbb98d..f7e8543846d7882c301fb0ad046b409567608618 100644 (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;
     }