From e3d30a03225dd1d26012ecd39b09e4ccf91befb5 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 13 Jun 2007 16:30:43 +0000 Subject: 2007-06-13 Havoc Pennington * configure.ac, bus/selinux.c, dbus/dbus-sysdeps-unix-util.c: add libaudit support, no clue what this means really but now we have it. Patches from Fedora package. * bus/bus.c (bus_context_new): move selinux initialization after changing to daemon user, patch from Fedora package * dbus/dbus-transport.c (auth_via_unix_user_function): fix a typo --- dbus/dbus-sysdeps-util-unix.c | 104 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 4 deletions(-) (limited to 'dbus/dbus-sysdeps-util-unix.c') diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index 339b8f96..e81c752e 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -43,6 +43,11 @@ #include #include #include +#ifdef HAVE_LIBAUDIT +#include +#include +#include +#endif /* HAVE_LIBAUDIT */ #ifdef HAVE_SYS_SYSLIMITS_H #include @@ -273,7 +278,11 @@ _dbus_change_to_daemon_user (const char *user, 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)) @@ -284,6 +293,58 @@ _dbus_change_to_daemon_user (const char *user, return FALSE; } +#ifdef HAVE_LIBAUDIT + we_were_root = _dbus_getuid () == 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. @@ -303,7 +364,7 @@ _dbus_change_to_daemon_user (const char *user, dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to set GID to %lu: %s", gid, _dbus_strerror (errno)); - return FALSE; + goto fail; } if (setuid (uid) < 0) @@ -311,10 +372,45 @@ _dbus_change_to_daemon_user (const char *user, dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to set UID to %lu: %s", uid, _dbus_strerror (errno)); - return FALSE; + goto fail; } - return TRUE; +#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; } /** Installs a UNIX signal handler -- cgit