2004-11-07 Colin Walters <walters@verbum.org>
[platform/upstream/dbus.git] / bus / selinux.c
1 /* selinux.c  SELinux security checks for D-BUS
2  *
3  * Author: Matthew Rickard <mjricka@epoch.ncsc.mil>
4  *
5  * Licensed under the Academic Free License version 2.1
6  * 
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22 #include <dbus/dbus-internals.h>
23 #include <dbus/dbus-string.h>
24 #include "selinux.h"
25 #include "services.h"
26 #include "policy.h"
27 #include "utils.h"
28 #include "config-parser.h"
29
30 #ifdef HAVE_SELINUX
31 #include <errno.h>
32 #include <pthread.h>
33 #include <syslog.h>
34 #include <selinux/selinux.h>
35 #include <selinux/avc.h>
36 #include <selinux/av_permissions.h>
37 #include <selinux/flask.h>
38 #include <signal.h>
39 #include <stdarg.h>
40 #endif /* HAVE_SELINUX */
41
42 #define BUS_SID_FROM_SELINUX(sid)  ((BusSELinuxID*) (sid))
43 #define SELINUX_SID_FROM_BUS(sid)  ((security_id_t) (sid))
44
45 #ifdef HAVE_SELINUX
46 /* Store the value telling us if SELinux is enabled in the kernel. */
47 static dbus_bool_t selinux_enabled = FALSE;
48
49 /* Store an avc_entry_ref to speed AVC decisions. */
50 static struct avc_entry_ref aeref;
51
52 /* Store the SID of the bus itself to use as the default. */
53 static security_id_t bus_sid = SECSID_WILD;
54
55 /* Thread to listen for SELinux status changes via netlink. */
56 static pthread_t avc_notify_thread;
57
58 /* Prototypes for AVC callback functions.  */
59 static void log_callback (const char *fmt, ...);
60 static void *avc_create_thread (void (*run) (void));
61 static void avc_stop_thread (void *thread);
62 static void *avc_alloc_lock (void);
63 static void avc_get_lock (void *lock);
64 static void avc_release_lock (void *lock);
65 static void avc_free_lock (void *lock);
66
67 /* AVC callback structures for use in avc_init.  */
68 static const struct avc_memory_callback mem_cb =
69 {
70   .func_malloc = dbus_malloc,
71   .func_free = dbus_free
72 };
73 static const struct avc_log_callback log_cb =
74 {
75   .func_log = log_callback,
76   .func_audit = NULL
77 };
78 static const struct avc_thread_callback thread_cb =
79 {
80   .func_create_thread = avc_create_thread,
81   .func_stop_thread = avc_stop_thread
82 };
83 static const struct avc_lock_callback lock_cb =
84 {
85   .func_alloc_lock = avc_alloc_lock,
86   .func_get_lock = avc_get_lock,
87   .func_release_lock = avc_release_lock,
88   .func_free_lock = avc_free_lock
89 };
90 #endif /* HAVE_SELINUX */
91
92 /**
93  * Log callback to log denial messages from the AVC.
94  * This is used in avc_init.  Logs to both standard
95  * error and syslogd.
96  *
97  * @param fmt the format string
98  * @param variable argument list
99  */
100 #ifdef HAVE_SELINUX
101 static void 
102 log_callback (const char *fmt, ...) 
103 {
104   va_list ap;
105   va_start(ap, fmt);
106   vsyslog (LOG_INFO, fmt, ap);
107   va_end(ap);
108 }
109
110 /**
111  * On a policy reload we need to reparse the SELinux configuration file, since
112  * this could have changed.  Send a SIGHUP to reload all configs.
113  */
114 static int
115 policy_reload_callback (u_int32_t event, security_id_t ssid, 
116                         security_id_t tsid, security_class_t tclass, 
117                         access_vector_t perms, access_vector_t *out_retained)
118 {
119   if (event == AVC_CALLBACK_RESET)
120     return raise (SIGHUP);
121   
122   return 0;
123 }
124
125 /**
126  * Create thread to notify the AVC of enforcing and policy reload
127  * changes via netlink.
128  *
129  * @param run the thread run function
130  * @return pointer to the thread
131  */
132 static void *
133 avc_create_thread (void (*run) (void))
134 {
135   int rc;
136
137   rc = pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
138   if (rc != 0)
139     {
140       _dbus_warn ("Failed to start AVC thread: %s\n", _dbus_strerror (rc));
141       exit (1);
142     }
143   return &avc_notify_thread;
144 }
145
146 /* Stop AVC netlink thread.  */
147 static void
148 avc_stop_thread (void *thread)
149 {
150   pthread_cancel (*(pthread_t *) thread);
151 }
152
153 /* Allocate a new AVC lock.  */
154 static void *
155 avc_alloc_lock (void)
156 {
157   pthread_mutex_t *avc_mutex;
158
159   avc_mutex = dbus_new (pthread_mutex_t, 1);
160   if (avc_mutex == NULL)
161     {
162       _dbus_warn ("Could not create mutex: %s\n", _dbus_strerror (errno));
163       exit (1);
164     }
165   pthread_mutex_init (avc_mutex, NULL);
166
167   return avc_mutex;
168 }
169
170 /* Acquire an AVC lock.  */
171 static void
172 avc_get_lock (void *lock)
173 {
174   pthread_mutex_lock (lock);
175 }
176
177 /* Release an AVC lock.  */
178 static void
179 avc_release_lock (void *lock)
180 {
181   pthread_mutex_unlock (lock);
182 }
183
184 /* Free an AVC lock.  */
185 static void
186 avc_free_lock (void *lock)
187 {
188   pthread_mutex_destroy (lock);
189   dbus_free (lock);
190 }
191 #endif /* HAVE_SELINUX */
192
193 /**
194  * Return whether or not SELinux is enabled; must be
195  * called after bus_selinux_init.
196  */
197 dbus_bool_t
198 bus_selinux_enabled (void)
199 {
200 #ifdef HAVE_SELINUX
201   return selinux_enabled;
202 #else
203   return FALSE;
204 #endif /* HAVE_SELINUX */
205 }
206
207 /**
208  * Do early initialization; determine whether SELinux is enabled.
209  */
210 dbus_bool_t
211 bus_selinux_pre_init (void)
212 {
213 #ifdef HAVE_SELINUX
214   int r;
215   _dbus_assert (bus_sid == SECSID_WILD);
216   
217   /* Determine if we are running an SELinux kernel. */
218   r = is_selinux_enabled ();
219   if (r < 0)
220     {
221       _dbus_warn ("Could not tell if SELinux is enabled: %s\n",
222                   _dbus_strerror (errno));
223       return FALSE;
224     }
225
226   selinux_enabled = r != 0;
227   return TRUE;
228 #else
229   return TRUE;
230 #endif
231 }
232
233 /**
234  * Initialize the user space access vector cache (AVC) for D-BUS and set up
235  * logging callbacks.
236  */
237 dbus_bool_t
238 bus_selinux_full_init (void)
239 {
240 #ifdef HAVE_SELINUX
241   char *bus_context;
242
243   _dbus_assert (bus_sid == SECSID_WILD);
244   
245   if (!selinux_enabled)
246     {
247       _dbus_verbose ("SELinux not enabled in this kernel.\n");
248       return TRUE;
249     }
250
251   _dbus_verbose ("SELinux is enabled in this kernel.\n");
252
253   avc_entry_ref_init (&aeref);
254   if (avc_init ("avc", &mem_cb, &log_cb, &thread_cb, &lock_cb) < 0)
255     {
256       _dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
257       return FALSE;
258     }
259   else
260     {
261       openlog ("dbus", LOG_PERROR, LOG_USER);
262       _dbus_verbose ("Access Vector Cache (AVC) started.\n");
263     }
264
265   if (avc_add_callback (policy_reload_callback, AVC_CALLBACK_RESET,
266                        NULL, NULL, 0, 0) < 0)
267     {
268       _dbus_warn ("Failed to add policy reload callback: %s\n",
269                   _dbus_strerror (errno));
270       avc_destroy ();
271       return FALSE;
272     }
273
274   bus_context = NULL;
275   bus_sid = SECSID_WILD;
276
277   if (getcon (&bus_context) < 0)
278     {
279       _dbus_verbose ("Error getting context of bus: %s\n",
280                      _dbus_strerror (errno));
281       return FALSE;
282     }
283       
284   if (avc_context_to_sid (bus_context, &bus_sid) < 0)
285     {
286       _dbus_verbose ("Error getting SID from bus context: %s\n",
287                      _dbus_strerror (errno));
288       freecon (bus_context);
289       return FALSE;
290     }
291
292   freecon (bus_context);
293   
294   return TRUE;
295 #else
296   return TRUE;
297 #endif /* HAVE_SELINUX */
298 }
299
300 /**
301  * Decrement SID reference count.
302  * 
303  * @param sid the SID to decrement
304  */
305 void
306 bus_selinux_id_unref (BusSELinuxID *sid)
307 {
308 #ifdef HAVE_SELINUX
309   if (!selinux_enabled)
310     return;
311
312   _dbus_assert (sid != NULL);
313   
314   sidput (SELINUX_SID_FROM_BUS (sid));
315 #endif /* HAVE_SELINUX */
316 }
317
318 void
319 bus_selinux_id_ref (BusSELinuxID *sid)
320 {
321 #ifdef HAVE_SELINUX
322   if (!selinux_enabled)
323     return;
324
325   _dbus_assert (sid != NULL);
326   
327   sidget (SELINUX_SID_FROM_BUS (sid));
328 #endif /* HAVE_SELINUX */
329 }
330
331 /**
332  * Determine if the SELinux security policy allows the given sender
333  * security context to go to the given recipient security context.
334  * This function determines if the requested permissions are to be
335  * granted from the connection to the message bus or to another
336  * optionally supplied security identifier (e.g. for a service
337  * context).  Currently these permissions are either send_msg or
338  * acquire_svc in the dbus class.
339  *
340  * @param sender_sid source security context
341  * @param override_sid is the target security context.  If SECSID_WILD this will
342  *        use the context of the bus itself (e.g. the default).
343  * @param target_class is the target security class.
344  * @param requested is the requested permissions.
345  * @returns #TRUE if security policy allows the send.
346  */
347 #ifdef HAVE_SELINUX
348 static dbus_bool_t
349 bus_selinux_check (BusSELinuxID        *sender_sid,
350                    BusSELinuxID        *override_sid,
351                    security_class_t     target_class,
352                    access_vector_t      requested)
353 {
354   if (!selinux_enabled)
355     return TRUE;
356
357   /* Make the security check.  AVC checks enforcing mode here as well. */
358   if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
359                     override_sid ?
360                     SELINUX_SID_FROM_BUS (override_sid) :
361                     SELINUX_SID_FROM_BUS (bus_sid), 
362                     target_class, requested, &aeref, NULL) < 0)
363     {
364       _dbus_verbose ("SELinux denying due to security policy.\n");
365       return FALSE;
366     }
367   else
368     return TRUE;
369 }
370 #endif /* HAVE_SELINUX */
371
372 /**
373  * Returns true if the given connection can acquire a service,
374  * assuming the given security ID is needed for that service.
375  *
376  * @param connection connection that wants to own the service
377  * @param service_sid the SID of the service from the table
378  * @returns #TRUE if acquire is permitted.
379  */
380 dbus_bool_t
381 bus_selinux_allows_acquire_service (DBusConnection     *connection,
382                                     BusSELinuxID       *service_sid)
383 {
384 #ifdef HAVE_SELINUX
385   BusSELinuxID *connection_sid;
386   
387   if (!selinux_enabled)
388     return TRUE;
389
390   connection_sid = bus_connection_get_selinux_id (connection);
391   
392   return bus_selinux_check (connection_sid,
393                             service_sid,
394                             SECCLASS_DBUS,
395                             DBUS__ACQUIRE_SVC);
396 #else
397   return TRUE;
398 #endif /* HAVE_SELINUX */
399 }
400
401 /**
402  * Check if SELinux security controls allow the message to be sent to a
403  * particular connection based on the security context of the sender and
404  * that of the receiver. The destination connection need not be the
405  * addressed recipient, it could be an "eavesdropper"
406  *
407  * @param sender the sender of the message.
408  * @param proposed_recipient the connection the message is to be sent to.
409  * @returns whether to allow the send
410  */
411 dbus_bool_t
412 bus_selinux_allows_send (DBusConnection     *sender,
413                          DBusConnection     *proposed_recipient)
414 {
415 #ifdef HAVE_SELINUX
416   BusSELinuxID *recipient_sid;
417   BusSELinuxID *sender_sid;
418
419   if (!selinux_enabled)
420     return TRUE;
421
422   sender_sid = bus_connection_get_selinux_id (sender);
423   /* A NULL proposed_recipient means the bus itself. */
424   if (proposed_recipient)
425     recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
426   else
427     recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);
428
429   return bus_selinux_check (sender_sid, recipient_sid,
430                             SECCLASS_DBUS, DBUS__SEND_MSG);
431 #else
432   return TRUE;
433 #endif /* HAVE_SELINUX */
434 }
435
436 /**
437  * Gets the security context of a connection to the bus. It is up to
438  * the caller to freecon() when they are done. 
439  *
440  * @param connection the connection to get the context of.
441  * @param con the location to store the security context.
442  * @returns #TRUE if context is successfully obtained.
443  */
444 #ifdef HAVE_SELINUX
445 static dbus_bool_t
446 bus_connection_read_selinux_context (DBusConnection     *connection,
447                                      char              **con)
448 {
449   int fd;
450
451   if (!selinux_enabled)
452     return FALSE;
453
454   _dbus_assert (connection != NULL);
455   
456   if (!dbus_connection_get_unix_fd (connection, &fd))
457     {
458       _dbus_verbose ("Failed to get file descriptor of socket.\n");
459       return FALSE;
460     }
461   
462   if (getpeercon (fd, con) < 0)
463     {
464       _dbus_verbose ("Error getting context of socket peer: %s\n",
465                      _dbus_strerror (errno));
466       return FALSE;
467     }
468   
469   _dbus_verbose ("Successfully read connection context.\n");
470   return TRUE;
471 }
472 #endif /* HAVE_SELINUX */
473
474 /**
475  * Read the SELinux ID from the connection.
476  *
477  * @param connection the connection to read from
478  * @returns the SID if successfully determined, #NULL otherwise.
479  */
480 BusSELinuxID*
481 bus_selinux_init_connection_id (DBusConnection *connection,
482                                 DBusError      *error)
483 {
484 #ifdef HAVE_SELINUX
485   char *con;
486   security_id_t sid;
487   
488   if (!selinux_enabled)
489     return NULL;
490
491   if (!bus_connection_read_selinux_context (connection, &con))
492     {
493       dbus_set_error (error, DBUS_ERROR_FAILED,
494                       "Failed to read an SELinux context from connection");
495       _dbus_verbose ("Error getting peer context.\n");
496       return NULL;
497     }
498
499   _dbus_verbose ("Converting context to SID to store on connection\n");
500
501   if (avc_context_to_sid (con, &sid) < 0)
502     {
503       if (errno == ENOMEM)
504         BUS_SET_OOM (error);
505       else
506         dbus_set_error (error, DBUS_ERROR_FAILED,
507                         "Error getting SID from context \"%s\": %s\n",
508                         con, _dbus_strerror (errno));
509       
510       _dbus_warn ("Error getting SID from context \"%s\": %s\n",
511                   con, _dbus_strerror (errno));
512       
513       freecon (con);
514       return NULL;
515     }
516  
517   freecon (con); 
518   return BUS_SID_FROM_SELINUX (sid);
519 #else
520   return NULL;
521 #endif /* HAVE_SELINUX */
522 }
523
524
525 /**
526  * Function for freeing hash table data.  These SIDs
527  * should no longer be referenced.
528  */
529 static void
530 bus_selinux_id_table_free_value (BusSELinuxID *sid)
531 {
532 #ifdef HAVE_SELINUX
533   /* NULL sometimes due to how DBusHashTable works */
534   if (sid)
535     bus_selinux_id_unref (sid);
536 #endif /* HAVE_SELINUX */
537 }
538
539 /**
540  * Creates a new table mapping service names to security ID.
541  * A security ID is a "compiled" security context, a security
542  * context is just a string.
543  *
544  * @returns the new table or #NULL if no memory
545  */
546 DBusHashTable*
547 bus_selinux_id_table_new (void)
548 {
549   return _dbus_hash_table_new (DBUS_HASH_STRING,
550                                (DBusFreeFunction) dbus_free,
551                                (DBusFreeFunction) bus_selinux_id_table_free_value);
552 }
553
554 /** 
555  * Hashes a service name and service context into the service SID
556  * table as a string and a SID.
557  *
558  * @param service_name is the name of the service.
559  * @param service_context is the context of the service.
560  * @param service_table is the table to hash them into.
561  * @return #FALSE if not enough memory
562  */
563 dbus_bool_t
564 bus_selinux_id_table_insert (DBusHashTable *service_table,
565                              const char    *service_name,
566                              const char    *service_context)
567 {
568 #ifdef HAVE_SELINUX
569   dbus_bool_t retval;
570   security_id_t sid;
571   char *key;
572
573   if (!selinux_enabled)
574     return TRUE;
575
576   sid = SECSID_WILD;
577   retval = FALSE;
578
579   key = _dbus_strdup (service_name);
580   if (key == NULL)
581     return retval;
582   
583   if (avc_context_to_sid ((char *) service_context, &sid) < 0)
584     {
585       if (errno == ENOMEM)
586         return FALSE;
587       _dbus_warn ("Error getting SID from context \"%s\": %s\n",
588                   (char *) service_context,
589                   _dbus_strerror (errno));
590       goto out;
591     }
592
593   if (!_dbus_hash_table_insert_string (service_table,
594                                        key,
595                                        BUS_SID_FROM_SELINUX (sid)))
596     goto out;
597
598   _dbus_verbose ("Parsed \tservice: %s \n\t\tcontext: %s\n",
599                   key, 
600                   sid->ctx);
601
602   /* These are owned by the hash, so clear them to avoid unref */
603   key = NULL;
604   sid = SECSID_WILD;
605
606   retval = TRUE;
607   
608  out:
609   if (sid != SECSID_WILD)
610     sidput (sid);
611
612   if (key)
613     dbus_free (key);
614
615   return retval;
616 #else
617   return TRUE;
618 #endif /* HAVE_SELINUX */
619 }
620
621
622 /**
623  * Find the security identifier associated with a particular service
624  * name.  Return a pointer to this SID, or #NULL/SECSID_WILD if the
625  * service is not found in the hash table.  This should be nearly a
626  * constant time operation.  If SELinux support is not available,
627  * always return NULL.
628  *
629  * @param service_table the hash table to check for service name.
630  * @param service_name the name of the service to look for.
631  * @returns the SELinux ID associated with the service
632  */
633 BusSELinuxID*
634 bus_selinux_id_table_lookup (DBusHashTable    *service_table,
635                              const DBusString *service_name)
636 {
637 #ifdef HAVE_SELINUX
638   security_id_t sid;
639
640   sid = SECSID_WILD;     /* default context */
641
642   if (!selinux_enabled)
643     return NULL;
644   
645   _dbus_verbose ("Looking up service SID for %s\n",
646                  _dbus_string_get_const_data (service_name));
647
648   sid = _dbus_hash_table_lookup_string (service_table,
649                                         _dbus_string_get_const_data (service_name));
650
651   if (sid == SECSID_WILD)
652     _dbus_verbose ("Service %s not found\n", 
653                    _dbus_string_get_const_data (service_name));
654   else
655     _dbus_verbose ("Service %s found\n", 
656                    _dbus_string_get_const_data (service_name));
657
658   return BUS_SID_FROM_SELINUX (sid);
659 #endif /* HAVE_SELINUX */
660   return NULL;
661 }
662
663 /**
664  * Get the SELinux policy root.  This is used to find the D-BUS
665  * specific config file within the policy.
666  */
667 const char *
668 bus_selinux_get_policy_root (void)
669 {
670 #ifdef HAVE_SELINUX
671   return selinux_policy_root ();
672 #else
673   return NULL;
674 #endif /* HAVE_SELINUX */
675
676
677 /**
678  * For debugging:  Print out the current hash table of service SIDs.
679  */
680 void
681 bus_selinux_id_table_print (DBusHashTable *service_table)
682 {
683 #ifdef DBUS_ENABLE_VERBOSE_MODE
684 #ifdef HAVE_SELINUX
685   DBusHashIter iter;
686
687   if (!selinux_enabled)
688     return;
689   
690   _dbus_verbose ("Service SID Table:\n");
691   _dbus_hash_iter_init (service_table, &iter);
692   while (_dbus_hash_iter_next (&iter))
693     {
694       const char *key = _dbus_hash_iter_get_string_key (&iter);
695       security_id_t sid = _dbus_hash_iter_get_value (&iter);
696       _dbus_verbose ("The key is %s\n", key);
697       _dbus_verbose ("The context is %s\n", sid->ctx);
698       _dbus_verbose ("The refcount is %d\n", sid->refcnt);
699     }
700 #endif /* HAVE_SELINUX */
701 #endif /* DBUS_ENABLE_VERBOSE_MODE */
702 }
703
704
705 #ifdef DBUS_ENABLE_VERBOSE_MODE
706 #ifdef HAVE_SELINUX
707 /**
708  * Print out some AVC statistics.
709  */
710 static void
711 bus_avc_print_stats (void)
712 {
713   struct avc_cache_stats cstats;
714
715   if (!selinux_enabled)
716     return;
717   
718   _dbus_verbose ("AVC Statistics:\n");
719   avc_cache_stats (&cstats);
720   avc_av_stats ();
721   _dbus_verbose ("AVC Cache Statistics:\n");
722   _dbus_verbose ("Entry lookups: %d\n", cstats.entry_lookups);
723   _dbus_verbose ("Entry hits: %d\n", cstats.entry_hits);
724   _dbus_verbose ("Entry misses %d\n", cstats.entry_misses);
725   _dbus_verbose ("Entry discards: %d\n", cstats.entry_discards);
726   _dbus_verbose ("CAV lookups: %d\n", cstats.cav_lookups);
727   _dbus_verbose ("CAV hits: %d\n", cstats.cav_hits);
728   _dbus_verbose ("CAV probes: %d\n", cstats.cav_probes);
729   _dbus_verbose ("CAV misses: %d\n", cstats.cav_misses);
730 }
731 #endif /* HAVE_SELINUX */
732 #endif /* DBUS_ENABLE_VERBOSE_MODE */
733
734
735 /**
736  * Destroy the AVC before we terminate.
737  */
738 void
739 bus_selinux_shutdown (void)
740 {
741 #ifdef HAVE_SELINUX
742   if (!selinux_enabled)
743     return;
744
745   sidput (bus_sid);
746   bus_sid = SECSID_WILD;
747   
748 #ifdef DBUS_ENABLE_VERBOSE_MODE
749   bus_avc_print_stats ();
750 #endif /* DBUS_ENABLE_VERBOSE_MODE */
751
752   avc_destroy ();
753 #endif /* HAVE_SELINUX */
754 }
755