From 94b5b236aa0743bacb2139c62d5a6e0143845634 Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Sat, 23 Mar 2019 22:18:11 +0200 Subject: Configure option to disable traditional activation Traditional activation could be disabled if all services use SystemdService activation instead. Provide an example of a hardened DBus systemd service drop-in file for such a setup. Signed-off-by: Topi Miettinen --- bus/Makefile.am | 10 +++++- bus/activation.c | 41 ++++++++++++++++++---- bus/dispatch.c | 22 ++++++++++-- ...m-hardening-without-traditional-activation.conf | 31 ++++++++++++++++ configure.ac | 9 +++++ dbus/Makefile.am | 13 +++++-- test/Makefile.am | 14 ++++++-- test/dbus-daemon.c | 6 ++++ test/name-test/CMakeLists.txt | 10 ++++-- test/name-test/Makefile.am | 9 +++-- 10 files changed, 144 insertions(+), 21 deletions(-) create mode 100644 bus/example-system-hardening-without-traditional-activation.conf diff --git a/bus/Makefile.am b/bus/Makefile.am index 0adc0c89..1595432c 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -67,6 +67,10 @@ examples_DATA = \ example-session-disable-stats.conf \ $(NULL) +dist_examples_DATA = \ + example-system-hardening-without-traditional-activation.conf \ + $(NULL) + if DBUS_ENABLE_LAUNCHD agentdir=$(LAUNCHD_AGENT_DIR) agent_DATA=org.freedesktop.dbus-session.plist @@ -171,8 +175,10 @@ liblaunch_helper_internal_la_LIBADD = \ noinst_PROGRAMS = dbus_daemon_exec_PROGRAMS = dbus-daemon if DBUS_UNIX +if ENABLE_TRADITIONAL_ACTIVATION noinst_LTLIBRARIES += liblaunch-helper-internal.la libexec_PROGRAMS = dbus-daemon-launch-helper +endif ENABLE_TRADITIONAL_ACTIVATION endif DBUS_UNIX install-data-hook: @@ -199,6 +205,7 @@ if DBUS_ENABLE_USER_SESSION endif if DBUS_UNIX +if ENABLE_TRADITIONAL_ACTIVATION install-exec-hook: if test `id -u` -eq 0; then \ chown root:$(DBUS_USER) $(DESTDIR)$(libexecdir)/dbus-daemon-launch-helper$(EXEEXT); \ @@ -207,7 +214,8 @@ install-exec-hook: echo "Not installing $(DESTDIR)$(libexecdir)/dbus-daemon-launch-helper binary setuid!"; \ echo "You'll need to manually set permissions to root:$(DBUS_USER) and permissions 4750"; \ fi -endif +endif ENABLE_TRADITIONAL_ACTIVATION +endif DBUS_UNIX EXTRA_DIST += \ dbus.service.in \ diff --git a/bus/activation.c b/bus/activation.c index 30950636..19ac869a 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -36,7 +36,9 @@ #include #include #include +#ifdef ENABLE_TRADITIONAL_ACTIVATION #include +#endif #include #include #include @@ -106,7 +108,9 @@ typedef struct char *systemd_service; DBusList *entries; int n_entries; +#ifdef ENABLE_TRADITIONAL_ACTIVATION DBusBabysitter *babysitter; +#endif DBusTimeout *timeout; unsigned int timeout_added : 1; } BusPendingActivation; @@ -187,6 +191,7 @@ bus_pending_activation_unref (BusPendingActivation *pending_activation) if (pending_activation->timeout) _dbus_timeout_unref (pending_activation->timeout); +#ifdef ENABLE_TRADITIONAL_ACTIVATION if (pending_activation->babysitter) { if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter, @@ -197,6 +202,7 @@ bus_pending_activation_unref (BusPendingActivation *pending_activation) _dbus_babysitter_unref (pending_activation->babysitter); } +#endif dbus_free (pending_activation->service_name); dbus_free (pending_activation->exec); @@ -1068,6 +1074,7 @@ bus_activation_unref (BusActivation *activation) dbus_free (activation); } +#ifdef ENABLE_TRADITIONAL_ACTIVATION static dbus_bool_t add_bus_environment (BusActivation *activation, DBusError *error) @@ -1108,6 +1115,7 @@ add_bus_environment (BusActivation *activation, return TRUE; } +#endif typedef struct { @@ -1387,6 +1395,7 @@ pending_activation_failed (BusPendingActivation *pending_activation, pending_activation->service_name); } +#ifdef ENABLE_TRADITIONAL_ACTIVATION /** * Depending on the exit code of the helper, set the error accordingly */ @@ -1557,6 +1566,7 @@ toggle_babysitter_watch (DBusWatch *watch, _dbus_loop_toggle_watch (bus_context_get_loop (pending_activation->activation->context), watch); } +#endif static dbus_bool_t pending_activation_timed_out (void *data) @@ -1569,12 +1579,14 @@ pending_activation_timed_out (void *data) context = pending_activation->activation->context; timeout = bus_context_get_activation_timeout (context); +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* Kill the spawned process, since it sucks * (not sure this is what we want to do, but * may as well try it for now) */ if (pending_activation->babysitter) _dbus_babysitter_kill_child (pending_activation->babysitter); +#endif dbus_error_init (&error); @@ -1599,8 +1611,10 @@ cancel_pending (void *data) _dbus_verbose ("Canceling pending activation of %s\n", pending_activation->service_name); +#ifdef ENABLE_TRADITIONAL_ACTIVATION if (pending_activation->babysitter) _dbus_babysitter_kill_child (pending_activation->babysitter); +#endif _dbus_hash_table_remove_string (pending_activation->activation->pending_activations, pending_activation->service_name); @@ -1696,11 +1710,13 @@ activation_find_entry (BusActivation *activation, return entry; } +#ifdef ENABLE_TRADITIONAL_ACTIVATION static char ** bus_activation_get_environment (BusActivation *activation) { return _dbus_hash_table_to_array (activation->environment, '='); } +#endif dbus_bool_t bus_activation_set_environment_variable (BusActivation *activation, @@ -1741,6 +1757,7 @@ out: return retval; } +#ifdef ENABLE_TRADITIONAL_ACTIVATION static void child_setup (void *user_data) { @@ -1764,6 +1781,7 @@ child_setup (void *user_data) } #endif } +#endif /* @@ -1790,21 +1808,23 @@ bus_activation_activate_service (BusActivation *activation, const char *service_name, DBusError *error) { - DBusError tmp_error; BusActivationEntry *entry; BusPendingActivation *pending_activation; BusPendingActivationEntry *pending_activation_entry; DBusMessage *message; DBusString service_str; - const char *servicehelper; - char **argv; - char **envp = NULL; - int argc; dbus_bool_t retval; dbus_bool_t was_pending_activation; - DBusString command; int limit; +#ifdef ENABLE_TRADITIONAL_ACTIVATION + DBusError tmp_error; + DBusString command; + char **argv; + char **envp = NULL; + int argc; + const char *servicehelper; DBusSpawnFlags flags = DBUS_SPAWN_NONE; +#endif _dbus_assert (activation != NULL); _dbus_assert (transaction != NULL); @@ -2174,6 +2194,7 @@ bus_activation_activate_service (BusActivation *activation, proceed with traditional activation. */ } +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* If entry was NULL, it would be because we were doing systemd activation * and activating systemd itself; but we already handled that case with * an early-return */ @@ -2323,7 +2344,13 @@ bus_activation_activate_service (BusActivation *activation, } return TRUE; - +#else /* !TRADITIONAL_ACTIVATION */ + bus_context_log (activation->context, + DBUS_SYSTEM_LOG_INFO, "Cannot activate service name='%s' requested by '%s' (%s): SystemdService not configured and dbus was compiled with --disable-traditional-activation", + service_name, + bus_connection_get_name (connection), + bus_connection_get_loginfo (connection)); +#endif cancel_pending_activation: _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_hash_table_remove_string (activation->pending_activations, diff --git a/bus/dispatch.c b/bus/dispatch.c index e91a8255..c3019b1e 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -639,6 +639,7 @@ pop_message_waiting_for_memory (DBusConnection *connection) return dbus_connection_pop_message (connection); } +#ifdef ENABLE_TRADITIONAL_ACTIVATION static DBusMessage* borrow_message_waiting_for_memory (DBusConnection *connection) { @@ -648,6 +649,7 @@ borrow_message_waiting_for_memory (DBusConnection *connection) return dbus_connection_borrow_message (connection); } +#endif static void warn_unexpected_real (DBusConnection *connection, @@ -1156,6 +1158,7 @@ check_hello_message (BusContext *context, return retval; } +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* returns TRUE if the correct thing happens, * but the correct thing may include OOM errors. */ @@ -1552,6 +1555,7 @@ check_get_connection_unix_process_id (BusContext *context, return retval; } +#endif /* returns TRUE if the correct thing happens, * but the correct thing may include OOM errors. @@ -1685,7 +1689,7 @@ check_add_match (BusContext *context, return retval; } -#ifdef DBUS_ENABLE_STATS +#if defined(ENABLE_TRADITIONAL_ACTIVATION) && defined(DBUS_ENABLE_STATS) /* returns TRUE if the correct thing happens, * but the correct thing may include OOM errors. */ @@ -1863,6 +1867,7 @@ check_hello_connection (BusContext *context, #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn" +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* returns TRUE if the correct thing happens, * but the correct thing may include OOM errors. */ @@ -3190,10 +3195,12 @@ check_segfault_service_auto_start (BusContext *context, return retval; } +#endif #define TEST_ECHO_MESSAGE "Test echo message" #define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self" +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* returns TRUE if the correct thing happens, * but the correct thing may include OOM errors. */ @@ -3708,8 +3715,9 @@ check_launch_service_file_missing (BusContext *context, return retval; } +#endif -#ifndef DBUS_WIN +#if defined(ENABLE_TRADITIONAL_ACTIVATION) && !defined(DBUS_WIN) #define SERVICE_USER_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoUser" @@ -4018,6 +4026,7 @@ check_launch_service_service_missing (BusContext *context, #define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail" +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* returns TRUE if the correct thing happens, * but the correct thing may include OOM errors. */ @@ -4701,6 +4710,7 @@ check_list_services (BusContext *context, return retval; } +#endif typedef struct { @@ -4751,6 +4761,7 @@ check2_try_iterations (BusContext *context, _dbus_test_fatal ("%s failed during oom", description); } +#ifdef ENABLE_TRADITIONAL_ACTIVATION static dbus_bool_t setenv_TEST_LAUNCH_HELPER_CONFIG(const DBusString *test_data_dir, const char *filename) @@ -4912,6 +4923,7 @@ bus_dispatch_test_conf (const DBusString *test_data_dir, check_shell_fail_service_auto_start); _dbus_test_ok ("%s:%s - check_shell_fail_service_auto_start", _DBUS_FUNCTION_NAME, filename); +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* specific to launcher */ if (use_launcher) { @@ -4920,6 +4932,7 @@ bus_dispatch_test_conf (const DBusString *test_data_dir, _dbus_test_ok ("%s:%s - check_launch_service_file_missing", _DBUS_FUNCTION_NAME, filename); } +#endif #if 0 /* Note: need to resolve some issues with the testing code in order to run @@ -4955,8 +4968,9 @@ bus_dispatch_test_conf (const DBusString *test_data_dir, _dbus_test_ok ("%s:%s", _DBUS_FUNCTION_NAME, filename); return TRUE; } +#endif -#ifndef DBUS_WIN +#if defined(ENABLE_TRADITIONAL_ACTIVATION) && !defined(DBUS_WIN) static dbus_bool_t bus_dispatch_test_conf_fail (const DBusString *test_data_dir, const char *filename) @@ -5029,6 +5043,7 @@ bus_dispatch_test (const char *test_data_dir_cstr) _dbus_string_init_const (&test_data_dir, test_data_dir_cstr); +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* run normal activation tests */ _dbus_verbose ("Normal activation tests\n"); if (!bus_dispatch_test_conf (&test_data_dir, @@ -5046,6 +5061,7 @@ bus_dispatch_test (const char *test_data_dir_cstr) if (!bus_dispatch_test_conf_fail (&test_data_dir, "valid-config-files-system/debug-allow-all-fail.conf")) return FALSE; +#endif #endif return TRUE; diff --git a/bus/example-system-hardening-without-traditional-activation.conf b/bus/example-system-hardening-without-traditional-activation.conf new file mode 100644 index 00000000..2665c9a8 --- /dev/null +++ b/bus/example-system-hardening-without-traditional-activation.conf @@ -0,0 +1,31 @@ +# Example drop-in file (dbus.service.d/override.conf) for systemd +# service. This version has many hardening options enabled and thus +# it is only suitable for cases where only systemd activation is used +# or traditional activation disabled by compiling dbus with +# --disable-traditional-activation. + +[Service] +CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_SYS_RESOURCE CAP_AUDIT_WRITE +DeviceAllow=/dev/null rw +DeviceAllow=/dev/urandom r +DevicePolicy=strict +IPAddressDeny=any +LimitMEMLOCK=0 +LockPersonality=yes +MemoryDenyWriteExecute=yes +NoNewPrivileges=yes +PrivateDevices=yes +PrivateTmp=yes +ProtectControlGroups=yes +ProtectHome=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +ProtectSystem=strict +ReadOnlyPaths=-/ +RestrictAddressFamilies=AF_UNIX +RestrictNamespaces=yes +RestrictRealtime=yes +SystemCallArchitectures=native +SystemCallFilter=@system-service +SystemCallFilter=~@chown @clock @cpu-emulation @debug @module @mount @obsolete @raw-io @reboot @resources @swap memfd_create mincore mlock mlockall personality +UMask=0077 diff --git a/configure.ac b/configure.ac index 83b3eb72..16e1ae4d 100644 --- a/configure.ac +++ b/configure.ac @@ -217,6 +217,7 @@ AC_ARG_ENABLE(kqueue, AS_HELP_STRING([--enable-kqueue],[build with kqueue suppor AC_ARG_ENABLE(console-owner-file, AS_HELP_STRING([--enable-console-owner-file],[enable console owner file]),enable_console_owner_file=$enableval,enable_console_owner_file=auto) AC_ARG_ENABLE(launchd, AS_HELP_STRING([--enable-launchd],[build with launchd auto-launch support]),enable_launchd=$enableval,enable_launchd=auto) AC_ARG_ENABLE(systemd, AS_HELP_STRING([--enable-systemd],[build with systemd at_console support]),enable_systemd=$enableval,enable_systemd=auto) +AC_ARG_ENABLE(traditional-activation, AS_HELP_STRING([--disable-traditional-activation], [Do not build support for service activation without using SystemdService]), enable_traditional_activation="$enableval", enable_traditional_activation=yes) AC_ARG_WITH(session-socket-dir, AS_HELP_STRING([--with-session-socket-dir=[dirname]],[Where to put sockets for the per-login-session message bus])) AC_ARG_WITH(test-socket-dir, AS_HELP_STRING([--with-test-socket-dir=[dirname]],[Where to put sockets for make check])) @@ -1043,6 +1044,13 @@ if test x$enable_systemd = xyes -a x$have_systemd != xyes ; then AC_MSG_ERROR([Explicitly requested systemd support, but systemd not found]) fi +AS_IF([test "x$enable_traditional_activation" = xyes], + AC_DEFINE(ENABLE_TRADITIONAL_ACTIVATION,[1], [Enable traditional activation without using systemd]) + AS_IF([test "x$enable_systemd" = xno], + AC_MSG_WARN([Traditional activation and systemd activation are both disabled, so service activation (automatically starting services that receive messages) will not work]))) + +AM_CONDITIONAL(ENABLE_TRADITIONAL_ACTIVATION, test x$enable_traditional_activation = xyes) + # If not found in $PATH, we might still have systemd and systemctl at runtime # (perhaps dbus is being compiled in a minimal chroot with no systemd). # Assume the upstream-recommended location. Distributors with split /usr @@ -1798,6 +1806,7 @@ echo " Building inotify support: ${have_inotify} Building kqueue support: ${have_kqueue} Building systemd support: ${have_systemd} + Traditional activation: ${enable_traditional_activation} Building X11 code: ${have_x11} Building Doxygen docs: ${enable_doxygen_docs} Building Ducktype docs: ${enable_ducktype_docs} diff --git a/dbus/Makefile.am b/dbus/Makefile.am index 8c9551df..ceed5ddf 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -85,8 +85,12 @@ DBUS_SHARED_arch_sources = \ dbus-transport-win.h DBUS_UTIL_arch_sources = \ - dbus-sysdeps-util-win.c \ - dbus-spawn-win.c + dbus-sysdeps-util-win.c + +if ENABLE_TRADITIONAL_ACTIVATION +DBUS_UTIL_arch_sources += dbus-spawn-win.c +endif + else if DBUS_ENABLE_LAUNCHD @@ -117,8 +121,11 @@ DBUS_SHARED_arch_sources = \ DBUS_UTIL_arch_sources = \ dbus-sysdeps-util-unix.c \ dbus-userdb-util.c \ - dbus-spawn-unix.c \ $(NULL) + +if ENABLE_TRADITIONAL_ACTIVATION +DBUS_UTIL_arch_sources += dbus-spawn-unix.c +endif endif if DBUS_HAVE_LINUX_EPOLL diff --git a/test/Makefile.am b/test/Makefile.am index 95a4592f..27d19460 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -67,7 +67,6 @@ uninstallable_test_programs = ## break-loader removed for now ## these binaries are used in tests but are not themselves tests TEST_BINARIES = \ - test-spawn \ test-exit \ test-names \ test-privserver \ @@ -76,7 +75,13 @@ TEST_BINARIES = \ $(NULL) if !DBUS_WINCE +if ENABLE_TRADITIONAL_ACTIVATION uninstallable_test_programs += test-spawn-oom +endif ENABLE_TRADITIONAL_ACTIVATION +endif !DBUS_WINCE + +if ENABLE_TRADITIONAL_ACTIVATION +TEST_BINARIES += test-spawn endif uninstallable_test_programs += \ @@ -90,11 +95,13 @@ uninstallable_test_programs += \ $(NULL) if DBUS_UNIX +if ENABLE_TRADITIONAL_ACTIVATION uninstallable_test_programs += test-bus-launch-helper-oom uninstallable_test_programs += test-bus-system # this is used by the tests but is not, itself, a test TEST_BINARIES += dbus-daemon-launch-helper-for-tests -endif +endif ENABLE_TRADITIONAL_ACTIVATION +endif DBUS_UNIX noinst_PROGRAMS += $(uninstallable_test_programs) TESTS += $(uninstallable_test_programs) @@ -120,10 +127,13 @@ test_privserver_LDADD = libdbus-testutils.la test_shell_service_LDADD = libdbus-testutils.la test_shell_SOURCES = shell-test.c test_shell_LDADD = libdbus-testutils.la + +if ENABLE_TRADITIONAL_ACTIVATION test_spawn_SOURCES = spawn-test.c test_spawn_LDADD = $(top_builddir)/dbus/libdbus-internal.la test_spawn_oom_SOURCES = internals/spawn-oom.c test_spawn_oom_LDADD = libdbus-testutils.la +endif test_assertions_SOURCES = internals/assertions.c test_assertions_LDADD = libdbus-testutils.la $(GLIB_LIBS) diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c index e4e11f16..1685fd7b 100644 --- a/test/dbus-daemon.c +++ b/test/dbus-daemon.c @@ -1980,6 +1980,7 @@ test_fd_limit (Fixture *f, #define ECHO_SERVICE_PATH "/org/freedesktop/TestSuite" #define ECHO_SERVICE_INTERFACE "org.freedesktop.TestSuite" +#ifdef ENABLE_TRADITIONAL_ACTIVATION /* * Helper for test_activation_forking: whenever the forking service is * activated, start it again. @@ -2194,6 +2195,7 @@ test_system_signals (Fixture *f, dbus_connection_remove_filter (f->left_conn, foo_signal_filter, f); } #endif +#endif static void teardown (Fixture *f, @@ -2325,6 +2327,7 @@ static Config as_another_user_config = { TEST_USER_ROOT, SPECIFY_ADDRESS }; +#ifdef ENABLE_TRADITIONAL_ACTIVATION static Config tmp_session_config = { NULL, 1, "valid-config-files/tmp-session.conf", TEST_USER_ME, SPECIFY_ADDRESS @@ -2335,6 +2338,7 @@ static Config nearly_system_config = { TEST_USER_ME, SPECIFY_ADDRESS }; #endif +#endif int main (int argc, @@ -2418,10 +2422,12 @@ main (int argc, g_test_add ("/fd-limit/system", Fixture, &as_another_user_config, setup, test_fd_limit, teardown); +#ifdef ENABLE_TRADITIONAL_ACTIVATION g_test_add ("/activation/forking", Fixture, &tmp_session_config, setup, test_activation_forking, teardown); g_test_add ("/system-policy/allow-signals", Fixture, &nearly_system_config, setup, test_system_signals, teardown); +#endif #endif ret = g_test_run (); diff --git a/test/name-test/CMakeLists.txt b/test/name-test/CMakeLists.txt index dabf892a..32f060a2 100644 --- a/test/name-test/CMakeLists.txt +++ b/test/name-test/CMakeLists.txt @@ -6,8 +6,12 @@ add_helper_executable(test-autolaunch test-autolaunch.c dbus-testutils) add_helper_executable(test-privserver-client test-privserver-client.c dbus-testutils) add_session_test_executable(test-ids test-ids.c ${DBUS_INTERNAL_LIBRARIES}) -add_session_test_executable(test-pending-call-dispatch test-pending-call-dispatch.c ${DBUS_INTERNAL_LIBRARIES}) -add_session_test_executable(test-pending-call-timeout test-pending-call-timeout.c ${DBUS_INTERNAL_LIBRARIES}) +if (ENABLE_TRADITIONAL_ACTIVATION) + add_session_test_executable(test-pending-call-dispatch test-pending-call-dispatch.c ${DBUS_INTERNAL_LIBRARIES}) + add_session_test_executable(test-pending-call-timeout test-pending-call-timeout.c ${DBUS_INTERNAL_LIBRARIES}) +endif() add_session_test_executable(test-shutdown test-shutdown.c dbus-testutils) -add_session_test_executable(test-thread-init test-threads-init.c ${DBUS_INTERNAL_LIBRARIES}) +if (ENABLE_TRADITIONAL_ACTIVATION) + add_session_test_executable(test-thread-init test-threads-init.c ${DBUS_INTERNAL_LIBRARIES}) +endif() endif() diff --git a/test/name-test/Makefile.am b/test/name-test/Makefile.am index bffe679a..81938778 100644 --- a/test/name-test/Makefile.am +++ b/test/name-test/Makefile.am @@ -51,15 +51,20 @@ TESTS += \ run-test.sh \ run-test-systemserver.sh \ test-ids \ + test-pending-call-disconnected \ + test-shutdown \ + $(NULL) + +if ENABLE_TRADITIONAL_ACTIVATION +TESTS += \ test-pending-call-dispatch \ test-pending-call-timeout \ - test-pending-call-disconnected \ test-privserver-client \ - test-shutdown \ test-threads-init \ $(NULL) endif endif +endif EXTRA_DIST=run-test.sh run-test-systemserver.sh -- cgit v1.2.1