summaryrefslogtreecommitdiff
path: root/bus
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2010-01-28 17:09:15 -0500
committerColin Walters <walters@verbum.org>2010-01-28 17:09:15 -0500
commit7a4cd46284dd634c165b5c4eb23606b7c0ff4ade (patch)
treebf0390d7c05896f538e8c6739108bb3d681f8ef7 /bus
parent1e82db47431fb19b78f8943c17d63227156e2432 (diff)
parentb93476ce07acce83ff3b396616bb8a0eaf719916 (diff)
downloaddbus-7a4cd46284dd634c165b5c4eb23606b7c0ff4ade.tar.gz
Merge branch 'my-dbus-1.2'
Conflicts: bus/Makefile.am dbus/dbus-sysdeps-util-unix.c dbus/dbus-transport.c test/test-service.c
Diffstat (limited to 'bus')
-rw-r--r--bus/Makefile.am12
-rw-r--r--bus/activation.c104
-rw-r--r--bus/activation.h4
-rw-r--r--bus/bus.c23
-rw-r--r--bus/selinux.c118
-rw-r--r--bus/selinux.h2
6 files changed, 203 insertions, 60 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);
diff --git a/bus/bus.c b/bus/bus.c
index f6ff1803..0bb9ffa4 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -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 */