diff options
-rw-r--r-- | bus/Makefile.am | 12 | ||||
-rw-r--r-- | bus/activation.c | 104 | ||||
-rw-r--r-- | bus/activation.h | 4 | ||||
-rw-r--r-- | bus/bus.c | 23 | ||||
-rw-r--r-- | bus/selinux.c | 118 | ||||
-rw-r--r-- | bus/selinux.h | 2 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | dbus/Makefile.am | 1 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 2 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-util-unix.c | 155 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 2 | ||||
-rw-r--r-- | test/test-service.c | 5 | ||||
-rw-r--r-- | tools/dbus-launch.c | 2 | ||||
-rw-r--r-- | tools/dbus-monitor.c | 14 |
14 files changed, 221 insertions, 228 deletions
diff --git a/bus/Makefile.am b/bus/Makefile.am index b1ee36c8..72233f10 100644 --- a/bus/Makefile.am +++ b/bus/Makefile.am @@ -103,8 +103,8 @@ dbus_daemon_launch_helper_SOURCES= \ $(LAUNCH_HELPER_SOURCES) dbus_daemon_launch_helper_LDADD= \ - $(DBUS_LAUNCHER_LIBS) \ - $(top_builddir)/dbus/libdbus-convenience.la + $(top_builddir)/dbus/libdbus-convenience.la \ + $(DBUS_LAUNCHER_LIBS) dbus_daemon_launch_helper_LDFLAGS=@R_DYNAMIC_LDFLAG@ @SECTION_LDFLAGS@ @@ -115,8 +115,8 @@ dbus_daemon_launch_helper_test_SOURCES= \ $(LAUNCH_HELPER_SOURCES) dbus_daemon_launch_helper_test_LDADD= \ - $(DBUS_LAUNCHER_LIBS) \ - $(top_builddir)/dbus/libdbus-convenience.la + $(top_builddir)/dbus/libdbus-convenience.la \ + $(DBUS_LAUNCHER_LIBS) dbus_daemon_launch_helper_test_LDFLAGS=@R_DYNAMIC_LDFLAG@ @SECTION_LDFLAGS@ dbus_daemon_launch_helper_test_CPPFLAGS= \ @@ -129,8 +129,8 @@ bus_test_launch_helper_SOURCES= \ $(LAUNCH_HELPER_SOURCES) bus_test_launch_helper_LDADD= \ - $(DBUS_LAUNCHER_LIBS) \ - $(top_builddir)/dbus/libdbus-convenience.la + $(top_builddir)/dbus/libdbus-convenience.la \ + $(DBUS_LAUNCHER_LIBS) bus_test_launch_helper_LDFLAGS=@R_DYNAMIC_LDFLAG@ @SECTION_LDFLAGS@ bus_test_launch_helper_CPPFLAGS= \ diff --git a/bus/activation.c b/bus/activation.c index 00caac27..0a28df16 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -735,74 +735,56 @@ out: return retval; } -BusActivation* -bus_activation_new (BusContext *context, - const DBusString *address, - DBusList **directories, - DBusError *error) +dbus_bool_t +bus_activation_reload (BusActivation *activation, + const DBusString *address, + DBusList **directories, + DBusError *error) { - BusActivation *activation; DBusList *link; char *dir; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - activation = dbus_new0 (BusActivation, 1); - if (activation == NULL) - { - BUS_SET_OOM (error); - return NULL; - } - - activation->refcount = 1; - activation->context = context; - activation->n_pending_activations = 0; - + + if (activation->server_address != NULL) + dbus_free (activation->server_address); if (!_dbus_string_copy_data (address, &activation->server_address)) { BUS_SET_OOM (error); goto failed; } - + + if (activation->entries != NULL) + _dbus_hash_table_unref (activation->entries); activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, (DBusFreeFunction)bus_activation_entry_unref); if (activation->entries == NULL) - { - BUS_SET_OOM (error); - goto failed; - } - - activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, - (DBusFreeFunction)bus_pending_activation_unref); - - if (activation->pending_activations == NULL) { BUS_SET_OOM (error); goto failed; } + if (activation->directories != NULL) + _dbus_hash_table_unref (activation->directories); activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, (DBusFreeFunction)bus_service_directory_unref); - - if (activation->directories == NULL) + + if (activation->directories == NULL) { BUS_SET_OOM (error); goto failed; } - - /* Load service files */ + link = _dbus_list_get_first_link (directories); while (link != NULL) { BusServiceDirectory *s_dir; - + dir = _dbus_strdup ((const char *) link->data); if (!dir) { BUS_SET_OOM (error); goto failed; } - + s_dir = dbus_new0 (BusServiceDirectory, 1); if (!s_dir) { @@ -813,7 +795,7 @@ bus_activation_new (BusContext *context, s_dir->refcount = 1; s_dir->dir_c = dir; - + s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, (DBusFreeFunction)bus_activation_entry_unref); @@ -833,8 +815,8 @@ bus_activation_new (BusContext *context, /* only fail on OOM, it is ok if we can't read the directory */ if (!update_directory (activation, s_dir, error)) - { - if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) + { + if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) goto failed; else dbus_error_free (error); @@ -843,10 +825,52 @@ bus_activation_new (BusContext *context, link = _dbus_list_get_next_link (directories, link); } + return TRUE; + failed: + return FALSE; +} + +BusActivation* +bus_activation_new (BusContext *context, + const DBusString *address, + DBusList **directories, + DBusError *error) +{ + BusActivation *activation; + DBusList *link; + char *dir; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + activation = dbus_new0 (BusActivation, 1); + if (activation == NULL) + { + BUS_SET_OOM (error); + return NULL; + } + + activation->refcount = 1; + activation->context = context; + activation->n_pending_activations = 0; + + if (!bus_activation_reload (activation, address, directories, error)) + goto failed; + + /* Initialize this hash table once, we don't want to lose pending + * activations on reload. */ + activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, + (DBusFreeFunction)bus_pending_activation_unref); + + if (activation->pending_activations == NULL) + { + BUS_SET_OOM (error); + goto failed; + } + activation->environment = _dbus_hash_table_new (DBUS_HASH_STRING, (DBusFreeFunction) dbus_free, (DBusFreeFunction) dbus_free); - + if (activation->environment == NULL) { BUS_SET_OOM (error); diff --git a/bus/activation.h b/bus/activation.h index 2dff812a..03bfed28 100644 --- a/bus/activation.h +++ b/bus/activation.h @@ -32,6 +32,10 @@ BusActivation* bus_activation_new (BusContext *context, const DBusString *address, DBusList **directories, DBusError *error); +dbus_bool_t bus_activation_reload (BusActivation *activation, + const DBusString *address, + DBusList **directories, + DBusError *error); BusActivation* bus_activation_ref (BusActivation *activation); void bus_activation_unref (BusActivation *activation); @@ -444,6 +444,8 @@ process_config_every_time (BusContext *context, /* get our limits and timeout lengths */ bus_config_parser_get_limits (parser, &context->limits); + if (context->policy) + bus_policy_unref (context->policy); context->policy = bus_config_parser_steal_policy (parser); _dbus_assert (context->policy != NULL); @@ -507,21 +509,24 @@ process_config_every_time (BusContext *context, dbus_free(context->servicehelper); context->servicehelper = s; } - + /* Create activation subsystem */ - new_activation = bus_activation_new (context, &full_address, - dirs, error); - if (new_activation == NULL) + if (context->activation) + { + if (!bus_activation_reload (context->activation, &full_address, dirs, error)) + goto failed; + } + else + { + context->activation = bus_activation_new (context, &full_address, dirs, error); + } + + if (context->activation == NULL) { _DBUS_ASSERT_ERROR_IS_SET (error); goto failed; } - if (is_reload) - bus_activation_unref (context->activation); - - context->activation = new_activation; - /* Drop existing conf-dir watches (if applicable) */ if (is_reload) diff --git a/bus/selinux.c b/bus/selinux.c index df9a00b1..456723ac 100644 --- a/bus/selinux.c +++ b/bus/selinux.c @@ -22,6 +22,7 @@ */ #include <dbus/dbus-internals.h> #include <dbus/dbus-string.h> +#include <dbus/dbus-userdb.h> #include "selinux.h" #include "services.h" #include "policy.h" @@ -44,7 +45,9 @@ #include <signal.h> #include <stdarg.h> #include <stdio.h> +#include <grp.h> #ifdef HAVE_LIBAUDIT +#include <cap-ng.h> #include <libaudit.h> #endif /* HAVE_LIBAUDIT */ #endif /* HAVE_SELINUX */ @@ -143,13 +146,17 @@ log_callback (const char *fmt, ...) #ifdef HAVE_LIBAUDIT if (audit_fd >= 0) { - char buf[PATH_MAX*2]; + capng_get_caps_process(); + if (capng_have_capability(CAPNG_EFFECTIVE, CAP_AUDIT_WRITE)) + { + char buf[PATH_MAX*2]; - /* FIXME: need to change this to show real user */ - vsnprintf(buf, sizeof(buf), fmt, ap); - audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, + /* FIXME: need to change this to show real user */ + vsnprintf(buf, sizeof(buf), fmt, ap); + audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, NULL, getuid()); - return; + return; + } } #endif /* HAVE_LIBAUDIT */ @@ -1010,3 +1017,104 @@ bus_selinux_shutdown (void) #endif /* HAVE_SELINUX */ } +/** + * Changes the user and group the bus is running as. + * + * @param user the user to become + * @param error return location for errors + * @returns #FALSE on failure + */ +dbus_bool_t +_dbus_change_to_daemon_user (const char *user, + DBusError *error) +{ + dbus_uid_t uid; + dbus_gid_t gid; + DBusString u; + + _dbus_string_init_const (&u, user); + + if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "User '%s' does not appear to exist?", + user); + return FALSE; + } + +#ifdef HAVE_LIBAUDIT + /* If we were root */ + if (_dbus_geteuid () == 0) + { + int rc; + + capng_clear (CAPNG_SELECT_BOTH); + capng_update (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, + CAP_AUDIT_WRITE); + rc = capng_change_id (uid, gid, 0); + if (rc) + { + switch (rc) { + default: + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to drop capabilities: %s\n", + _dbus_strerror (errno)); + break; + case -4: + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to set GID to %lu: %s", gid, + _dbus_strerror (errno)); + break; + case -5: + _dbus_warn ("Failed to drop supplementary groups: %s\n", + _dbus_strerror (errno)); + break; + case -6: + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to set UID to %lu: %s", uid, + _dbus_strerror (errno)); + break; + case -7: + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to unset keep-capabilities: %s\n", + _dbus_strerror (errno)); + break; + } + return FALSE; + } + } +#else + /* setgroups() only works if we are a privileged process, + * so we don't return error on failure; the only possible + * failure is that we don't have perms to do it. + * + * not sure this is right, maybe if setuid() + * is going to work then setgroups() should also work. + */ + if (setgroups (0, NULL) < 0) + _dbus_warn ("Failed to drop supplementary groups: %s\n", + _dbus_strerror (errno)); + + /* Set GID first, or the setuid may remove our permission + * to change the GID + */ + if (setgid (gid) < 0) + { + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to set GID to %lu: %s", gid, + _dbus_strerror (errno)); + return FALSE; + } + + if (setuid (uid) < 0) + { + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to set UID to %lu: %s", uid, + _dbus_strerror (errno)); + return FALSE; + } +#endif /* !HAVE_LIBAUDIT */ + + return TRUE; +} + diff --git a/bus/selinux.h b/bus/selinux.h index 3bab36de..f208fbeb 100644 --- a/bus/selinux.h +++ b/bus/selinux.h @@ -68,5 +68,7 @@ BusSELinuxID* bus_selinux_init_connection_id (DBusConnection *connection, void bus_selinux_audit_init(void); +dbus_bool_t _dbus_change_to_daemon_user (const char *user, + DBusError *error); #endif /* BUS_SELINUX_H */ diff --git a/configure.in b/configure.in index 124f2705..bda6716b 100644 --- a/configure.in +++ b/configure.in @@ -877,7 +877,7 @@ else AC_CHECK_LIB(audit, audit_log_user_avc_message, have_libaudit=yes, have_libaudit=no) if test x$have_libaudit = xyes ; then - AC_CHECK_LIB(cap, cap_set_proc, + AC_CHECK_LIB(cap-ng, capng_clear, have_libaudit=yes, have_libaudit=no) fi fi @@ -885,8 +885,7 @@ fi AM_CONDITIONAL(HAVE_LIBAUDIT, test x$have_libaudit = xyes) if test x$have_libaudit = xyes ; then - SELINUX_LIBS="$SELINUX_LIBS -laudit" - LIBS="-lcap $LIBS" + SELINUX_LIBS="$SELINUX_LIBS -laudit -lcap-ng" AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support]) fi diff --git a/dbus/Makefile.am b/dbus/Makefile.am index cabe2b0f..1c710ac5 100644 --- a/dbus/Makefile.am +++ b/dbus/Makefile.am @@ -247,6 +247,7 @@ noinst_LTLIBRARIES=libdbus-convenience.la libdbus_1_la_LIBADD= $(DBUS_CLIENT_LIBS) libdbus_1_la_LDFLAGS= $(export_symbols) -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -no-undefined @R_DYNAMIC_LDFLAG@ @PIC_LDFLAGS@ +libdbus_convenience_la_LIBADD=$(DBUS_CLIENT_LIBS) libdbus_convenience_la_LDFLAGS=@R_DYNAMIC_LDFLAG@ ## note that TESTS has special meaning (stuff to use in make check) diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 0d3e999b..5d9c404f 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -1550,7 +1550,7 @@ _dbus_read_credentials_socket (int client_fd, #elif defined(HAVE_CMSGCRED) struct cmsgcred *cred; - cred = (struct cmsgcred *) CMSG_DATA (&cmsg); + cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); pid_read = cred->cmcred_pid; uid_read = cred->cmcred_euid; #elif defined(LOCAL_CREDS) diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index d969d0a0..cf77f0a6 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -44,12 +44,6 @@ #include <dirent.h> #include <sys/un.h> #include <syslog.h> -#include <syslog.h> -#ifdef HAVE_LIBAUDIT -#include <sys/prctl.h> -#include <sys/capability.h> -#include <libaudit.h> -#endif /* HAVE_LIBAUDIT */ #ifdef HAVE_SYS_SYSLIMITS_H #include <sys/syslimits.h> @@ -309,155 +303,6 @@ _dbus_verify_daemon_user (const char *user) return _dbus_get_user_id_and_primary_group (&u, NULL, NULL); } -/** - * Changes the user and group the bus is running as. - * - * @param user the user to become - * @param error return location for errors - * @returns #FALSE on failure - */ -dbus_bool_t -_dbus_change_to_daemon_user (const char *user, - DBusError *error) -{ - dbus_uid_t uid; - dbus_gid_t gid; - DBusString u; -#ifdef HAVE_LIBAUDIT - dbus_bool_t we_were_root; - cap_t new_caps; -#endif - - _dbus_string_init_const (&u, user); - - if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid)) - { - dbus_set_error (error, DBUS_ERROR_FAILED, - "User '%s' does not appear to exist?", - user); - return FALSE; - } - -#ifdef HAVE_LIBAUDIT - we_were_root = _dbus_geteuid () == 0; - new_caps = NULL; - /* have a tmp set of caps that we use to transition to the usr/grp dbus should - * run as ... doesn't really help. But keeps people happy. - */ - - if (we_were_root) - { - cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE }; - cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID }; - cap_t tmp_caps = cap_init(); - - if (!tmp_caps || !(new_caps = cap_init ())) - { - dbus_set_error (error, DBUS_ERROR_FAILED, - "Failed to initialize drop of capabilities: %s\n", - _dbus_strerror (errno)); - - if (tmp_caps) - cap_free (tmp_caps); - - return FALSE; - } - - /* assume these work... */ - cap_set_flag (new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET); - cap_set_flag (new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET); - cap_set_flag (tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET); - cap_set_flag (tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET); - - if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to set keep-capabilities: %s\n", - _dbus_strerror (errno)); - cap_free (tmp_caps); - goto fail; - } - - if (cap_set_proc (tmp_caps) == -1) - { - dbus_set_error (error, DBUS_ERROR_FAILED, - "Failed to drop capabilities: %s\n", - _dbus_strerror (errno)); - cap_free (tmp_caps); - goto fail; - } - cap_free (tmp_caps); - } -#endif /* HAVE_LIBAUDIT */ - - /* setgroups() only works if we are a privileged process, - * so we don't return error on failure; the only possible - * failure is that we don't have perms to do it. - * - * not sure this is right, maybe if setuid() - * is going to work then setgroups() should also work. - */ - if (setgroups (0, NULL) < 0) - _dbus_warn ("Failed to drop supplementary groups: %s\n", - _dbus_strerror (errno)); - - /* Set GID first, or the setuid may remove our permission - * to change the GID - */ - if (setgid (gid) < 0) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to set GID to %lu: %s", gid, - _dbus_strerror (errno)); - goto fail; - } - - if (setuid (uid) < 0) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to set UID to %lu: %s", uid, - _dbus_strerror (errno)); - goto fail; - } - -#ifdef HAVE_LIBAUDIT - if (we_were_root) - { - if (cap_set_proc (new_caps)) - { - dbus_set_error (error, DBUS_ERROR_FAILED, - "Failed to drop capabilities: %s\n", - _dbus_strerror (errno)); - goto fail; - } - cap_free (new_caps); - - /* should always work, if it did above */ - if (prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1) - { - dbus_set_error (error, _dbus_error_from_errno (errno), - "Failed to unset keep-capabilities: %s\n", - _dbus_strerror (errno)); - return FALSE; - } - } -#endif - - return TRUE; - - fail: -#ifdef HAVE_LIBAUDIT - if (!we_were_root) - { - /* should always work, if it did above */ - prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0); - cap_free (new_caps); - } -#endif - - return FALSE; -} - void _dbus_init_system_log (void) { diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 50998f04..75d5cc26 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -408,8 +408,6 @@ dbus_bool_t _dbus_become_daemon (const DBusString *pidfile, dbus_bool_t keep_umask); dbus_bool_t _dbus_verify_daemon_user (const char *user); -dbus_bool_t _dbus_change_to_daemon_user (const char *user, - DBusError *error); dbus_bool_t _dbus_write_pid_to_file_and_pipe (const DBusString *pidfile, DBusPipe *print_pid_pipe, diff --git a/test/test-service.c b/test/test-service.c index 2bd2dbc8..93f59f1e 100644 --- a/test/test-service.c +++ b/test/test-service.c @@ -411,7 +411,9 @@ main (int argc, name = argv[1]; #ifndef DBUS_WIN do_fork = strcmp (argv[2], "fork") == 0; -#endif +#else + do_fork = FALSE; +#endif } /* The bare minimum for simulating a program "daemonizing"; the intent @@ -428,6 +430,7 @@ main (int argc, sleep (1); } #endif + dbus_error_init (&error); connection = dbus_bus_get (DBUS_BUS_STARTER, &error); if (connection == NULL) diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c index 912afba8..d3553e81 100644 --- a/tools/dbus-launch.c +++ b/tools/dbus-launch.c @@ -405,6 +405,7 @@ signal_handler (int sig) #ifdef SIGHUP case SIGHUP: #endif + case SIGINT: case SIGTERM: got_sighup = TRUE; break; @@ -429,6 +430,7 @@ kill_bus_when_session_ends (void) act.sa_flags = 0; sigaction (SIGHUP, &act, NULL); sigaction (SIGTERM, &act, NULL); + sigaction (SIGINT, &act, NULL); #ifdef DBUS_BUILD_X11 x11_init(); diff --git a/tools/dbus-monitor.c b/tools/dbus-monitor.c index 873108bc..c3681289 100644 --- a/tools/dbus-monitor.c +++ b/tools/dbus-monitor.c @@ -33,8 +33,6 @@ #include <time.h> -#include <signal.h> - #include "dbus-print-message.h" #ifdef DBUS_WIN @@ -214,6 +212,13 @@ main (int argc, char *argv[]) int i = 0, j = 0, numFilters = 0; char **filters = NULL; + + /* Set stdout to be unbuffered; this is basically so that if people + * do dbus-monitor > file, then send SIGINT via Control-C, they + * don't lose the last chunk of messages. + */ + setvbuf (stdout, NULL, _IOLBF, 0); + for (i = 1; i < argc; i++) { char *arg = argv[i]; @@ -339,10 +344,7 @@ main (int argc, char *argv[]) exit (1); } - /* we handle SIGINT so exit() is reached and flushes stdout */ - signal (SIGINT, sigint_handler); - while (dbus_connection_read_write_dispatch(connection, -1) - && !sigint_received) + while (dbus_connection_read_write_dispatch(connection, -1)) ; exit (0); lose: |