--- dbus-0.61/bus/selinux.c.selinux-avc-audit 2006-02-24 14:41:15.000000000 -0500 +++ dbus-0.61/bus/selinux.c 2006-02-24 14:41:15.000000000 -0500 @@ -38,6 +38,9 @@ #include #include #include +#ifdef HAVE_LIBAUDIT +#include +#endif /* HAVE_LIBAUDIT */ #endif /* HAVE_SELINUX */ #define BUS_SID_FROM_SELINUX(sid) ((BusSELinuxID*) (sid)) @@ -100,12 +103,40 @@ * @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); } @@ -313,6 +344,10 @@ freecon (bus_context); +#ifdef HAVE_LIBAUDIT + audit_init (); +#endif /* HAVE_LIBAUDIT */ + return TRUE; #else return TRUE; @@ -937,6 +972,9 @@ #endif /* DBUS_ENABLE_VERBOSE_MODE */ avc_destroy (); +#ifdef HAVE_LIBAUDIT + audit_close (audit_fd); +#endif /* HAVE_LIBAUDIT */ } #endif /* HAVE_SELINUX */ } --- dbus-0.61/configure.in.selinux-avc-audit 2006-02-24 11:36:29.000000000 -0500 +++ dbus-0.61/configure.in 2006-02-24 14:55:17.000000000 -0500 @@ -67,6 +67,7 @@ AC_ARG_ENABLE(mono_docs, AS_HELP_STRING([--enable-mono-docs],[build mono docs]),enable_mono_docs=$enableval,enable_mono_docs=no) AC_ARG_ENABLE(python, AS_HELP_STRING([--enable-python],[build python bindings]),enable_python=$enableval,enable_python=auto) AC_ARG_ENABLE(selinux, AS_HELP_STRING([--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_ENABLE(dnotify, AS_HELP_STRING([--enable-dnotify],[build with dnotify support (linux only)]),enable_dnotify=$enableval,enable_dnotify=auto) AC_ARG_WITH(xml, AS_HELP_STRING([--with-xml=[libxml/expat]],[XML library to use])) @@ -851,6 +852,27 @@ AC_DEFINE(DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX,1,[Use dnotify on Linux]) 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= --- dbus-0.61-orig/dbus/dbus-sysdeps-util-unix.c.selinux-avc-audit 2006-02-24 10:46:45.000000000 -0500 +++ dbus-0.61/dbus/dbus-sysdeps-util-unix.c 2006-04-04 13:00:04.000000000 -0400 @@ -42,6 +42,11 @@ #include #include #include +#ifdef HAVE_LIBAUDIT +#include +#include +#include +#endif /* HAVE_LIBAUDIT */ #ifndef O_BINARY #define O_BINARY 0 @@ -247,6 +252,55 @@ 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 */ + /* 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. @@ -265,7 +319,7 @@ 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) @@ -273,10 +327,42 @@ 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