Home | History | Annotate | Download | only in bus
      1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
      2  * selinux.c  SELinux security checks for D-Bus
      3  *
      4  * Author: Matthew Rickard <mjricka (at) epoch.ncsc.mil>
      5  *
      6  * Licensed under the Academic Free License version 2.1
      7  *
      8  * This program is free software; you can redistribute it and/or modify
      9  * it under the terms of the GNU General Public License as published by
     10  * the Free Software Foundation; either version 2 of the License, or
     11  * (at your option) any later version.
     12  *
     13  * This program is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  * GNU General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU General Public License
     19  * along with this program; if not, write to the Free Software
     20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     21  *
     22  */
     23 
     24 #include <config.h>
     25 #include <dbus/dbus-internals.h>
     26 #include <dbus/dbus-string.h>
     27 #ifndef DBUS_WIN
     28 #include <dbus/dbus-userdb.h>
     29 #endif
     30 #include "selinux.h"
     31 #include "services.h"
     32 #include "policy.h"
     33 #include "utils.h"
     34 #include "config-parser.h"
     35 
     36 #ifdef HAVE_ERRNO_H
     37 #include <errno.h>
     38 #endif
     39 #ifdef HAVE_SELINUX
     40 #include <sys/types.h>
     41 #include <unistd.h>
     42 #include <limits.h>
     43 #include <pthread.h>
     44 #include <syslog.h>
     45 #include <selinux/selinux.h>
     46 #include <selinux/avc.h>
     47 #include <selinux/av_permissions.h>
     48 #include <selinux/flask.h>
     49 #include <signal.h>
     50 #include <stdarg.h>
     51 #include <stdio.h>
     52 #include <grp.h>
     53 #endif /* HAVE_SELINUX */
     54 #ifdef HAVE_LIBAUDIT
     55 #include <cap-ng.h>
     56 #include <libaudit.h>
     57 #endif /* HAVE_LIBAUDIT */
     58 
     59 #define BUS_SID_FROM_SELINUX(sid)  ((BusSELinuxID*) (sid))
     60 #define SELINUX_SID_FROM_BUS(sid)  ((security_id_t) (sid))
     61 
     62 #ifdef HAVE_SELINUX
     63 /* Store the value telling us if SELinux is enabled in the kernel. */
     64 static dbus_bool_t selinux_enabled = FALSE;
     65 
     66 /* Store an avc_entry_ref to speed AVC decisions. */
     67 static struct avc_entry_ref aeref;
     68 
     69 /* Store the SID of the bus itself to use as the default. */
     70 static security_id_t bus_sid = SECSID_WILD;
     71 
     72 /* Thread to listen for SELinux status changes via netlink. */
     73 static pthread_t avc_notify_thread;
     74 
     75 /* Prototypes for AVC callback functions.  */
     76 static void log_callback (const char *fmt, ...);
     77 static void log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft);
     78 static void *avc_create_thread (void (*run) (void));
     79 static void avc_stop_thread (void *thread);
     80 static void *avc_alloc_lock (void);
     81 static void avc_get_lock (void *lock);
     82 static void avc_release_lock (void *lock);
     83 static void avc_free_lock (void *lock);
     84 
     85 /* AVC callback structures for use in avc_init.  */
     86 static const struct avc_memory_callback mem_cb =
     87 {
     88   .func_malloc = dbus_malloc,
     89   .func_free = dbus_free
     90 };
     91 static const struct avc_log_callback log_cb =
     92 {
     93   .func_log = log_callback,
     94   .func_audit = log_audit_callback
     95 };
     96 static const struct avc_thread_callback thread_cb =
     97 {
     98   .func_create_thread = avc_create_thread,
     99   .func_stop_thread = avc_stop_thread
    100 };
    101 static const struct avc_lock_callback lock_cb =
    102 {
    103   .func_alloc_lock = avc_alloc_lock,
    104   .func_get_lock = avc_get_lock,
    105   .func_release_lock = avc_release_lock,
    106   .func_free_lock = avc_free_lock
    107 };
    108 #endif /* HAVE_SELINUX */
    109 
    110 /**
    111  * Log callback to log denial messages from the AVC.
    112  * This is used in avc_init.  Logs to both standard
    113  * error and syslogd.
    114  *
    115  * @param fmt the format string
    116  * @param variable argument list
    117  */
    118 #ifdef HAVE_SELINUX
    119 
    120 #ifdef HAVE_LIBAUDIT
    121 static int audit_fd = -1;
    122 #endif
    123 
    124 void
    125 bus_selinux_audit_init(void)
    126 {
    127 #ifdef HAVE_LIBAUDIT
    128   audit_fd = audit_open ();
    129 
    130   if (audit_fd < 0)
    131     {
    132       /* If kernel doesn't support audit, bail out */
    133       if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT)
    134         return;
    135       /* If user bus, bail out */
    136       if (errno == EPERM && getuid() != 0)
    137         return;
    138       _dbus_warn ("Failed opening connection to the audit subsystem");
    139     }
    140 #endif /* HAVE_LIBAUDIT */
    141 }
    142 
    143 static void
    144 log_callback (const char *fmt, ...)
    145 {
    146   va_list ap;
    147 
    148   va_start(ap, fmt);
    149 
    150 #ifdef HAVE_LIBAUDIT
    151   if (audit_fd >= 0)
    152   {
    153     capng_get_caps_process();
    154     if (capng_have_capability(CAPNG_EFFECTIVE, CAP_AUDIT_WRITE))
    155     {
    156       char buf[PATH_MAX*2];
    157 
    158       /* FIXME: need to change this to show real user */
    159       vsnprintf(buf, sizeof(buf), fmt, ap);
    160       audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL,
    161                                NULL, getuid());
    162       return;
    163     }
    164   }
    165 #endif /* HAVE_LIBAUDIT */
    166 
    167   vsyslog (LOG_USER | LOG_INFO, fmt, ap);
    168   va_end(ap);
    169 }
    170 
    171 /**
    172  * On a policy reload we need to reparse the SELinux configuration file, since
    173  * this could have changed.  Send a SIGHUP to reload all configs.
    174  */
    175 static int
    176 policy_reload_callback (u_int32_t event, security_id_t ssid,
    177                         security_id_t tsid, security_class_t tclass,
    178                         access_vector_t perms, access_vector_t *out_retained)
    179 {
    180   if (event == AVC_CALLBACK_RESET)
    181     return raise (SIGHUP);
    182 
    183   return 0;
    184 }
    185 
    186 /**
    187  * Log any auxiliary data
    188  */
    189 static void
    190 log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft)
    191 {
    192   DBusString *audmsg = data;
    193 
    194   if (bufleft > (size_t) _dbus_string_get_length(audmsg))
    195     {
    196       _dbus_string_copy_to_buffer_with_nul (audmsg, buf, bufleft);
    197     }
    198   else
    199     {
    200       DBusString s;
    201 
    202       _dbus_string_init_const(&s, "Buffer too small for audit message");
    203 
    204       if (bufleft > (size_t) _dbus_string_get_length(&s))
    205         _dbus_string_copy_to_buffer_with_nul (&s, buf, bufleft);
    206     }
    207 }
    208 
    209 /**
    210  * Create thread to notify the AVC of enforcing and policy reload
    211  * changes via netlink.
    212  *
    213  * @param run the thread run function
    214  * @return pointer to the thread
    215  */
    216 static void *
    217 avc_create_thread (void (*run) (void))
    218 {
    219   int rc;
    220 
    221   rc = pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
    222   if (rc != 0)
    223     {
    224       _dbus_warn ("Failed to start AVC thread: %s\n", _dbus_strerror (rc));
    225       exit (1);
    226     }
    227   return &avc_notify_thread;
    228 }
    229 
    230 /* Stop AVC netlink thread.  */
    231 static void
    232 avc_stop_thread (void *thread)
    233 {
    234   pthread_cancel (*(pthread_t *) thread);
    235 }
    236 
    237 /* Allocate a new AVC lock.  */
    238 static void *
    239 avc_alloc_lock (void)
    240 {
    241   pthread_mutex_t *avc_mutex;
    242 
    243   avc_mutex = dbus_new (pthread_mutex_t, 1);
    244   if (avc_mutex == NULL)
    245     {
    246       _dbus_warn ("Could not create mutex: %s\n", _dbus_strerror (errno));
    247       exit (1);
    248     }
    249   pthread_mutex_init (avc_mutex, NULL);
    250 
    251   return avc_mutex;
    252 }
    253 
    254 /* Acquire an AVC lock.  */
    255 static void
    256 avc_get_lock (void *lock)
    257 {
    258   pthread_mutex_lock (lock);
    259 }
    260 
    261 /* Release an AVC lock.  */
    262 static void
    263 avc_release_lock (void *lock)
    264 {
    265   pthread_mutex_unlock (lock);
    266 }
    267 
    268 /* Free an AVC lock.  */
    269 static void
    270 avc_free_lock (void *lock)
    271 {
    272   pthread_mutex_destroy (lock);
    273   dbus_free (lock);
    274 }
    275 #endif /* HAVE_SELINUX */
    276 
    277 /**
    278  * Return whether or not SELinux is enabled; must be
    279  * called after bus_selinux_init.
    280  */
    281 dbus_bool_t
    282 bus_selinux_enabled (void)
    283 {
    284 #ifdef HAVE_SELINUX
    285   return selinux_enabled;
    286 #else
    287   return FALSE;
    288 #endif /* HAVE_SELINUX */
    289 }
    290 
    291 /**
    292  * Do early initialization; determine whether SELinux is enabled.
    293  */
    294 dbus_bool_t
    295 bus_selinux_pre_init (void)
    296 {
    297 #ifdef HAVE_SELINUX
    298   int r;
    299   _dbus_assert (bus_sid == SECSID_WILD);
    300 
    301   /* Determine if we are running an SELinux kernel. */
    302   r = is_selinux_enabled ();
    303   if (r < 0)
    304     {
    305       _dbus_warn ("Could not tell if SELinux is enabled: %s\n",
    306                   _dbus_strerror (errno));
    307       return FALSE;
    308     }
    309 
    310   selinux_enabled = r != 0;
    311   return TRUE;
    312 #else
    313   return TRUE;
    314 #endif
    315 }
    316 
    317 /**
    318  * Initialize the user space access vector cache (AVC) for D-Bus and set up
    319  * logging callbacks.
    320  */
    321 dbus_bool_t
    322 bus_selinux_full_init (void)
    323 {
    324 #ifdef HAVE_SELINUX
    325   char *bus_context;
    326 
    327   _dbus_assert (bus_sid == SECSID_WILD);
    328 
    329   if (!selinux_enabled)
    330     {
    331       _dbus_verbose ("SELinux not enabled in this kernel.\n");
    332       return TRUE;
    333     }
    334 
    335   _dbus_verbose ("SELinux is enabled in this kernel.\n");
    336 
    337   avc_entry_ref_init (&aeref);
    338   if (avc_init ("avc", &mem_cb, &log_cb, &thread_cb, &lock_cb) < 0)
    339     {
    340       _dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
    341       return FALSE;
    342     }
    343   else
    344     {
    345       _dbus_verbose ("Access Vector Cache (AVC) started.\n");
    346     }
    347 
    348   if (avc_add_callback (policy_reload_callback, AVC_CALLBACK_RESET,
    349                        NULL, NULL, 0, 0) < 0)
    350     {
    351       _dbus_warn ("Failed to add policy reload callback: %s\n",
    352                   _dbus_strerror (errno));
    353       avc_destroy ();
    354       return FALSE;
    355     }
    356 
    357   bus_context = NULL;
    358   bus_sid = SECSID_WILD;
    359 
    360   if (getcon (&bus_context) < 0)
    361     {
    362       _dbus_verbose ("Error getting context of bus: %s\n",
    363                      _dbus_strerror (errno));
    364       return FALSE;
    365     }
    366 
    367   if (avc_context_to_sid (bus_context, &bus_sid) < 0)
    368     {
    369       _dbus_verbose ("Error getting SID from bus context: %s\n",
    370                      _dbus_strerror (errno));
    371       freecon (bus_context);
    372       return FALSE;
    373     }
    374 
    375   freecon (bus_context);
    376 
    377 #endif /* HAVE_SELINUX */
    378   return TRUE;
    379 }
    380 
    381 /**
    382  * Decrement SID reference count.
    383  *
    384  * @param sid the SID to decrement
    385  */
    386 void
    387 bus_selinux_id_unref (BusSELinuxID *sid)
    388 {
    389 #ifdef HAVE_SELINUX
    390   if (!selinux_enabled)
    391     return;
    392 
    393   _dbus_assert (sid != NULL);
    394 
    395   sidput (SELINUX_SID_FROM_BUS (sid));
    396 #endif /* HAVE_SELINUX */
    397 }
    398 
    399 void
    400 bus_selinux_id_ref (BusSELinuxID *sid)
    401 {
    402 #ifdef HAVE_SELINUX
    403   if (!selinux_enabled)
    404     return;
    405 
    406   _dbus_assert (sid != NULL);
    407 
    408   sidget (SELINUX_SID_FROM_BUS (sid));
    409 #endif /* HAVE_SELINUX */
    410 }
    411 
    412 /**
    413  * Determine if the SELinux security policy allows the given sender
    414  * security context to go to the given recipient security context.
    415  * This function determines if the requested permissions are to be
    416  * granted from the connection to the message bus or to another
    417  * optionally supplied security identifier (e.g. for a service
    418  * context).  Currently these permissions are either send_msg or
    419  * acquire_svc in the dbus class.
    420  *
    421  * @param sender_sid source security context
    422  * @param override_sid is the target security context.  If SECSID_WILD this will
    423  *        use the context of the bus itself (e.g. the default).
    424  * @param target_class is the target security class.
    425  * @param requested is the requested permissions.
    426  * @returns #TRUE if security policy allows the send.
    427  */
    428 #ifdef HAVE_SELINUX
    429 static dbus_bool_t
    430 bus_selinux_check (BusSELinuxID        *sender_sid,
    431                    BusSELinuxID        *override_sid,
    432                    security_class_t     target_class,
    433                    access_vector_t      requested,
    434 		   DBusString          *auxdata)
    435 {
    436   if (!selinux_enabled)
    437     return TRUE;
    438 
    439   /* Make the security check.  AVC checks enforcing mode here as well. */
    440   if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
    441                     override_sid ?
    442                     SELINUX_SID_FROM_BUS (override_sid) :
    443                     SELINUX_SID_FROM_BUS (bus_sid),
    444                     target_class, requested, &aeref, auxdata) < 0)
    445     {
    446     switch (errno)
    447       {
    448       case EACCES:
    449         _dbus_verbose ("SELinux denying due to security policy.\n");
    450         return FALSE;
    451       case EINVAL:
    452         _dbus_verbose ("SELinux denying due to invalid security context.\n");
    453         return FALSE;
    454       default:
    455         _dbus_verbose ("SELinux denying due to: %s\n", _dbus_strerror (errno));
    456         return FALSE;
    457       }
    458     }
    459   else
    460     return TRUE;
    461 }
    462 #endif /* HAVE_SELINUX */
    463 
    464 /**
    465  * Returns true if the given connection can acquire a service,
    466  * assuming the given security ID is needed for that service.
    467  *
    468  * @param connection connection that wants to own the service
    469  * @param service_sid the SID of the service from the table
    470  * @returns #TRUE if acquire is permitted.
    471  */
    472 dbus_bool_t
    473 bus_selinux_allows_acquire_service (DBusConnection     *connection,
    474                                     BusSELinuxID       *service_sid,
    475 				    const char         *service_name,
    476 				    DBusError          *error)
    477 {
    478 #ifdef HAVE_SELINUX
    479   BusSELinuxID *connection_sid;
    480   unsigned long spid;
    481   DBusString auxdata;
    482   dbus_bool_t ret;
    483 
    484   if (!selinux_enabled)
    485     return TRUE;
    486 
    487   connection_sid = bus_connection_get_selinux_id (connection);
    488   if (!dbus_connection_get_unix_process_id (connection, &spid))
    489     spid = 0;
    490 
    491   if (!_dbus_string_init (&auxdata))
    492     goto oom;
    493 
    494   if (!_dbus_string_append (&auxdata, "service="))
    495     goto oom;
    496 
    497   if (!_dbus_string_append (&auxdata, service_name))
    498     goto oom;
    499 
    500   if (spid)
    501     {
    502       if (!_dbus_string_append (&auxdata, " spid="))
    503 	goto oom;
    504 
    505       if (!_dbus_string_append_uint (&auxdata, spid))
    506 	goto oom;
    507     }
    508 
    509   ret = bus_selinux_check (connection_sid,
    510 			   service_sid,
    511 			   SECCLASS_DBUS,
    512 			   DBUS__ACQUIRE_SVC,
    513 			   &auxdata);
    514 
    515   _dbus_string_free (&auxdata);
    516   return ret;
    517 
    518  oom:
    519   _dbus_string_free (&auxdata);
    520   BUS_SET_OOM (error);
    521   return FALSE;
    522 
    523 #else
    524   return TRUE;
    525 #endif /* HAVE_SELINUX */
    526 }
    527 
    528 /**
    529  * Check if SELinux security controls allow the message to be sent to a
    530  * particular connection based on the security context of the sender and
    531  * that of the receiver. The destination connection need not be the
    532  * addressed recipient, it could be an "eavesdropper"
    533  *
    534  * @param sender the sender of the message.
    535  * @param proposed_recipient the connection the message is to be sent to.
    536  * @returns whether to allow the send
    537  */
    538 dbus_bool_t
    539 bus_selinux_allows_send (DBusConnection     *sender,
    540                          DBusConnection     *proposed_recipient,
    541 			 const char         *msgtype,
    542 			 const char         *interface,
    543 			 const char         *member,
    544 			 const char         *error_name,
    545 			 const char         *destination,
    546 			 DBusError          *error)
    547 {
    548 #ifdef HAVE_SELINUX
    549   BusSELinuxID *recipient_sid;
    550   BusSELinuxID *sender_sid;
    551   unsigned long spid, tpid;
    552   DBusString auxdata;
    553   dbus_bool_t ret;
    554   dbus_bool_t string_alloced;
    555 
    556   if (!selinux_enabled)
    557     return TRUE;
    558 
    559   if (!sender || !dbus_connection_get_unix_process_id (sender, &spid))
    560     spid = 0;
    561   if (!proposed_recipient || !dbus_connection_get_unix_process_id (proposed_recipient, &tpid))
    562     tpid = 0;
    563 
    564   string_alloced = FALSE;
    565   if (!_dbus_string_init (&auxdata))
    566     goto oom;
    567   string_alloced = TRUE;
    568 
    569   if (!_dbus_string_append (&auxdata, "msgtype="))
    570     goto oom;
    571 
    572   if (!_dbus_string_append (&auxdata, msgtype))
    573     goto oom;
    574 
    575   if (interface)
    576     {
    577       if (!_dbus_string_append (&auxdata, " interface="))
    578 	goto oom;
    579       if (!_dbus_string_append (&auxdata, interface))
    580 	goto oom;
    581     }
    582 
    583   if (member)
    584     {
    585       if (!_dbus_string_append (&auxdata, " member="))
    586 	goto oom;
    587       if (!_dbus_string_append (&auxdata, member))
    588 	goto oom;
    589     }
    590 
    591   if (error_name)
    592     {
    593       if (!_dbus_string_append (&auxdata, " error_name="))
    594 	goto oom;
    595       if (!_dbus_string_append (&auxdata, error_name))
    596 	goto oom;
    597     }
    598 
    599   if (destination)
    600     {
    601       if (!_dbus_string_append (&auxdata, " dest="))
    602 	goto oom;
    603       if (!_dbus_string_append (&auxdata, destination))
    604 	goto oom;
    605     }
    606 
    607   if (spid)
    608     {
    609       if (!_dbus_string_append (&auxdata, " spid="))
    610 	goto oom;
    611 
    612       if (!_dbus_string_append_uint (&auxdata, spid))
    613 	goto oom;
    614     }
    615 
    616   if (tpid)
    617     {
    618       if (!_dbus_string_append (&auxdata, " tpid="))
    619 	goto oom;
    620 
    621       if (!_dbus_string_append_uint (&auxdata, tpid))
    622 	goto oom;
    623     }
    624 
    625   sender_sid = bus_connection_get_selinux_id (sender);
    626   /* A NULL proposed_recipient means the bus itself. */
    627   if (proposed_recipient)
    628     recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
    629   else
    630     recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);
    631 
    632   ret = bus_selinux_check (sender_sid,
    633 			   recipient_sid,
    634 			   SECCLASS_DBUS,
    635 			   DBUS__SEND_MSG,
    636 			   &auxdata);
    637 
    638   _dbus_string_free (&auxdata);
    639 
    640   return ret;
    641 
    642  oom:
    643   if (string_alloced)
    644     _dbus_string_free (&auxdata);
    645   BUS_SET_OOM (error);
    646   return FALSE;
    647 
    648 #else
    649   return TRUE;
    650 #endif /* HAVE_SELINUX */
    651 }
    652 
    653 dbus_bool_t
    654 bus_selinux_append_context (DBusMessage    *message,
    655 			    BusSELinuxID   *sid,
    656 			    DBusError      *error)
    657 {
    658 #ifdef HAVE_SELINUX
    659   char *context;
    660 
    661   if (avc_sid_to_context (SELINUX_SID_FROM_BUS (sid), &context) < 0)
    662     {
    663       if (errno == ENOMEM)
    664         BUS_SET_OOM (error);
    665       else
    666         dbus_set_error (error, DBUS_ERROR_FAILED,
    667                         "Error getting context from SID: %s\n",
    668 			_dbus_strerror (errno));
    669       return FALSE;
    670     }
    671   if (!dbus_message_append_args (message,
    672 				 DBUS_TYPE_ARRAY,
    673 				 DBUS_TYPE_BYTE,
    674 				 &context,
    675 				 strlen (context),
    676 				 DBUS_TYPE_INVALID))
    677     {
    678       _DBUS_SET_OOM (error);
    679       return FALSE;
    680     }
    681   freecon (context);
    682   return TRUE;
    683 #else
    684   return TRUE;
    685 #endif
    686 }
    687 
    688 /**
    689  * Gets the security context of a connection to the bus. It is up to
    690  * the caller to freecon() when they are done.
    691  *
    692  * @param connection the connection to get the context of.
    693  * @param con the location to store the security context.
    694  * @returns #TRUE if context is successfully obtained.
    695  */
    696 #ifdef HAVE_SELINUX
    697 static dbus_bool_t
    698 bus_connection_read_selinux_context (DBusConnection     *connection,
    699                                      char              **con)
    700 {
    701   int fd;
    702 
    703   if (!selinux_enabled)
    704     return FALSE;
    705 
    706   _dbus_assert (connection != NULL);
    707 
    708   if (!dbus_connection_get_unix_fd (connection, &fd))
    709     {
    710       _dbus_verbose ("Failed to get file descriptor of socket.\n");
    711       return FALSE;
    712     }
    713 
    714   if (getpeercon (fd, con) < 0)
    715     {
    716       _dbus_verbose ("Error getting context of socket peer: %s\n",
    717                      _dbus_strerror (errno));
    718       return FALSE;
    719     }
    720 
    721   _dbus_verbose ("Successfully read connection context.\n");
    722   return TRUE;
    723 }
    724 #endif /* HAVE_SELINUX */
    725 
    726 /**
    727  * Read the SELinux ID from the connection.
    728  *
    729  * @param connection the connection to read from
    730  * @returns the SID if successfully determined, #NULL otherwise.
    731  */
    732 BusSELinuxID*
    733 bus_selinux_init_connection_id (DBusConnection *connection,
    734                                 DBusError      *error)
    735 {
    736 #ifdef HAVE_SELINUX
    737   char *con;
    738   security_id_t sid;
    739 
    740   if (!selinux_enabled)
    741     return NULL;
    742 
    743   if (!bus_connection_read_selinux_context (connection, &con))
    744     {
    745       dbus_set_error (error, DBUS_ERROR_FAILED,
    746                       "Failed to read an SELinux context from connection");
    747       _dbus_verbose ("Error getting peer context.\n");
    748       return NULL;
    749     }
    750 
    751   _dbus_verbose ("Converting context to SID to store on connection\n");
    752 
    753   if (avc_context_to_sid (con, &sid) < 0)
    754     {
    755       if (errno == ENOMEM)
    756         BUS_SET_OOM (error);
    757       else
    758         dbus_set_error (error, DBUS_ERROR_FAILED,
    759                         "Error getting SID from context \"%s\": %s\n",
    760 			con, _dbus_strerror (errno));
    761 
    762       _dbus_warn ("Error getting SID from context \"%s\": %s\n",
    763 		  con, _dbus_strerror (errno));
    764 
    765       freecon (con);
    766       return NULL;
    767     }
    768 
    769   freecon (con);
    770   return BUS_SID_FROM_SELINUX (sid);
    771 #else
    772   return NULL;
    773 #endif /* HAVE_SELINUX */
    774 }
    775 
    776 
    777 /**
    778  * Function for freeing hash table data.  These SIDs
    779  * should no longer be referenced.
    780  */
    781 static void
    782 bus_selinux_id_table_free_value (BusSELinuxID *sid)
    783 {
    784 #ifdef HAVE_SELINUX
    785   /* NULL sometimes due to how DBusHashTable works */
    786   if (sid)
    787     bus_selinux_id_unref (sid);
    788 #endif /* HAVE_SELINUX */
    789 }
    790 
    791 /**
    792  * Creates a new table mapping service names to security ID.
    793  * A security ID is a "compiled" security context, a security
    794  * context is just a string.
    795  *
    796  * @returns the new table or #NULL if no memory
    797  */
    798 DBusHashTable*
    799 bus_selinux_id_table_new (void)
    800 {
    801   return _dbus_hash_table_new (DBUS_HASH_STRING,
    802                                (DBusFreeFunction) dbus_free,
    803                                (DBusFreeFunction) bus_selinux_id_table_free_value);
    804 }
    805 
    806 /**
    807  * Hashes a service name and service context into the service SID
    808  * table as a string and a SID.
    809  *
    810  * @param service_name is the name of the service.
    811  * @param service_context is the context of the service.
    812  * @param service_table is the table to hash them into.
    813  * @return #FALSE if not enough memory
    814  */
    815 dbus_bool_t
    816 bus_selinux_id_table_insert (DBusHashTable *service_table,
    817                              const char    *service_name,
    818                              const char    *service_context)
    819 {
    820 #ifdef HAVE_SELINUX
    821   dbus_bool_t retval;
    822   security_id_t sid;
    823   char *key;
    824 
    825   if (!selinux_enabled)
    826     return TRUE;
    827 
    828   sid = SECSID_WILD;
    829   retval = FALSE;
    830 
    831   key = _dbus_strdup (service_name);
    832   if (key == NULL)
    833     return retval;
    834 
    835   if (avc_context_to_sid ((char *) service_context, &sid) < 0)
    836     {
    837       if (errno == ENOMEM)
    838         {
    839 	  dbus_free (key);
    840           return FALSE;
    841 	}
    842 
    843       _dbus_warn ("Error getting SID from context \"%s\": %s\n",
    844 		  (char *) service_context,
    845                   _dbus_strerror (errno));
    846       goto out;
    847     }
    848 
    849   if (!_dbus_hash_table_insert_string (service_table,
    850                                        key,
    851                                        BUS_SID_FROM_SELINUX (sid)))
    852     goto out;
    853 
    854   _dbus_verbose ("Parsed \tservice: %s \n\t\tcontext: %s\n",
    855                   key,
    856                   sid->ctx);
    857 
    858   /* These are owned by the hash, so clear them to avoid unref */
    859   key = NULL;
    860   sid = SECSID_WILD;
    861 
    862   retval = TRUE;
    863 
    864  out:
    865   if (sid != SECSID_WILD)
    866     sidput (sid);
    867 
    868   if (key)
    869     dbus_free (key);
    870 
    871   return retval;
    872 #else
    873   return TRUE;
    874 #endif /* HAVE_SELINUX */
    875 }
    876 
    877 
    878 /**
    879  * Find the security identifier associated with a particular service
    880  * name.  Return a pointer to this SID, or #NULL/SECSID_WILD if the
    881  * service is not found in the hash table.  This should be nearly a
    882  * constant time operation.  If SELinux support is not available,
    883  * always return NULL.
    884  *
    885  * @param service_table the hash table to check for service name.
    886  * @param service_name the name of the service to look for.
    887  * @returns the SELinux ID associated with the service
    888  */
    889 BusSELinuxID*
    890 bus_selinux_id_table_lookup (DBusHashTable    *service_table,
    891                              const DBusString *service_name)
    892 {
    893 #ifdef HAVE_SELINUX
    894   security_id_t sid;
    895 
    896   sid = SECSID_WILD;     /* default context */
    897 
    898   if (!selinux_enabled)
    899     return NULL;
    900 
    901   _dbus_verbose ("Looking up service SID for %s\n",
    902                  _dbus_string_get_const_data (service_name));
    903 
    904   sid = _dbus_hash_table_lookup_string (service_table,
    905                                         _dbus_string_get_const_data (service_name));
    906 
    907   if (sid == SECSID_WILD)
    908     _dbus_verbose ("Service %s not found\n",
    909                    _dbus_string_get_const_data (service_name));
    910   else
    911     _dbus_verbose ("Service %s found\n",
    912                    _dbus_string_get_const_data (service_name));
    913 
    914   return BUS_SID_FROM_SELINUX (sid);
    915 #endif /* HAVE_SELINUX */
    916   return NULL;
    917 }
    918 
    919 /**
    920  * Get the SELinux policy root.  This is used to find the D-Bus
    921  * specific config file within the policy.
    922  */
    923 const char *
    924 bus_selinux_get_policy_root (void)
    925 {
    926 #ifdef HAVE_SELINUX
    927   return selinux_policy_root ();
    928 #else
    929   return NULL;
    930 #endif /* HAVE_SELINUX */
    931 }
    932 
    933 /**
    934  * For debugging:  Print out the current hash table of service SIDs.
    935  */
    936 void
    937 bus_selinux_id_table_print (DBusHashTable *service_table)
    938 {
    939 #ifdef DBUS_ENABLE_VERBOSE_MODE
    940 #ifdef HAVE_SELINUX
    941   DBusHashIter iter;
    942 
    943   if (!selinux_enabled)
    944     return;
    945 
    946   _dbus_verbose ("Service SID Table:\n");
    947   _dbus_hash_iter_init (service_table, &iter);
    948   while (_dbus_hash_iter_next (&iter))
    949     {
    950       const char *key = _dbus_hash_iter_get_string_key (&iter);
    951       security_id_t sid = _dbus_hash_iter_get_value (&iter);
    952       _dbus_verbose ("The key is %s\n", key);
    953       _dbus_verbose ("The context is %s\n", sid->ctx);
    954       _dbus_verbose ("The refcount is %d\n", sid->refcnt);
    955     }
    956 #endif /* HAVE_SELINUX */
    957 #endif /* DBUS_ENABLE_VERBOSE_MODE */
    958 }
    959 
    960 
    961 #ifdef DBUS_ENABLE_VERBOSE_MODE
    962 #ifdef HAVE_SELINUX
    963 /**
    964  * Print out some AVC statistics.
    965  */
    966 static void
    967 bus_avc_print_stats (void)
    968 {
    969   struct avc_cache_stats cstats;
    970 
    971   if (!selinux_enabled)
    972     return;
    973 
    974   _dbus_verbose ("AVC Statistics:\n");
    975   avc_cache_stats (&cstats);
    976   avc_av_stats ();
    977   _dbus_verbose ("AVC Cache Statistics:\n");
    978   _dbus_verbose ("Entry lookups: %d\n", cstats.entry_lookups);
    979   _dbus_verbose ("Entry hits: %d\n", cstats.entry_hits);
    980   _dbus_verbose ("Entry misses %d\n", cstats.entry_misses);
    981   _dbus_verbose ("Entry discards: %d\n", cstats.entry_discards);
    982   _dbus_verbose ("CAV lookups: %d\n", cstats.cav_lookups);
    983   _dbus_verbose ("CAV hits: %d\n", cstats.cav_hits);
    984   _dbus_verbose ("CAV probes: %d\n", cstats.cav_probes);
    985   _dbus_verbose ("CAV misses: %d\n", cstats.cav_misses);
    986 }
    987 #endif /* HAVE_SELINUX */
    988 #endif /* DBUS_ENABLE_VERBOSE_MODE */
    989 
    990 
    991 /**
    992  * Destroy the AVC before we terminate.
    993  */
    994 void
    995 bus_selinux_shutdown (void)
    996 {
    997 #ifdef HAVE_SELINUX
    998   if (!selinux_enabled)
    999     return;
   1000 
   1001   _dbus_verbose ("AVC shutdown\n");
   1002 
   1003   if (bus_sid != SECSID_WILD)
   1004     {
   1005       sidput (bus_sid);
   1006       bus_sid = SECSID_WILD;
   1007 
   1008 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1009 
   1010       if (_dbus_is_verbose())
   1011         bus_avc_print_stats ();
   1012 
   1013 #endif /* DBUS_ENABLE_VERBOSE_MODE */
   1014 
   1015       avc_destroy ();
   1016 #ifdef HAVE_LIBAUDIT
   1017       audit_close (audit_fd);
   1018 #endif /* HAVE_LIBAUDIT */
   1019     }
   1020 #endif /* HAVE_SELINUX */
   1021 }
   1022 
   1023 /* The !HAVE_LIBAUDIT case lives in dbus-sysdeps-util-unix.c */
   1024 #ifdef HAVE_LIBAUDIT
   1025 /**
   1026  * Changes the user and group the bus is running as.
   1027  *
   1028  * @param user the user to become
   1029  * @param error return location for errors
   1030  * @returns #FALSE on failure
   1031  */
   1032 dbus_bool_t
   1033 _dbus_change_to_daemon_user  (const char    *user,
   1034                               DBusError     *error)
   1035 {
   1036   dbus_uid_t uid;
   1037   dbus_gid_t gid;
   1038   DBusString u;
   1039 
   1040   _dbus_string_init_const (&u, user);
   1041 
   1042   if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
   1043     {
   1044       dbus_set_error (error, DBUS_ERROR_FAILED,
   1045                       "User '%s' does not appear to exist?",
   1046                       user);
   1047       return FALSE;
   1048     }
   1049 
   1050   /* If we were root */
   1051   if (_dbus_geteuid () == 0)
   1052     {
   1053       int rc;
   1054 
   1055       capng_clear (CAPNG_SELECT_BOTH);
   1056       capng_update (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,
   1057                     CAP_AUDIT_WRITE);
   1058       rc = capng_change_id (uid, gid, CAPNG_DROP_SUPP_GRP);
   1059       if (rc)
   1060         {
   1061           switch (rc) {
   1062             default:
   1063               dbus_set_error (error, DBUS_ERROR_FAILED,
   1064                               "Failed to drop capabilities: %s\n",
   1065                               _dbus_strerror (errno));
   1066               break;
   1067             case -4:
   1068               dbus_set_error (error, _dbus_error_from_errno (errno),
   1069                               "Failed to set GID to %lu: %s", gid,
   1070                               _dbus_strerror (errno));
   1071               break;
   1072             case -5:
   1073               _dbus_warn ("Failed to drop supplementary groups: %s\n",
   1074                           _dbus_strerror (errno));
   1075               break;
   1076             case -6:
   1077               dbus_set_error (error, _dbus_error_from_errno (errno),
   1078                               "Failed to set UID to %lu: %s", uid,
   1079                               _dbus_strerror (errno));
   1080               break;
   1081             case -7:
   1082               dbus_set_error (error, _dbus_error_from_errno (errno),
   1083                               "Failed to unset keep-capabilities: %s\n",
   1084                               _dbus_strerror (errno));
   1085               break;
   1086           }
   1087           return FALSE;
   1088         }
   1089     }
   1090 
   1091  return TRUE;
   1092 }
   1093 #endif
   1094