Merge branch 'my-dbus-1.2'

Conflicts:
	bus/Makefile.am
	dbus/dbus-sysdeps-util-unix.c
	dbus/dbus-transport.c
	test/test-service.c
This commit is contained in:
Colin Walters 2010-01-28 17:09:15 -05:00
commit 7a4cd46284
14 changed files with 221 additions and 228 deletions

View file

@ -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= \

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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;
}

View file

@ -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 */

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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)
{

View file

@ -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,

View file

@ -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)

View file

@ -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();

View file

@ -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: