summaryrefslogtreecommitdiff
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
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
-rw-r--r--bus/selinux.c118
-rw-r--r--bus/selinux.h2
-rw-r--r--configure.in5
-rw-r--r--dbus/dbus-sysdeps-util-unix.c154
-rw-r--r--dbus/dbus-sysdeps.h2
5 files changed, 117 insertions, 164 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;
+}
+
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 7feb1a93..cb16eec4 100644
--- a/configure.in
+++ b/configure.in
@@ -851,7 +851,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
@@ -859,8 +859,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/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
index 83f74fe2..27cdbb01 100644
--- a/dbus/dbus-sysdeps-util-unix.c
+++ b/dbus/dbus-sysdeps-util-unix.c
@@ -44,11 +44,6 @@
#include <dirent.h>
#include <sys/un.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>
@@ -308,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 30e7dff2..b154f016 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -418,8 +418,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,