dbus-daemon test: Don't test fd limits if in an unprivileged container
authorSimon McVittie <smcv@collabora.com>
Tue, 4 Dec 2018 12:09:26 +0000 (12:09 +0000)
committerSimon McVittie <smcv@collabora.com>
Fri, 15 May 2020 10:23:15 +0000 (11:23 +0100)
In an unprivileged container, uid 0 doesn't have CAP_SYS_RESOURCE, so
we can't expect the dbus-daemon to be able to escalate its fd limit.

This can be reproduced using bubblewrap:

    sudo bwrap \
        --cap-drop CAP_SYS_RESOURCE \
        --ro-bind / / \
        --dev /dev \
    env \
        DBUS_TEST_DAEMON=.../bus/dbus-daemon \
        DBUS_TEST_DATA=.../test/data \
    .../test/test-dbus-daemon \
        -p /fd-limit \
        --verbose

Bug-Debian: https://bugs.debian.org/908092

test/dbus-daemon.c

index 7d3bb4b..d753d83 100644 (file)
@@ -2040,6 +2040,7 @@ test_fd_limit (Fixture *f,
 {
 #ifdef HAVE_PRLIMIT
   struct rlimit lim;
+  struct rlimit new_limit;
   const struct passwd *pwd = NULL;
 #endif
 
@@ -2067,7 +2068,7 @@ test_fd_limit (Fixture *f,
     }
 
   if (prlimit (getpid (), RLIMIT_NOFILE, NULL, &lim) < 0)
-    g_error ("prlimit(): %s", g_strerror (errno));
+    g_error ("get prlimit (self): %s", g_strerror (errno));
 
   g_test_message ("our RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
                   (long) lim.rlim_cur, (long) lim.rlim_max);
@@ -2079,8 +2080,33 @@ test_fd_limit (Fixture *f,
       return;
     }
 
+  new_limit = lim;
+  new_limit.rlim_cur = DESIRED_RLIMIT;
+  new_limit.rlim_max = DESIRED_RLIMIT;
+
+  /* Try to increase the rlimit ourselves. If we're root in an
+   * unprivileged Linux container, then we won't have CAP_SYS_RESOURCE
+   * and this will fail with EPERM. If so, the dbus-daemon wouldn't be
+   * able to increase its rlimit either. */
+  if (prlimit (getpid (), RLIMIT_NOFILE, &new_limit, NULL) < 0)
+    {
+      gchar *message;
+
+      message = g_strdup_printf ("Cannot test, we cannot change the rlimit so "
+                                 "presumably neither can the dbus-daemon: %s",
+                                 g_strerror (errno));
+      g_test_skip (message);
+      g_free (message);
+      return;
+    }
+
+  /* Immediately put our original limit back so it won't interfere with
+   * subsequent tests. This should always succeed. */
+  if (prlimit (getpid (), RLIMIT_NOFILE, &lim, NULL) < 0)
+    g_error ("Cannot restore our original limits: %s", g_strerror (errno));
+
   if (prlimit (f->daemon_pid, RLIMIT_NOFILE, NULL, &lim) < 0)
-    g_error ("prlimit(): %s", g_strerror (errno));
+    g_error ("get prlimit (dbus-daemon): %s", g_strerror (errno));
 
   g_test_message ("dbus-daemon's RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
                   (long) lim.rlim_cur, (long) lim.rlim_max);