From 7936d37e8f52159d69edf266ae3cf270f137bb04 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 7 Jan 2011 13:36:01 -0500 Subject: RHEL-4: Import dbus-0.22-cap-audit-write.patch --- bus/selinux.c | 38 +++++++++++++++++++++ configure.in | 23 ++++++++++++- dbus/dbus-sysdeps.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 152 insertions(+), 4 deletions(-) diff --git a/bus/selinux.c b/bus/selinux.c index 673b2ca0..06dae881 100644 --- a/bus/selinux.c +++ b/bus/selinux.c @@ -37,6 +37,9 @@ #include #include #include +#ifdef HAVE_LIBAUDIT +#include +#endif /* HAVE_LIBAUDIT */ #endif /* HAVE_SELINUX */ #define BUS_SID_FROM_SELINUX(sid) ((BusSELinuxID*) (sid)) @@ -98,12 +101,40 @@ static const struct avc_lock_callback lock_cb = * @param variable argument list */ #ifdef HAVE_SELINUX +#ifdef HAVE_LIBAUDIT +static int audit_fd = -1; +static void audit_init(void) +{ + audit_fd = audit_open(); + if (audit_fd < 0) { + /* If kernel doesn't support audit, bail out */ + if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) + return; + /* If user bus, bail out */ + if (errno == EPERM && getuid() != 0) + return; + _dbus_warn ("Failed opening connection to the audit subsystem"); + } +} +#endif /* HAVE_LIBAUDIT */ + static void log_callback (const char *fmt, ...) { va_list ap; va_start(ap, fmt); +#ifdef HAVE_LIBAUDIT + { + 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, + NULL, getuid()); + } +#else vsyslog (LOG_INFO, fmt, ap); +#endif /* HAVE_LIBAUDIT */ va_end(ap); } @@ -294,6 +325,10 @@ bus_selinux_full_init (void) freecon (bus_context); +#ifdef HAVE_LIBAUDIT + audit_init (); +#endif /* HAVE_LIBAUDIT */ + return TRUE; #else return TRUE; @@ -866,6 +901,9 @@ bus_selinux_shutdown (void) #endif /* DBUS_ENABLE_VERBOSE_MODE */ avc_destroy (); +#ifdef HAVE_LIBAUDIT + audit_close (audit_fd); +#endif /* HAVE_LIBAUDIT */ #endif /* HAVE_SELINUX */ } diff --git a/configure.in b/configure.in index 83946a48..2ddded03 100644 --- a/configure.in +++ b/configure.in @@ -39,7 +39,7 @@ AC_ARG_ENABLE(mono, [ --enable-mono build mono bindings],en AC_ARG_ENABLE(mono_docs, [ --enable-mono-docs build mono docs],enable_mono_docs=$enableval,enable_mono_docs=auto) AC_ARG_ENABLE(python, [ --enable-python build python bindings],enable_python=$enableval,enable_python=auto) AC_ARG_ENABLE(selinux, [ --enable-selinux build with SELinux support],enable_selinux=$enableval,enable_selinux=auto) - +AC_ARG_ENABLE(libaudit, [ --enable-libaudit build audit daemon support for SELinux],enable_libaudit=$enableval,enable_libaudit=auto) AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use]) AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install]) AC_ARG_WITH(session-socket-dir, [ --with-session-socket-dir=[dirname] Where to put sockets for the per-login-session message bus]) @@ -724,6 +724,27 @@ else SELINUX_LIBS= fi +# libaudit detection +if test x$enable_libaudit = xno ; then + have_libaudit=no; +else + # See if we have audit daemon & capabilities library + 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, + have_libaudit=yes, have_libaudit=no) + fi +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" + AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support]) +fi + #### Set up final flags DBUS_CLIENT_CFLAGS= DBUS_CLIENT_LIBS= diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 79f764d6..4092ae91 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -38,6 +38,13 @@ #include #include #include + +#ifdef HAVE_LIBAUDIT +#include +#include +#include +#endif /* HAVE_LIBAUDIT */ + #include #include #include @@ -3281,6 +3288,55 @@ _dbus_change_identity (dbus_uid_t uid, dbus_gid_t gid, DBusError *error) { + int priv = FALSE; + +#ifdef HAVE_LIBAUDIT + /* 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. + */ + cap_t new_caps = NULL; + + priv = !getuid(); + if (priv) + { + 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\n"); + 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)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to drop capabilities\n"); + cap_free(tmp_caps); + goto fail; + } + cap_free(tmp_caps); + } +#endif /* HAVE_LIBAUDIT */ + /* Set GID first, or the setuid may remove our permission * to change the GID */ @@ -3289,7 +3345,7 @@ _dbus_change_identity (dbus_uid_t uid, 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) @@ -3297,10 +3353,43 @@ _dbus_change_identity (dbus_uid_t uid, 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 (priv) + { + if (cap_set_proc(new_caps)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to drop capabilities\n"); + goto fail; + } + cap_free(new_caps); + + if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1) + { /* should always work, if it did above */ + 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 (priv) + { + /* 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 v1.2.1