2007-06-13 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Wed, 13 Jun 2007 16:30:43 +0000 (16:30 +0000)
committerHavoc Pennington <hp@redhat.com>
Wed, 13 Jun 2007 16:30:43 +0000 (16:30 +0000)
* 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

ChangeLog
bus/bus.c
bus/selinux.c
configure.in
dbus/dbus-sysdeps-util-unix.c
dbus/dbus-transport.c

index a433fd4..26e9784 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2007-06-13  Havoc Pennington  <hp@redhat.com>
+
+       * 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
+
 2007-06-12  Havoc Pennington  <hp@redhat.com>
 
        * dbus/dbus-message.c (dbus_message_iter_open_container): improve
index 073f0a5..a6abc45 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -739,11 +739,6 @@ bus_context_new (const DBusString *config_file,
       _dbus_string_free (&pid);
     }
 
-  if (!bus_selinux_full_init ())
-    {
-      _dbus_warn ("SELinux initialization failed\n");
-    }
-
   if (!process_config_postinit (context, parser, error))
     {
       _DBUS_ASSERT_ERROR_IS_SET (error);
@@ -767,6 +762,11 @@ bus_context_new (const DBusString *config_file,
          goto failed;
        }
     }
+
+  if (!bus_selinux_full_init ())
+    {
+      _dbus_warn ("SELinux initialization failed\n");
+    }
   
   dbus_server_free_data_slot (&server_data_slot);
   
index e5f26da..c213838 100644 (file)
@@ -38,6 +38,9 @@
 #include <selinux/flask.h>
 #include <signal.h>
 #include <stdarg.h>
+#ifdef HAVE_LIBAUDIT
+#include <libaudit.h>
+#endif /* HAVE_LIBAUDIT */
 #endif /* HAVE_SELINUX */
 
 #define BUS_SID_FROM_SELINUX(sid)  ((BusSELinuxID*) (sid))
@@ -100,11 +103,50 @@ static const struct avc_lock_callback lock_cb =
  * @param variable argument list
  */
 #ifdef HAVE_SELINUX
+
+#ifdef HAVE_LIBAUDIT
+static int audit_fd = -1;
+#endif
+
+static void
+audit_init(void)
+{
+#ifdef HAVE_LIBAUDIT  
+  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
+  if (audit_fd >= 0)
+  {
+    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());
+    return;
+  }
+#endif /* HAVE_LIBAUDIT */
+  
   vsyslog (LOG_INFO, fmt, ap);
   va_end(ap);
 }
@@ -303,6 +345,8 @@ bus_selinux_full_init (void)
 
   freecon (bus_context);
   
+  audit_init ();
+
   return TRUE;
 #else
   return TRUE;
@@ -925,12 +969,18 @@ bus_selinux_shutdown (void)
     {
       sidput (bus_sid);
       bus_sid = SECSID_WILD;
-      
+
 #ifdef DBUS_ENABLE_VERBOSE_MODE
-      bus_avc_print_stats ();
+      if (_dbus_is_verbose()) 
+        bus_avc_print_stats ();
 #endif /* DBUS_ENABLE_VERBOSE_MODE */
 
       avc_destroy ();
+#ifdef HAVE_LIBAUDIT
+      audit_close (audit_fd);
+#endif /* HAVE_LIBAUDIT */
     }
 #endif /* HAVE_SELINUX */
 }
index 4836342..4bdc535 100644 (file)
@@ -56,6 +56,7 @@ AC_ARG_ENABLE(doxygen-docs, AS_HELP_STRING([--enable-doxygen-docs],[build DOXYGE
 AC_ARG_ENABLE(gcov, AS_HELP_STRING([--enable-gcov],[compile with coverage profiling instrumentation (gcc only)]),enable_gcov=$enableval,enable_gcov=no)
 AC_ARG_ENABLE(abstract-sockets, AS_HELP_STRING([--enable-abstract-sockets],[use abstract socket namespace (linux only)]),enable_abstract_sockets=$enableval,enable_abstract_sockets=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_ENABLE(kqueue, AS_HELP_STRING([--enable-kqueue],[build with kqueue support]),enable_kqueue=$enableval,enable_kqueue=auto)
 AC_ARG_ENABLE(console-owner-file, AS_HELP_STRING([--enable-console-owner-file],[enable console owner file]),enable_console_owner_file=$enableval,enable_console_owner_file=auto)
@@ -904,6 +905,27 @@ fi
 
 AM_CONDITIONAL(HAVE_CONSOLE_OWNER_FILE, test x$have_console_owner_file = xyes)
 
+# 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="$THREAD_LIBS"
index 339b8f9..e81c752 100644 (file)
 #include <sys/socket.h>
 #include <dirent.h>
 #include <sys/un.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>
@@ -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
index d738cc0..0e27dd1 100644 (file)
@@ -516,9 +516,9 @@ auth_via_unix_user_function (DBusTransport *transport)
   connection = transport->connection;
   unix_user_function = transport->unix_user_function;
   unix_user_data = transport->unix_user_data;
-  uid = _dbus_credentials_get_unix_uid (auth_identity),
+  uid = _dbus_credentials_get_unix_uid (auth_identity);
               
-    _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
+  _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
   _dbus_connection_unlock (connection);
 
   allow = (* unix_user_function) (connection,