summaryrefslogtreecommitdiff
path: root/bus/selinux.c
diff options
context:
space:
mode:
authorColin Walters <walters@verbum.org>2010-01-27 19:38:44 -0500
committerColin Walters <walters@verbum.org>2010-01-28 17:01:24 -0500
commit0a3905d7f3b2ff43b09479863775939f9c8acad4 (patch)
tree5b3bd15ac10ce030b3e4179d7b38406b196d1066 /bus/selinux.c
parent5b2cf0d0310f5da78dc99ce55c678ca93d2c29c4 (diff)
downloaddbus-0a3905d7f3b2ff43b09479863775939f9c8acad4.tar.gz
Switch to libcap-ng, avoid linking libdbus against libcap[-ng]
(Commit message written by Colin Walters <walters@verbum.org>) A current Fedora goal is to convert projects to libcap-ng which more easily allows dropping Linux capabilities. For software which also links to libdbus, it's problematic to link against libcap as well. Though really, libdbus should have never linked against libcap in the first place, which is another thing this patch changes by moving the libcap-using bits out of dbus/ and into bus/. https://bugzilla.redhat.com/show_bug.cgi?id=518541
Diffstat (limited to 'bus/selinux.c')
-rw-r--r--bus/selinux.c118
1 files changed, 113 insertions, 5 deletions
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;
+}
+