summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2018-02-20 11:45:39 +0000
committerSimon McVittie <smcv@collabora.com>2018-02-21 11:19:53 +0000
commite3d0e2c518f06b3cecb31ab15d55396ba4348fb9 (patch)
treee0b3b73338bad28326714011c0ad0a2685616d7c
parentbd75bb1687ddd2bcdfe865f3af43f892306bd8af (diff)
downloaddbus-e3d0e2c518f06b3cecb31ab15d55396ba4348fb9.tar.gz
Add a unit test for the dbus-daemon resetting its fd limit
Reviewed-by: David King <dking@redhat.com> [smcv: Fix typo in cmake macro name] Signed-off-by: Simon McVittie <smcv@collabora.com> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=105165 (cherry picked from commit 49ca421997d91d3e01626b2c92a826e6a5db0b2f)
-rw-r--r--cmake/ConfigureChecks.cmake1
-rw-r--r--cmake/config.h.cmake1
-rw-r--r--configure.ac3
-rw-r--r--test/Makefile.am3
-rw-r--r--test/data/valid-config-files/as-another-user.conf.in28
-rw-r--r--test/dbus-daemon.c95
-rwxr-xr-xtools/ci-build.sh7
7 files changed, 131 insertions, 7 deletions
diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake
index 7a03ef1f..4fbf45b8 100644
--- a/cmake/ConfigureChecks.cmake
+++ b/cmake/ConfigureChecks.cmake
@@ -63,6 +63,7 @@ check_symbol_exists(SCM_RIGHTS "sys/types.h;sys/socket.h;sys/un.h" HAVE_UNIX_
check_symbol_exists(prctl "sys/prctl.h" HAVE_PRCTL)
check_symbol_exists(raise "signal.h" HAVE_RAISE)
check_symbol_exists(getrlimit "sys/resource.h;sys/time.h" HAVE_GETRLIMIT)
+check_symbol_exists(prlimit "sys/resource.h;sys/time.h" HAVE_PRLIMIT)
check_symbol_exists(setrlimit "sys/resource.h;sys/time.h" HAVE_SETRLIMIT)
check_struct_member(cmsgcred cmcred_pid "sys/types.h sys/socket.h" HAVE_CMSGCRED) # dbus-sysdeps.c
diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake
index 5a757ef8..d785beea 100644
--- a/cmake/config.h.cmake
+++ b/cmake/config.h.cmake
@@ -228,6 +228,7 @@
#cmakedefine HAVE_DIRFD 1
#cmakedefine HAVE_INOTIFY_INIT1 1
#cmakedefine HAVE_GETRLIMIT 1
+#cmakedefine HAVE_PRLIMIT 1
#cmakedefine HAVE_SETRLIMIT 1
#cmakedefine HAVE_UNIX_FD_PASSING 1
diff --git a/configure.ac b/configure.ac
index cbbcfb6b..a80cc1c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -606,7 +606,7 @@ AC_DEFINE_UNQUOTED([DBUS_USE_SYNC], [$have_sync], [Use the gcc __sync extension]
AC_SEARCH_LIBS(socket,[socket network])
AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)])
-AC_CHECK_FUNCS([vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull issetugid getresuid setresuid getrlimit])
+AC_CHECK_FUNCS([vsnprintf vasprintf nanosleep usleep setenv clearenv unsetenv socketpair getgrouplist fpathconf setrlimit poll setlocale localeconv strtoll strtoull issetugid getresuid setresuid getrlimit prlimit])
AC_CHECK_HEADERS([syslog.h])
if test "x$ac_cv_header_syslog_h" = "xyes"; then
@@ -681,6 +681,7 @@ closedir(dirp);
fi
AC_CHECK_HEADERS(sys/resource.h)
+AC_CHECK_HEADERS([sys/time.h])
AC_CHECK_HEADERS(dirent.h)
diff --git a/test/Makefile.am b/test/Makefile.am
index 1f4057ee..ecf5aed7 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -339,6 +339,7 @@ endif DBUS_ENABLE_INSTALLED_TESTS
in_data = \
data/valid-config-files-system/debug-allow-all-fail.conf.in \
data/valid-config-files-system/debug-allow-all-pass.conf.in \
+ data/valid-config-files/as-another-user.conf.in \
data/valid-config-files/debug-allow-all-sha1.conf.in \
data/valid-config-files/debug-allow-all.conf.in \
data/valid-config-files/finite-timeout.conf.in \
@@ -468,6 +469,7 @@ uninstalled-config-local:
sed \
-e 's,[@]DBUS_TEST_DATA[@],@abs_builddir@/data,' \
-e 's,[@]DBUS_TEST_EXEC[@],@abs_builddir@,' \
+ -e 's,[@]DBUS_USER[@],$(DBUS_USER),' \
-e 's,[@]EXEEXT[@],$(EXEEXT),' \
-e 's,[@]TEST_LAUNCH_HELPER_BINARY[@],@abs_top_builddir@/bus/dbus-daemon-launch-helper-test$(EXEEXT),' \
-e 's,[@]TEST_LISTEN[@],$(TEST_LISTEN),' \
@@ -482,6 +484,7 @@ if DBUS_ENABLE_INSTALLED_TESTS
sed \
-e 's,[@]DBUS_TEST_DATA[@],$(testexecdir)/data,' \
-e 's,[@]DBUS_TEST_EXEC[@],$(testexecdir),' \
+ -e 's,[@]DBUS_USER[@],$(DBUS_USER),' \
-e 's,[@]EXEEXT[@],$(EXEEXT),' \
-e 's,[@]TEST_LAUNCH_HELPER_BINARY[@],/bin/false,' \
-e 's,[@]TEST_LISTEN[@],$(TEST_LISTEN),' \
diff --git a/test/data/valid-config-files/as-another-user.conf.in b/test/data/valid-config-files/as-another-user.conf.in
new file mode 100644
index 00000000..89d00c8c
--- /dev/null
+++ b/test/data/valid-config-files/as-another-user.conf.in
@@ -0,0 +1,28 @@
+<!--
+Configuration similar to the system bus, to be used when testing rlimit
+handling.
+-->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <type>system</type>
+ <user>@DBUS_USER@</user>
+ <auth>EXTERNAL</auth>
+
+ <!-- This is not the same as the real system bus: we don't want to collide -->
+ <listen>@TEST_LISTEN@</listen>
+
+ <policy context="default">
+ <allow user="*"/>
+ <deny own="*"/>
+ <deny send_type="method_call"/>
+ <allow send_type="signal"/>
+ <allow send_requested_reply="true" send_type="method_return"/>
+ <allow send_requested_reply="true" send_type="error"/>
+ <allow receive_type="method_call"/>
+ <allow receive_type="method_return"/>
+ <allow receive_type="error"/>
+ <allow receive_type="signal"/>
+ </policy>
+</busconfig>
diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c
index d940f431..dacad9aa 100644
--- a/test/dbus-daemon.c
+++ b/test/dbus-daemon.c
@@ -40,8 +40,17 @@
#include <string.h>
#ifdef DBUS_UNIX
+# include <pwd.h>
# include <unistd.h>
# include <sys/types.h>
+
+# ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+# endif
+
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
#endif
/* Platforms where we know that credentials-passing passes both the
@@ -124,6 +133,7 @@ typedef struct {
const char *bug_ref;
guint min_messages;
const char *config_file;
+ TestUser user;
enum { SPECIFY_ADDRESS = 0, RELY_ON_DEFAULT } connect_mode;
} Config;
@@ -151,7 +161,7 @@ setup (Fixture *f,
}
address = test_get_dbus_daemon (config ? config->config_file : NULL,
- TEST_USER_ME,
+ config ? config->user : TEST_USER_ME,
&f->daemon_pid);
if (address == NULL)
@@ -646,6 +656,71 @@ test_canonical_path_uae (Fixture *f,
dbus_message_unref (m);
}
+#define DESIRED_RLIMIT 65536
+
+#ifdef DBUS_UNIX
+static void
+test_fd_limit (Fixture *f,
+ gconstpointer context)
+{
+#ifdef HAVE_PRLIMIT
+ struct rlimit lim;
+ const struct passwd *pwd = NULL;
+#endif
+
+ if (f->skip)
+ return;
+
+#ifdef HAVE_PRLIMIT
+
+ if (getuid () != 0)
+ {
+ g_test_skip ("Cannot test, only uid 0 is expected to raise fd limit");
+ return;
+ }
+
+ pwd = getpwnam (DBUS_USER);
+
+ if (pwd == NULL)
+ {
+ gchar *message = g_strdup_printf ("user '%s' does not exist",
+ DBUS_USER);
+
+ g_test_skip (message);
+ g_free (message);
+ return;
+ }
+
+ if (prlimit (getpid (), RLIMIT_NOFILE, NULL, &lim) < 0)
+ g_error ("prlimit(): %s", g_strerror (errno));
+
+ g_test_message ("our RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
+ (long) lim.rlim_cur, (long) lim.rlim_max);
+
+ if (lim.rlim_cur == RLIM_INFINITY || lim.rlim_cur >= DESIRED_RLIMIT)
+ {
+ /* The dbus-daemon will have inherited our large rlimit */
+ g_test_skip ("Cannot test, our own fd limit was already large");
+ return;
+ }
+
+ if (prlimit (f->daemon_pid, RLIMIT_NOFILE, NULL, &lim) < 0)
+ g_error ("prlimit(): %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);
+
+ if (lim.rlim_cur != RLIM_INFINITY)
+ g_assert_cmpint (lim.rlim_cur, >=, DESIRED_RLIMIT);
+
+#else /* !HAVE_PRLIMIT */
+
+ g_test_skip ("prlimit() not supported on this platform");
+
+#endif /* !HAVE_PRLIMIT */
+}
+#endif
+
static void
teardown (Fixture *f,
gconstpointer context G_GNUC_UNUSED)
@@ -705,18 +780,25 @@ teardown (Fixture *f,
static Config limited_config = {
"34393", 10000, "valid-config-files/incoming-limit.conf",
- SPECIFY_ADDRESS
+ TEST_USER_ME, SPECIFY_ADDRESS
};
static Config finite_timeout_config = {
NULL, 1, "valid-config-files/finite-timeout.conf",
- SPECIFY_ADDRESS
+ TEST_USER_ME, SPECIFY_ADDRESS
};
#ifdef DBUS_UNIX
static Config listen_unix_runtime_config = {
"61303", 1, "valid-config-files/listen-unix-runtime.conf",
- RELY_ON_DEFAULT
+ TEST_USER_ME, RELY_ON_DEFAULT
+};
+
+static Config as_another_user_config = {
+ NULL, 1, "valid-config-files/as-another-user.conf",
+ /* We start the dbus-daemon as root and drop privileges, like the
+ * real system bus does */
+ TEST_USER_ROOT, SPECIFY_ADDRESS
};
#endif
@@ -743,6 +825,11 @@ main (int argc,
* and that blocks on a round-trip to the dbus-daemon */
g_test_add ("/unix-runtime-is-default", Fixture, &listen_unix_runtime_config,
setup, test_echo, teardown);
+
+ g_test_add ("/fd-limit/session", Fixture, NULL,
+ setup, test_fd_limit, teardown);
+ g_test_add ("/fd-limit/system", Fixture, &as_another_user_config,
+ setup, test_fd_limit, teardown);
#endif
return g_test_run ();
diff --git a/tools/ci-build.sh b/tools/ci-build.sh
index 1108698a..d4f9d854 100755
--- a/tools/ci-build.sh
+++ b/tools/ci-build.sh
@@ -226,9 +226,12 @@ case "$ci_buildsys" in
gnome-desktop-testing-runner -d /usr/local/share dbus/ || \
maybe_fail_tests
- # these tests benefit from being re-run as root
+ # these tests benefit from being re-run as root, and one
+ # test needs a finite fd limit to be useful
sudo env LD_LIBRARY_PATH=/usr/local/lib \
- gnome-desktop-testing-runner -d /usr/local/share \
+ bash -c 'ulimit -S -n 1024; ulimit -H -n 4096; exec "$@"' bash \
+ gnome-desktop-testing-runner -d /usr/local/share \
+ dbus/test-dbus-daemon_with_config.test \
dbus/test-uid-permissions_with_config.test || \
maybe_fail_tests
fi