dbus/bus Makefile.am, 1.29, 1.30 bus.c, 1.52, 1.53 bus.h, 1.23, 1.24 config-parser.c, 1.30, 1.31 config-parser.h, 1.14, 1.15 connection.c, 1.54, 1.55 connection.h, 1.19, 1.20 dbus-daemon-1.1.in, 1.7, 1.8 main.c, 1.23, 1.24 policy.c, 1.19, 1.20 selinux.c, NONE, 1.1 selinux.h, NONE, 1.1 services.c, 1.21, 1.22 services.h, 1.10, 1.11 test-main.c, 1.16, 1.17

Havoc Pennington hp at freedesktop.org
Thu Jul 29 22:59:37 PDT 2004


Update of /cvs/dbus/dbus/bus
In directory pdx:/tmp/cvs-serv30925/bus

Modified Files:
	Makefile.am bus.c bus.h config-parser.c config-parser.h 
	connection.c connection.h dbus-daemon-1.1.in main.c policy.c 
	services.c services.h test-main.c 
Added Files:
	selinux.c selinux.h 
Log Message:
2004-07-24  Havoc Pennington  <hp at redhat.com>

	SELinux support from Matthew Rickard <mjricka at epoch.ncsc.mil>

	* bus/selinux.c, bus/selinux.h: new file encapsulating selinux
	functionality

	* configure.in: add --enable-selinux
	
	* bus/policy.c (bus_policy_merge): add FIXME to a comment

	* bus/main.c (main): initialize and shut down selinux

	* bus/connection.c: store SELinux ID on each connection, to avoid 
	repeated getting of the string context and converting it into 
	an ID

	* bus/bus.c (bus_context_get_policy): new accessor, though it
	isn't used
	(bus_context_check_security_policy): check whether the security
	context of sender connection can send to the security context of
	recipient connection

	* bus/config-parser.c: add parsing for <selinux> and <associate>
	
	* dbus/dbus-transport.c (_dbus_transport_get_unix_fd): to
	implement dbus_connection_get_unix_fd()

	* dbus/dbus-connection.c (dbus_connection_get_unix_fd): new
	function, used by the selinux stuff
	


Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/bus/Makefile.am,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- Makefile.am	11 Oct 2003 06:20:28 -0000	1.29
+++ Makefile.am	30 Jul 2004 05:59:33 -0000	1.30
@@ -10,7 +10,7 @@
 
 CONFIG_IN_FILES=				\
 	session.conf.in				\
-	system.conf.in 
+	system.conf.in
 
 config_DATA=					\
 	session.conf				\
@@ -44,6 +44,8 @@
 	expirelist.h				\
 	policy.c				\
 	policy.h				\
+	selinux.h				\
+	selinux.c				\
 	services.c				\
 	services.h				\
 	signals.c				\

Index: bus.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/bus.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- bus.c	29 May 2004 04:17:16 -0000	1.52
+++ bus.c	30 Jul 2004 05:59:33 -0000	1.53
@@ -29,6 +29,7 @@
 #include "policy.h"
 #include "config-parser.h"
 #include "signals.h"
+#include "selinux.h"
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-hash.h>
 #include <dbus/dbus-internals.h>
@@ -403,6 +404,7 @@
 {
   DBusString full_address;
   DBusList *link;
+  DBusHashTable *service_sid_table;
   
   dbus_bool_t retval;
 
@@ -480,6 +482,11 @@
       goto failed;
     }
 
+  service_sid_table = bus_config_parser_steal_service_sid_table (parser);
+  bus_registry_set_service_sid_table (context->registry,
+                                      service_sid_table);
+  _dbus_hash_table_unref (service_sid_table);
+  
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   retval = TRUE;
 
@@ -569,6 +576,13 @@
       goto failed;
     }
 
+  context->registry = bus_registry_new (context);
+  if (context->registry == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+  
   if (!load_config (context, FALSE, error))
     {
       _DBUS_ASSERT_ERROR_IS_SET (error);
@@ -637,13 +651,6 @@
       goto failed;
     }
 
-  context->registry = bus_registry_new (context);
-  if (context->registry == NULL)
-    {
-      BUS_SET_OOM (error);
-      goto failed;
-    }
-
   context->matchmaker = bus_matchmaker_new ();
   if (context->matchmaker == NULL)
     {
@@ -958,6 +965,12 @@
                                 uid);
 }
 
+BusPolicy *
+bus_context_get_policy (BusContext *context)
+{
+  return context->policy;
+}
+
 BusClientPolicy*
 bus_context_create_client_policy (BusContext      *context,
                                   DBusConnection  *connection,
@@ -1088,6 +1101,28 @@
   
   if (sender != NULL)
     {
+      /* First verify the SELinux access controls.  If allowed then
+       * go on with the standard checks.
+       */
+      if (!bus_selinux_allows_send (sender, proposed_recipient))
+        {
+          const char *dest = dbus_message_get_destination (message);
+          dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                          "An SELinux policy prevents this sender "
+                          "from sending this message to this recipient "
+                          "(rejected message had interface \"%s\" "
+                          "member \"%s\" error name \"%s\" destination \"%s\")",
+                          dbus_message_get_interface (message) ?
+                          dbus_message_get_interface (message) : "(unset)",
+                          dbus_message_get_member (message) ?
+                          dbus_message_get_member (message) : "(unset)",
+                          dbus_message_get_error_name (message) ?
+                          dbus_message_get_error_name (message) : "(unset)",
+                          dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
+          _dbus_verbose ("SELinux security check denying send to service\n");
+          return FALSE;
+        }
+       
       if (bus_connection_is_active (sender))
         {
           sender_policy = bus_connection_get_policy (sender);

Index: bus.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/bus.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- bus.h	16 Apr 2004 15:01:25 -0000	1.23
+++ bus.h	30 Jul 2004 05:59:33 -0000	1.24
@@ -38,6 +38,7 @@
 typedef struct BusClientPolicy  BusClientPolicy;
 typedef struct BusPolicyRule    BusPolicyRule;
 typedef struct BusRegistry      BusRegistry;
+typedef struct BusSELinuxID     BusSELinuxID;
 typedef struct BusService       BusService;
 typedef struct BusTransaction   BusTransaction;
 typedef struct BusMatchmaker    BusMatchmaker;
@@ -78,8 +79,11 @@
 BusMatchmaker*    bus_context_get_matchmaker                     (BusContext       *context);
 DBusLoop*         bus_context_get_loop                           (BusContext       *context);
 DBusUserDatabase* bus_context_get_user_database                  (BusContext       *context);
+
 dbus_bool_t       bus_context_allow_user                         (BusContext       *context,
                                                                   unsigned long     uid);
+BusPolicy*        bus_context_get_policy                         (BusContext       *context);
+
 BusClientPolicy*  bus_context_create_client_policy               (BusContext       *context,
                                                                   DBusConnection   *connection,
                                                                   DBusError        *error);
@@ -101,5 +105,4 @@
                                                                   DBusMessage      *message,
                                                                   DBusError        *error);
 
-
 #endif /* BUS_BUS_H */

Index: config-parser.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/config-parser.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- config-parser.c	29 May 2004 04:17:16 -0000	1.30
+++ config-parser.c	30 Jul 2004 05:59:34 -0000	1.31
@@ -24,6 +24,7 @@
 #include "test.h"
 #include "utils.h"
 #include "policy.h"
+#include "selinux.h"
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-internals.h>
 #include <string.h>
@@ -44,7 +45,9 @@
   ELEMENT_PIDFILE,
   ELEMENT_SERVICEDIR,
   ELEMENT_INCLUDEDIR,
-  ELEMENT_TYPE
+  ELEMENT_TYPE,
+  ELEMENT_SELINUX,
+  ELEMENT_ASSOCIATE
 } ElementType;
 
 typedef enum
@@ -117,6 +120,8 @@
 
   DBusList *included_files;  /**< Included files stack */
 
+  DBusHashTable *service_sid_table; /**< Map service names to SELinux contexts */
+
   unsigned int fork : 1; /**< TRUE to fork into daemon mode */
 
   unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */
@@ -157,6 +162,10 @@
       return "includedir";
     case ELEMENT_TYPE:
       return "type";
+    case ELEMENT_SELINUX:
+      return "selinux";
+    case ELEMENT_ASSOCIATE:
+      return "associate";
     }
 
   _dbus_assert_not_reached ("bad element type");
@@ -235,6 +244,7 @@
                 DBusError       *error)
 {
   DBusList *link;
+  DBusHashTable *table;
 
   if (!bus_policy_merge (parser->policy,
                          included->policy))
@@ -242,6 +252,17 @@
       BUS_SET_OOM (error);
       return FALSE;
     }
+
+  table = bus_selinux_id_table_union (parser->service_sid_table,
+                                      included->service_sid_table);
+  if (table == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  _dbus_hash_table_unref (parser->service_sid_table);
+  parser->service_sid_table = table;
   
   if (included->user != NULL)
     {
@@ -317,12 +338,17 @@
     }
 
   if (((parser->policy = bus_policy_new ()) == NULL) ||
-      !_dbus_string_copy (basedir, 0, &parser->basedir, 0))
+      !_dbus_string_copy (basedir, 0, &parser->basedir, 0) ||
+      ((parser->service_sid_table = bus_selinux_id_table_new ()) == NULL))
     {
       if (parser->policy)
         bus_policy_unref (parser->policy);
       
       _dbus_string_free (&parser->basedir);
+
+      if (parser->service_sid_table == NULL)
+        _dbus_hash_table_unref (parser->service_sid_table);
+      
       dbus_free (parser);
       return NULL;
     }
@@ -428,6 +454,9 @@
       if (parser->policy)
         bus_policy_unref (parser->policy);
 
+      if (parser->service_sid_table)
+        _dbus_hash_table_unref (parser->service_sid_table);
+      
       dbus_free (parser);
     }
 }
@@ -658,7 +687,7 @@
           BUS_SET_OOM (error);
           return FALSE;
         }
-
+      
       return TRUE;
     }
   else if (strcmp (element_name, "includedir") == 0)
@@ -843,6 +872,22 @@
 
       return TRUE;
     }
+  else if (strcmp (element_name, "selinux") == 0)
+    {
+      Element *e;
+      const char *name;
+
+      if (!check_no_attributes (parser, "selinux", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_SELINUX) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
   else
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
@@ -1390,6 +1435,58 @@
     }
 }
 
+static dbus_bool_t
+start_selinux_child (BusConfigParser   *parser,
+                     const char        *element_name,
+                     const char       **attribute_names,
+                     const char       **attribute_values,
+                     DBusError         *error)
+{
+  if (strcmp (element_name, "associate") == 0)
+    {
+      const char *own;
+      const char *context;
+      
+      if (!locate_attributes (parser, "associate",
+                              attribute_names,
+                              attribute_values,
+                              error,
+                              "own", &own,
+                              "context", &context,
+                              NULL))
+        return FALSE;
+      
+      if (push_element (parser, ELEMENT_ASSOCIATE) == NULL)
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+
+      if (own == NULL || context == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Element <associate> must have attributes own=\"<servicename>\" and context=\"<selinux context>\"");
+          return FALSE;
+        }
+
+      if (!bus_selinux_id_table_insert (parser->service_sid_table,
+                                        own, context))
+        {
+          BUS_SET_OOM (error);
+          return FALSE;
+        }
+      
+      return TRUE;
+    }
+  else
+    {
+      dbus_set_error (error, DBUS_ERROR_FAILED,
+                      "Element <%s> not allowed inside <%s> in configuration file",
+                      element_name, "selinux");
+      return FALSE;
+    }
+}
+
 dbus_bool_t
 bus_config_parser_start_element (BusConfigParser   *parser,
                                  const char        *element_name,
@@ -1440,6 +1537,12 @@
                                  attribute_names, attribute_values,
                                  error);
     }
+  else if (t == ELEMENT_SELINUX)
+    {
+      return start_selinux_child (parser, element_name,
+                                  attribute_names, attribute_values,
+                                  error);
+    }
   else
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
@@ -1635,6 +1738,8 @@
     case ELEMENT_ALLOW:
     case ELEMENT_DENY:
     case ELEMENT_FORK:
+    case ELEMENT_SELINUX:
+    case ELEMENT_ASSOCIATE:
       break;
     }
 
@@ -1867,6 +1972,8 @@
     case ELEMENT_ALLOW:
     case ELEMENT_DENY:
     case ELEMENT_FORK:
+    case ELEMENT_SELINUX:
+    case ELEMENT_ASSOCIATE:
       if (all_whitespace (content))
         return TRUE;
       else
@@ -2160,6 +2267,20 @@
   *limits = parser->limits;
 }
 
+DBusHashTable*
+bus_config_parser_steal_service_sid_table (BusConfigParser *parser)
+{
+  DBusHashTable *table;
+
+  _dbus_assert (parser->service_sid_table != NULL); /* can only steal once */
+
+  table = parser->service_sid_table;
+
+  parser->service_sid_table = NULL;
+
+  return table;
+}
+
 #ifdef DBUS_BUILD_TESTS
 #include <stdio.h>
 
@@ -2494,6 +2615,8 @@
   
   /* FIXME: compare policy */
 
+  /* FIXME: compare service selinux ID table */
+
   if (! limits_equal (&a->limits, &b->limits))
     return FALSE;
 

Index: config-parser.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/config-parser.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- config-parser.h	9 Apr 2004 19:50:29 -0000	1.14
+++ config-parser.h	30 Jul 2004 05:59:34 -0000	1.15
@@ -29,6 +29,7 @@
 #include <dbus/dbus.h>
 #include <dbus/dbus-string.h>
 #include <dbus/dbus-list.h>
+#include <dbus/dbus-hash.h>
 #include "bus.h"
 
 /* Whatever XML library we're using just pushes data into this API */
@@ -70,6 +71,8 @@
 void        bus_config_parser_get_limits       (BusConfigParser *parser,
                                                 BusLimits       *limits);
 
+DBusHashTable* bus_config_parser_steal_service_sid_table (BusConfigParser *parser);
+
 /* Loader functions (backended off one of the XML parsers).  Returns a
  * finished ConfigParser.
  */

Index: connection.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/connection.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- connection.c	20 May 2004 19:47:34 -0000	1.54
+++ connection.c	30 Jul 2004 05:59:34 -0000	1.55
@@ -27,6 +27,7 @@
 #include "utils.h"
 #include "signals.h"
 #include "expirelist.h"
+#include "selinux.h"
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-hash.h>
 #include <dbus/dbus-timeout.h>
@@ -75,6 +76,8 @@
   DBusPreallocatedSend *oom_preallocated;
   BusClientPolicy *policy;
 
+  BusSELinuxID *selinux_id;
+
   long connection_tv_sec;  /**< Time when we connected (seconds component) */
   long connection_tv_usec; /**< Time when we connected (microsec component) */
   int stamp;               /**< connections->stamp last time we were traversed */
@@ -401,6 +404,9 @@
 
   if (d->policy)
     bus_client_policy_unref (d->policy);
+
+  if (d->selinux_id)
+    bus_selinux_id_unref (d->selinux_id);
   
   dbus_free (d->name);
   
@@ -539,6 +545,7 @@
 {
   BusConnectionData *d;
   dbus_bool_t retval;
+  DBusError error;
   
   d = dbus_new0 (BusConnectionData, 1);
   
@@ -562,6 +569,20 @@
     }
 
   retval = FALSE;
+
+  dbus_error_init (&error);
+  d->selinux_id = bus_selinux_init_connection_id (connection,
+                                                  &error);
+  if (dbus_error_is_set (&error))
+    {
+      /* This is a bit bogus because we pretend all errors
+       * are OOM; this is done because we know that in bus.c
+       * an OOM error disconnects the connection, which is
+       * the same thing we want on any other error.
+       */
+      dbus_error_free (&error);
+      goto out;
+    }
   
   if (!dbus_connection_set_watch_functions (connection,
                                             add_connection_watch,
@@ -639,7 +660,11 @@
 
  out:
   if (!retval)
-    {      
+    {
+      if (d->selinux_id)
+        bus_selinux_id_unref (d->selinux_id);
+      d->selinux_id = NULL;
+      
       if (!dbus_connection_set_watch_functions (connection,
                                                 NULL, NULL, NULL,
                                                 connection,
@@ -1008,6 +1033,18 @@
   return bus_context_get_matchmaker (d->connections->context);
 }
 
+BusSELinuxID*
+bus_connection_get_selinux_id (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return d->selinux_id;
+}
+
 /**
  * Checks whether the connection is registered with the message bus.
  *

Index: connection.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/connection.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- connection.h	2 Dec 2003 10:44:21 -0000	1.19
+++ connection.h	30 Jul 2004 05:59:34 -0000	1.20
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu" -*- */
 /* connection.h  Client connections
  *
- * Copyright (C) 2003  Red Hat, Inc.
+ * Copyright (C) 2003, 2004  Red Hat, Inc.
  *
  * Licensed under the Academic Free License version 2.0
  * 
@@ -50,6 +50,7 @@
 BusRegistry*    bus_connection_get_registry       (DBusConnection               *connection);
 BusActivation*  bus_connection_get_activation     (DBusConnection               *connection);
 BusMatchmaker*  bus_connection_get_matchmaker     (DBusConnection               *connection);
+BusSELinuxID*   bus_connection_get_selinux_id     (DBusConnection               *connection);
 dbus_bool_t     bus_connections_check_limits      (BusConnections               *connections,
                                                    DBusConnection               *requesting_completion,
                                                    DBusError                    *error);

Index: dbus-daemon-1.1.in
===================================================================
RCS file: /cvs/dbus/dbus/bus/dbus-daemon-1.1.in,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- dbus-daemon-1.1.in	29 May 2004 04:17:16 -0000	1.7
+++ dbus-daemon-1.1.in	30 Jul 2004 05:59:34 -0000	1.8
@@ -463,6 +463,110 @@
 Be careful with send_interface/receive_interface, because the 
 interface field in messages is optional.
 
+.TP
+.I "<selinux>"
+
+.PP
+The <selinux> element contains settings related to Security Enhanced Linux.
+More details below.
+
+.TP
+.I "<associate>"
+
+.PP
+An <associate> element appears below an <selinux> element and
+creates a mapping. Right now only one kind of association is possible:
+.nf
+   <associate own="org.freedesktop.Foobar" context="foo_t"/> 
+.fi
+
+.PP
+This means that if a connection asks to own the service
+"org.freedesktop.Foobar" then the source context will be the context
+of the connection and the target context will be "foo_t" - see the 
+short discussion of SELinux below.
+
+.PP
+Note, the context here is the target context when acquiring a service,
+NOT the context of the connection owning the service.
+
+.PP
+There's currently no way to set a default for owning any service, if
+we add this syntax it will look like:
+.nf
+   <associate own="*" context="foo_t"/> 
+.fi
+If you find a reason this is useful, let the developers know.
+Right now the default will be the security context of the bus itself.
+
+.PP
+If two <associate> elements specify the same service name, 
+the element appearing later in the configuration file will 
+be used.
+
+.SH SELinux
+
+.PP
+See http://www.nsa.gov/selinux/ for full details on SELinux. Some useful excerpts:
+
+.IP "" 8
+Every subject (process) and object (e.g. file, socket, IPC object,
+etc) in the system is assigned a collection of security attributes,
+known as a security context. A security context contains all of the
+security attributes associated with a particular subject or object
+that are relevant to the security policy.
+
+.IP "" 8
+In order to better encapsulate security contexts and to provide
+greater efficiency, the policy enforcement code of SELinux typically
+handles security identifiers (SIDs) rather than security contexts. A
+SID is an integer that is mapped by the security server to a security
+context at runtime.
+
+.IP "" 8
+When a security decision is required, the policy enforcement code
+passes a pair of SIDs (typically the SID of a subject and the SID of
+an object, but sometimes a pair of subject SIDs or a pair of object
+SIDs), and an object security class to the security server. The object
+security class indicates the kind of object, e.g. a process, a regular
+file, a directory, a TCP socket, etc.
+
+.IP "" 8
+Access decisions specify whether or not a permission is granted for a
+given pair of SIDs and class. Each object class has a set of
+associated permissions defined to control operations on objects with
+that class.
+
+.PP
+D-BUS performs SELinux security checks in two places.
+
+.PP
+First, any time a message is routed from one connection to another
+connection, the bus daemon will check permissions with the security context of
+the first connection as source, security context of the second connection
+as target, object class "dbus" and requested permission "send_msg".
+
+.PP
+If a security context is not available for a connection 
+(impossible when using UNIX domain sockets), then the target 
+context used is the context of the bus daemon itself.
+There is currently no way to change this default, because we're 
+assuming that only UNIX domain sockets will be used to 
+connect to the systemwide bus. If this changes, we'll 
+probably add a way to set the default connection context.
+
+.PP
+Second, any time a connection asks to own a service, 
+the bus daemon will check permissions with the security 
+context of the connection as source, the security context specified
+for the service name with an <associate> element as target, object 
+class "dbus" and requested permission "acquire_svc".
+
+.PP
+If the service name has no security context associated in the 
+configuration file, the security context of the bus daemon 
+itself will be used.
+
 .SH AUTHOR
 See http://www.freedesktop.org/software/dbus/doc/AUTHORS
 

Index: main.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/main.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- main.c	20 May 2004 18:45:16 -0000	1.23
+++ main.c	30 Jul 2004 05:59:34 -0000	1.24
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <signal.h>
 #include <errno.h>
+#include "selinux.h"
 
 static BusContext *context;
 
@@ -371,7 +372,13 @@
           print_pid_fd = val;
         }
     }
-  
+
+  if (!bus_selinux_init ())
+    {
+      _dbus_warn ("SELinux initialization failed\n");
+      exit (1);
+    }
+
   dbus_error_init (&error);
   context = bus_context_new (&config_file, force_fork,
                              print_addr_fd, print_pid_fd,
@@ -395,6 +402,7 @@
   
   bus_context_shutdown (context);
   bus_context_unref (context);
+  bus_selinux_shutdown ();
 
   return 0;
 }

Index: policy.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/policy.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- policy.c	29 May 2004 04:17:16 -0000	1.19
+++ policy.c	30 Jul 2004 05:59:34 -0000	1.20
@@ -177,7 +177,7 @@
                                                free_rule_list_func);
   if (policy->rules_by_gid == NULL)
     goto failed;
-  
+
   return policy;
   
  failed:
@@ -594,9 +594,10 @@
 bus_policy_merge (BusPolicy *policy,
                   BusPolicy *to_absorb)
 {
-  /* Not properly atomic, but as used for configuration files
-   * we don't rely on it.
-   */  
+  /* FIXME Not properly atomic, but as used for configuration files we
+   * don't rely on it quite so much.
+   */
+  
   if (!append_copy_of_policy_list (&policy->default_rules,
                                    &to_absorb->default_rules))
     return FALSE;
@@ -670,7 +671,7 @@
                           NULL);
 
       _dbus_list_clear (&policy->rules);
-      
+
       dbus_free (policy);
     }
 }

--- NEW FILE: selinux.c ---
/* selinux.c  SELinux security checks for D-BUS
 *
 * Author: Matthew Rickard <mjricka at epoch.ncsc.mil>
 *
 * Licensed under the Academic Free License version 2.0
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include <dbus/dbus-internals.h>
#include <dbus/dbus-string.h>
#include "selinux.h"
#include "services.h"
#include "policy.h"
#include "config-parser.h"

#ifdef HAVE_SELINUX
#include <errno.h>
#include <syslog.h>
#include <selinux/selinux.h>
#include <selinux/avc.h>
#include <selinux/av_permissions.h>
#include <selinux/flask.h>
#include <stdarg.h>
#endif /* HAVE_SELINUX */

#define BUS_SID_FROM_SELINUX(sid)  ((BusSELinuxID*) (sid))
#define SELINUX_SID_FROM_BUS(sid)  ((security_id_t) (sid))

#ifdef HAVE_SELINUX
/* Store the value telling us if SELinux is enabled in the kernel. */
static dbus_bool_t selinux_enabled = FALSE;

/* Store an avc_entry_ref to speed AVC decisions. */
static struct avc_entry_ref aeref;

static security_id_t bus_sid = SECSID_WILD;
#endif /* HAVE_SELINUX */

/**
 * Log callback to log denial messages from the AVC.
 * This is used in avc_init.  Logs to both standard
 * error and syslogd.
 *
 * @param fmt the format string
 * @param variable argument list
 */
#ifdef HAVE_SELINUX
static void 
log_callback (const char *fmt, ...) 
{
  va_list ap;
  va_start(ap, fmt);
  vsyslog (LOG_INFO, fmt, ap);
  va_end(ap);
}
#endif /* HAVE_SELINUX */


/**
 * Initialize the user space access vector cache (AVC) for D-BUS and set up
 * logging callbacks.
 */
dbus_bool_t
bus_selinux_init (void)
{
#ifdef HAVE_SELINUX
  struct avc_log_callback log_cb = {(void*)log_callback, NULL};
  int r;
  char *bus_context;

  _dbus_assert (bus_sid == SECSID_WILD);
  
  /* Determine if we are running an SELinux kernel. */
  r = is_selinux_enabled ();
  if (r < 0)
    {
      _dbus_warn ("Could not tell if SELinux is enabled: %s\n",
                  _dbus_strerror (errno));
      return FALSE;
    }

  selinux_enabled = r != 0;

  if (!selinux_enabled)
    {
      _dbus_verbose ("SELinux not enabled in this kernel.\n");
      return TRUE;
    }

  _dbus_verbose ("SELinux is enabled in this kernel.\n");

  avc_entry_ref_init (&aeref);
  if (avc_init ("avc", NULL, &log_cb, NULL, NULL) < 0)
    {
      _dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
      return FALSE;
    }
  else
    {
      openlog ("dbus", LOG_PERROR, LOG_USER);
      _dbus_verbose ("Access Vector Cache (AVC) started.\n");
    }

  bus_context = NULL;
  bus_sid = SECSID_WILD;

  if (getcon (&bus_context) < 0)
    {
      _dbus_verbose ("Error getting context of bus: %s\n",
                     _dbus_strerror (errno));
      return FALSE;
    }
      
  if (avc_context_to_sid (bus_context, &bus_sid) < 0)
    {
      _dbus_verbose ("Error getting SID from bus context: %s\n",
                     _dbus_strerror (errno));
      freecon (bus_context);
      return FALSE;
    }

  freecon (bus_context);
  
  return TRUE;
#else
  return TRUE;
#endif /* HAVE_SELINUX */
}


/**
 * Decrement SID reference count.
 * 
 * @param sid the SID to decrement
 */
void
bus_selinux_id_unref (BusSELinuxID *sid)
{
#ifdef HAVE_SELINUX
  if (!selinux_enabled)
    return;

  _dbus_assert (sid != NULL);
  
  sidput (SELINUX_SID_FROM_BUS (sid));
#endif /* HAVE_SELINUX */
}

void
bus_selinux_id_ref (BusSELinuxID *sid)
{
#ifdef HAVE_SELINUX
  if (!selinux_enabled)
    return;

  _dbus_assert (sid != NULL);
  
  sidget (SELINUX_SID_FROM_BUS (sid));
#endif /* HAVE_SELINUX */
}

/**
 * Determine if the SELinux security policy allows the given sender
 * security context to go to the given recipient security context.
 * This function determines if the requested permissions are to be
 * granted from the connection to the message bus or to another
 * optionally supplied security identifier (e.g. for a service
 * context).  Currently these permissions are either send_msg or
 * acquire_svc in the dbus class.
 *
 * @param sender_sid source security context
 * @param override_sid is the target security context.  If SECSID_WILD this will
 *        use the context of the bus itself (e.g. the default).
 * @param target_class is the target security class.
 * @param requested is the requested permissions.
 * @returns #TRUE if security policy allows the send.
 */
#ifdef HAVE_SELINUX
static dbus_bool_t
bus_selinux_check (BusSELinuxID        *sender_sid,
                   BusSELinuxID        *override_sid,
                   security_class_t     target_class,
                   access_vector_t      requested)
{
  if (!selinux_enabled)
    return TRUE;
  
  /* Make the security check.  AVC checks enforcing mode here as well. */
  if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
                    override_sid ?
                    SELINUX_SID_FROM_BUS (override_sid) :
                    SELINUX_SID_FROM_BUS (bus_sid), 
                    target_class, requested, &aeref, NULL) < 0)
    {
      _dbus_verbose ("SELinux denying due to security policy.\n");
      return FALSE;
    }
  else
    return TRUE;
}
#endif /* HAVE_SELINUX */

/**
 * Returns true if the given connection can acquire a service,
 * assuming the given security ID is needed for that service.
 *
 * @param connection connection that wants to own the service
 * @param service_sid the SID of the service from the table
 * @returns #TRUE if acquire is permitted.
 */
dbus_bool_t
bus_selinux_allows_acquire_service (DBusConnection     *connection,
                                    BusSELinuxID       *service_sid)
{
#ifdef HAVE_SELINUX
  BusSELinuxID *connection_sid;
  
  if (!selinux_enabled)
    return TRUE;

  connection_sid = bus_connection_get_selinux_id (connection);
  
  return bus_selinux_check (connection_sid,
                            service_sid,
                            SECCLASS_DBUS,
                            DBUS__ACQUIRE_SVC);
#else
  return TRUE;
#endif /* HAVE_SELINUX */
}

/**
 * Check if SELinux security controls allow the message to be sent to a
 * particular connection based on the security context of the sender and
 * that of the receiver. The destination connection need not be the
 * addressed recipient, it could be an "eavesdropper"
 *
 * @param sender the sender of the message.
 * @param proposed_recipient the connection the message is to be sent to.
 * @returns whether to allow the send
 */
dbus_bool_t
bus_selinux_allows_send (DBusConnection     *sender,
                         DBusConnection     *proposed_recipient)
{
#ifdef HAVE_SELINUX
  BusSELinuxID *recipient_sid;
  BusSELinuxID *sender_sid;

  if (!selinux_enabled)
    return TRUE;

  sender_sid = bus_connection_get_selinux_id (sender);
  /* A NULL proposed_recipient means the bus itself. */
  if (proposed_recipient)
    recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
  else
    recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);

  return bus_selinux_check (sender_sid, recipient_sid,
                            SECCLASS_DBUS, DBUS__SEND_MSG);
#else
  return TRUE;
#endif /* HAVE_SELINUX */
}

/**
 * Gets the security context of a connection to the bus. It is up to
 * the caller to freecon() when they are done. 
 *
 * @param connection the connection to get the context of.
 * @param con the location to store the security context.
 * @returns #TRUE if context is successfully obtained.
 */
#ifdef HAVE_SELINUX
static dbus_bool_t
bus_connection_read_selinux_context (DBusConnection     *connection,
                                     char              **con)
{
  int fd;

  if (!selinux_enabled)
    return FALSE;

  _dbus_assert (connection != NULL);
  
  if (!dbus_connection_get_unix_fd (connection, &fd))
    {
      _dbus_verbose ("Failed to get file descriptor of socket.\n");
      return FALSE;
    }
  
  if (getpeercon (fd, con) < 0)
    {
      _dbus_verbose ("Error getting context of socket peer: %s\n",
                     _dbus_strerror (errno));
      return FALSE;
    }
  
  _dbus_verbose ("Successfully read connection context.\n");
  return TRUE;
}
#endif /* HAVE_SELINUX */

/**
 * Read the SELinux ID from the connection.
 *
 * @param connection the connection to read from
 * @returns the SID if successfully determined, #NULL otherwise.
 */
BusSELinuxID*
bus_selinux_init_connection_id (DBusConnection *connection,
                                DBusError      *error)
{
#ifdef HAVE_SELINUX
  char *con;
  security_id_t sid;
  
  if (!selinux_enabled)
    return NULL;

  if (!bus_connection_read_selinux_context (connection, &con))
    {
      dbus_set_error (error, DBUS_ERROR_FAILED,
                      "Failed to read an SELinux context from connection");
      _dbus_verbose ("Error getting peer context.\n");
      return NULL;
    }

  _dbus_verbose ("Converting context to SID to store on connection\n");

  if (avc_context_to_sid (con, &sid) < 0)
    {
      if (errno == ENOMEM)
        BUS_SET_OOM (error);
      else
        dbus_set_error (error, DBUS_ERROR_FAILED,
                        "Error getting SID from context: %s\n",
                        _dbus_strerror (errno));
      
      _dbus_warn ("Error getting SID from context: %s\n",
                  _dbus_strerror (errno));
      
      freecon (con);
      return NULL;
    }
 
  freecon (con); 
  return BUS_SID_FROM_SELINUX (sid);
#else
  return NULL;
#endif /* HAVE_SELINUX */
}


/* Function for freeing hash table data.  These SIDs
 * should no longer be referenced.
 */
static void
bus_selinux_id_table_free_value (BusSELinuxID *sid)
{
#ifdef HAVE_SELINUX
  /* NULL sometimes due to how DBusHashTable works */
  if (sid)
    bus_selinux_id_unref (sid);
#endif /* HAVE_SELINUX */
}

/**
 * Creates a new table mapping service names to security ID.
 * A security ID is a "compiled" security context, a security
 * context is just a string.
 *
 * @returns the new table or #NULL if no memory
 */
DBusHashTable*
bus_selinux_id_table_new (void)
{
  return _dbus_hash_table_new (DBUS_HASH_STRING,
                               (DBusFreeFunction) dbus_free,
                               (DBusFreeFunction) bus_selinux_id_table_free_value);
}

/** 
 * Hashes a service name and service context into the service SID
 * table as a string and a SID.
 *
 * @param service_name is the name of the service.
 * @param service_context is the context of the service.
 * @param service_table is the table to hash them into.
 * @return #FALSE if not enough memory
 */
dbus_bool_t
bus_selinux_id_table_insert (DBusHashTable *service_table,
                             const char    *service_name,
                             const char    *service_context)
{
#ifdef HAVE_SELINUX
  dbus_bool_t retval;
  security_id_t sid;
  char *key;

  if (!selinux_enabled)
    return TRUE;

  sid = SECSID_WILD;
  retval = FALSE;

  key = _dbus_strdup (service_name);
  if (key == NULL)
    return retval;
  
  if (avc_context_to_sid (service_context, &sid) < 0)
    {
      _dbus_assert (errno == ENOMEM);
      goto out;
    }

  if (!_dbus_hash_table_insert_string (service_table,
                                       key,
                                       BUS_SID_FROM_SELINUX (sid)))
    goto out;

  _dbus_verbose ("Parsed \tservice: %s \n\t\tcontext: %s\n",
                  key, 
                  sid->ctx);

  /* These are owned by the hash, so clear them to avoid unref */
  key = NULL;
  sid = SECSID_WILD;

  retval = TRUE;
  
 out:
  if (sid != SECSID_WILD)
    sidput (sid);

  if (key)
    dbus_free (key);

  return retval;
#else
  return TRUE;
#endif /* HAVE_SELINUX */
}


/**
 * Find the security identifier associated with a particular service
 * name.  Return a pointer to this SID, or #NULL/SECSID_WILD if the
 * service is not found in the hash table.  This should be nearly a
 * constant time operation.  If SELinux support is not available,
 * always return NULL.
 *
 * @todo This should return a const security_id_t since we don't
 *       want the caller to mess with it.
 *
 * @param service_table the hash table to check for service name.
 * @param service_name the name of the service to look for.
 * @returns the SELinux ID associated with the service
 */
BusSELinuxID*
bus_selinux_id_table_lookup (DBusHashTable    *service_table,
                             const DBusString *service_name)
{
#ifdef HAVE_SELINUX
  security_id_t sid;

  sid = SECSID_WILD;     /* default context */

  if (!selinux_enabled)
    return NULL;
  
  _dbus_verbose ("Looking up service SID for %s\n",
                 _dbus_string_get_const_data (service_name));

  sid = _dbus_hash_table_lookup_string (service_table,
                                        _dbus_string_get_const_data (service_name));

  if (sid == SECSID_WILD)
    _dbus_verbose ("Service %s not found\n", 
                   _dbus_string_get_const_data (service_name));
  else
    _dbus_verbose ("Service %s found\n", 
                   _dbus_string_get_const_data (service_name));

  return BUS_SID_FROM_SELINUX (sid);
#endif /* HAVE_SELINUX */
  return NULL;
}

#ifdef HAVE_SELINUX
static dbus_bool_t
bus_selinux_id_table_copy_over (DBusHashTable    *dest,
                                DBusHashTable    *override)
{
  const char *key;
  char *key_copy;
  BusSELinuxID *sid;
  DBusHashIter iter;
  
  _dbus_hash_iter_init (override, &iter);
  while (_dbus_hash_iter_next (&iter))
    {
      key = _dbus_hash_iter_get_string_key (&iter);
      sid = _dbus_hash_iter_get_value (&iter);

      key_copy = _dbus_strdup (key);
      if (key_copy == NULL)
        return FALSE;

      if (!_dbus_hash_table_insert_string (dest,
                                           key_copy,
                                           sid))
        {
          dbus_free (key_copy);
          return FALSE;
        }

      bus_selinux_id_ref (sid);
    }

  return TRUE;
}
#endif /* HAVE_SELINUX */

/**
 * Creates the union of the two tables (each table maps a service
 * name to a security ID). In case of the same service name in
 * both tables, the security ID from "override" will be used.
 *
 * @param base the base table
 * @param override the table that takes precedence in the merge
 * @returns the new table, or #NULL if out of memory
 */
DBusHashTable*
bus_selinux_id_table_union (DBusHashTable    *base,
                            DBusHashTable    *override)
{
  DBusHashTable *combined_table;

  combined_table = bus_selinux_id_table_new ();

  if (combined_table == NULL)
    return NULL;
  
#ifdef HAVE_SELINUX 
  if (!selinux_enabled)
    return combined_table;

  if (!bus_selinux_id_table_copy_over (combined_table, base))
    {
      _dbus_hash_table_unref (combined_table);
      return NULL;
    }

  if (!bus_selinux_id_table_copy_over (combined_table, override))
    {
      _dbus_hash_table_unref (combined_table);
      return NULL;
    }
#endif /* HAVE_SELINUX */
  
  return combined_table;
}

/**
 * For debugging:  Print out the current hash table of service SIDs.
 */
void
bus_selinux_id_table_print (DBusHashTable *service_table)
{
#ifdef DBUS_ENABLE_VERBOSE_MODE
#ifdef HAVE_SELINUX
  DBusHashIter iter;

  if (!selinux_enabled)
    return;
  
  _dbus_verbose ("Service SID Table:\n");
  _dbus_hash_iter_init (service_table, &iter);
  while (_dbus_hash_iter_next (&iter))
    {
      const char *key = _dbus_hash_iter_get_string_key (&iter);
      security_id_t sid = _dbus_hash_iter_get_value (&iter);
      _dbus_verbose ("The key is %s\n", key);
      _dbus_verbose ("The context is %s\n", sid->ctx);
      _dbus_verbose ("The refcount is %d\n", sid->refcnt);
    }
#endif /* HAVE_SELINUX */
#endif /* DBUS_ENABLE_VERBOSE_MODE */
}


#ifdef DBUS_ENABLE_VERBOSE_MODE
#ifdef HAVE_SELINUX
/**
 * Print out some AVC statistics.
 */
static void
bus_avc_print_stats (void)
{
  struct avc_cache_stats cstats;

  if (!selinux_enabled)
    return;
  
  _dbus_verbose ("AVC Statistics:\n");
  avc_cache_stats (&cstats);
  avc_av_stats ();
  _dbus_verbose ("AVC Cache Statistics:\n");
  _dbus_verbose ("Entry lookups: %d\n", cstats.entry_lookups);
  _dbus_verbose ("Entry hits: %d\n", cstats.entry_hits);
  _dbus_verbose ("Entry misses %d\n", cstats.entry_misses);
  _dbus_verbose ("Entry discards: %d\n", cstats.entry_discards);
  _dbus_verbose ("CAV lookups: %d\n", cstats.cav_lookups);
  _dbus_verbose ("CAV hits: %d\n", cstats.cav_hits);
  _dbus_verbose ("CAV probes: %d\n", cstats.cav_probes);
  _dbus_verbose ("CAV misses: %d\n", cstats.cav_misses);
}
#endif /* HAVE_SELINUX */
#endif /* DBUS_ENABLE_VERBOSE_MODE */


/**
 * Destroy the AVC before we terminate.
 */
void
bus_selinux_shutdown (void)
{
#ifdef HAVE_SELINUX
  if (!selinux_enabled)
    return;

  sidput (bus_sid);
  bus_sid = SECSID_WILD;
  
#ifdef DBUS_ENABLE_VERBOSE_MODE
  bus_avc_print_stats ();
#endif /* DBUS_ENABLE_VERBOSE_MODE */

  avc_destroy ();
#endif /* HAVE_SELINUX */
}


--- NEW FILE: selinux.h ---
/* selinux.h  SELinux security check headers for D-BUS
 *
 * Author: Matthew Rickard <mjricka at epoch.ncsc.mil>
 *
 * Licensed under the Academic Free License version 2.0
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef BUS_SELINUX_H
#define BUS_SELINUX_H

#include <dbus/dbus-hash.h>
#include <dbus/dbus-connection.h>
#include "services.h"

dbus_bool_t bus_selinux_init     (void);
void        bus_selinux_shutdown (void);

void bus_selinux_id_ref    (BusSELinuxID *sid);
void bus_selinux_id_unref  (BusSELinuxID *sid);

DBusHashTable* bus_selinux_id_table_new    (void);
BusSELinuxID*  bus_selinux_id_table_lookup (DBusHashTable    *service_table,
                                            const DBusString *service_name);
dbus_bool_t    bus_selinux_id_table_insert (DBusHashTable    *service_table,
                                            const char       *service_name,
                                            const char       *service_context);
DBusHashTable* bus_selinux_id_table_union  (DBusHashTable    *base,
                                            DBusHashTable    *override);
void           bus_selinux_id_table_print  (DBusHashTable    *service_table);



dbus_bool_t bus_selinux_allows_acquire_service (DBusConnection *connection,
                                                BusSELinuxID   *service_sid);
dbus_bool_t bus_selinux_allows_send            (DBusConnection *sender,
                                                DBusConnection *proposed_recipient);



BusSELinuxID* bus_selinux_init_connection_id (DBusConnection *connection,
                                              DBusError      *error);



#endif /* BUS_SELINUX_H */

Index: services.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/services.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- services.c	22 Jul 2004 07:07:01 -0000	1.21
+++ services.c	30 Jul 2004 05:59:34 -0000	1.22
@@ -31,6 +31,8 @@
 #include "utils.h"
 #include "activation.h"
 #include "policy.h"
+#include "bus.h"
+#include "selinux.h"
 
 struct BusService
 {
@@ -51,6 +53,8 @@
   
   DBusHashTable *service_hash;
   DBusMemPool   *service_pool;
+
+  DBusHashTable *service_sid_table;
 };
 
 BusRegistry*
@@ -75,6 +79,8 @@
   if (registry->service_pool == NULL)
     goto failed;
 
+  registry->service_sid_table = NULL;
+  
   return registry;
 
  failed:
@@ -103,7 +109,9 @@
         _dbus_hash_table_unref (registry->service_hash);
       if (registry->service_pool)
         _dbus_mem_pool_free (registry->service_pool);
-
+      if (registry->service_sid_table)
+        _dbus_hash_table_unref (registry->service_sid_table);
+      
       dbus_free (registry);
     }
 }
@@ -263,6 +271,7 @@
   BusClientPolicy *policy;
   BusService *service;
   BusActivation  *activation;
+  BusSELinuxID *sid;
   
   retval = FALSE;
 
@@ -292,6 +301,24 @@
   policy = bus_connection_get_policy (connection);
   _dbus_assert (policy != NULL);
 
+  /* Note that if sid is #NULL then the bus's own context gets used
+   * in bus_connection_selinux_allows_acquire_service()
+   */
+  sid = bus_selinux_id_table_lookup (registry->service_sid_table,
+                                     service_name);
+
+  if (!bus_selinux_allows_acquire_service (connection, sid))
+    {
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "Connection \"%s\" is not allowed to own the service \"%s\" due "
+                      "to SELinux policy",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)",
+		      service_name);
+      goto out;
+    }
+      
   if (!bus_client_policy_check_can_own (policy, connection,
                                         service_name))
     {
@@ -387,6 +414,19 @@
   return retval;
 }
 
+void
+bus_registry_set_service_sid_table (BusRegistry   *registry,
+                                    DBusHashTable *table)
+{
+  _dbus_assert (registry->service_sid_table != table);
+  
+  if (registry->service_sid_table)
+    _dbus_hash_table_unref (registry->service_sid_table);
+
+  registry->service_sid_table = table;
+  _dbus_hash_table_ref (table);
+}
+
 static void
 bus_service_unlink_owner (BusService      *service,
                           DBusConnection  *owner)

Index: services.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/services.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- services.h	2 Dec 2003 10:44:21 -0000	1.10
+++ services.h	30 Jul 2004 05:59:34 -0000	1.11
@@ -26,6 +26,7 @@
 
 #include <dbus/dbus.h>
 #include <dbus/dbus-string.h>
+#include <dbus/dbus-hash.h>
 #include "connection.h"
 #include "bus.h"
 
@@ -55,6 +56,8 @@
                                            dbus_uint32_t               *result,
                                            BusTransaction              *transaction,
                                            DBusError                   *error);
+void         bus_registry_set_service_sid_table (BusRegistry           *registry,
+                                                 DBusHashTable         *table);
 
 BusService*     bus_service_ref                      (BusService     *service);
 void            bus_service_unref                    (BusService     *service);

Index: test-main.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/test-main.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- test-main.c	12 Mar 2004 14:07:16 -0000	1.16
+++ test-main.c	30 Jul 2004 05:59:34 -0000	1.17
@@ -27,6 +27,7 @@
 #include <dbus/dbus-string.h>
 #include <dbus/dbus-sysdeps.h>
 #include <dbus/dbus-internals.h>
+#include "selinux.h"
 
 #ifdef DBUS_BUILD_TESTS
 static void
@@ -69,6 +70,9 @@
       return 1;
     }
 
+  if (!bus_selinux_init ())
+    die ("could not init selinux support");
+
   _dbus_string_init_const (&test_data_dir, dir);
 
 #if 0
@@ -119,6 +123,8 @@
   check_memleaks (argv[0]);
   
   printf ("%s: Success\n", argv[0]);
+
+  bus_selinux_shutdown ();
   
   return 0;
 #else /* DBUS_BUILD_TESTS */



More information about the dbus-commit mailing list