[glib/wip/smcv/fileutils-test-as-root] glib/tests/fileutils: Fix expectations when running as root




commit 084aaf6b8b6542b48e8f2fd285477eda60f2ac08
Author: Simon McVittie <smcv collabora com>
Date:   Wed Oct 28 09:49:32 2020 +0000

    glib/tests/fileutils: Fix expectations when running as root
    
    This test asserts that g_file_set_contents_full() will fail when used
    on a read-only file, but processes with CAP_DAC_OVERRIDE on Linux or
    uid 0 on traditional Unix can and do ignore DAC permissions.
    
    Historically, running build-time tests as uid 0 has been considered to
    be a very bad idea, and running installed-tests as uid 0 unnecessarily
    has also been discouraged; but with increasing availability of expendable
    environments suitable for CI systems (virtual machines, containers, and
    cheap bare-metal hardware like Raspberry Pi) it's increasingly common
    that there is nothing that needs to be protected from mistakes, so
    everything is run as uid 0 in the expendable environment.
    
    Instead, probe the file with Standard C fopen() to see what happens, and
    assert that g_file_set_contents_full() has the same behaviour
    (whatever that happens to be).
    
    Bug-Debian: https://bugs.debian.org/973271
    Signed-off-by: Simon McVittie <smcv collabora com>

 glib/tests/fileutils.c | 54 +++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 5 deletions(-)
---
diff --git a/glib/tests/fileutils.c b/glib/tests/fileutils.c
index fa6fc6acf..f486e735d 100644
--- a/glib/tests/fileutils.c
+++ b/glib/tests/fileutils.c
@@ -1128,10 +1128,12 @@ test_set_contents_full (void)
 static void
 test_set_contents_full_read_only_file (void)
 {
+  FILE *stdio_file;
   gint fd;
   GError *error = NULL;
   gchar *file_name = NULL;
   gboolean ret;
+  gboolean can_override_dac = FALSE;
 
   g_test_summary ("Test g_file_set_contents_full() on a read-only file");
 
@@ -1145,10 +1147,32 @@ test_set_contents_full_read_only_file (void)
   close (fd);
   g_assert_no_errno (chmod (file_name, 0200));
 
+  /* If we have CAP_DAC_OVERRIDE on Linux or uid 0 on traditional Unix,
+   * we will ignore the permissions. Assume that the desired result is
+   * that g_file_set_contents_full() succeeds or fails in the same way
+   * as Standard C fopen(). */
+  stdio_file = fopen (file_name, "r+");
+
+  if (stdio_file != NULL)
+    {
+      can_override_dac = TRUE;
+      fclose (stdio_file);
+    }
+
   /* Set the file contents */
   ret = g_file_set_contents_full (file_name, "b", 1, G_FILE_SET_CONTENTS_NONE, 0644, &error);
-  g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
-  g_assert_false (ret);
+
+  if (can_override_dac)
+    {
+      g_assert_no_error (error);
+      g_assert_true (ret);
+    }
+  else
+    {
+      g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
+      g_assert_false (ret);
+    }
+
   g_clear_error (&error);
 
   g_remove (file_name);
@@ -1169,11 +1193,13 @@ test_set_contents_full_read_only_directory (void)
 
   for (flags = 0; flags < (gint) flags_mask; flags++)
     {
+      FILE *stdio_file;
       gint fd;
       GError *error = NULL;
       gchar *dir_name = NULL;
       gchar *file_name = NULL;
       gboolean ret;
+      gboolean can_override_dac = FALSE;
 
       g_test_message ("Flags %d", flags);
 
@@ -1189,12 +1215,30 @@ test_set_contents_full_read_only_directory (void)
 
       g_assert_no_errno (chmod (dir_name, 0));
 
+      /* See test_set_contents_full_read_only_file() */
+      stdio_file = fopen (file_name, "r+");
+
+      if (stdio_file != NULL)
+        {
+          can_override_dac = TRUE;
+          fclose (stdio_file);
+        }
+
       /* Set the file contents */
       ret = g_file_set_contents_full (file_name, "b", 1, flags, 0644, &error);
-      g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
-      g_assert_false (ret);
-      g_clear_error (&error);
 
+      if (can_override_dac)
+        {
+          g_assert_no_error (error);
+          g_assert_true (ret);
+        }
+      else
+        {
+          g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES);
+          g_assert_false (ret);
+        }
+
+      g_clear_error (&error);
       g_remove (file_name);
       g_unlink (dir_name);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]