1 /* selinux.c SELinux security checks for D-BUS
3 * Author: Matthew Rickard <mjricka@epoch.ncsc.mil>
5 * Licensed under the Academic Free License version 2.1
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.
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.
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
22 #include <dbus/dbus-internals.h>
23 #include <dbus/dbus-string.h>
28 #include "config-parser.h"
34 #include <selinux/selinux.h>
35 #include <selinux/avc.h>
36 #include <selinux/av_permissions.h>
37 #include <selinux/flask.h>
40 #endif /* HAVE_SELINUX */
42 #define BUS_SID_FROM_SELINUX(sid) ((BusSELinuxID*) (sid))
43 #define SELINUX_SID_FROM_BUS(sid) ((security_id_t) (sid))
46 /* Store the value telling us if SELinux is enabled in the kernel. */
47 static dbus_bool_t selinux_enabled = FALSE;
49 /* Store an avc_entry_ref to speed AVC decisions. */
50 static struct avc_entry_ref aeref;
52 /* Store the SID of the bus itself to use as the default. */
53 static security_id_t bus_sid = SECSID_WILD;
55 /* Thread to listen for SELinux status changes via netlink. */
56 static pthread_t avc_notify_thread;
58 /* Prototypes for AVC callback functions. */
59 static void log_callback (const char *fmt, ...);
60 static void log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft);
61 static void *avc_create_thread (void (*run) (void));
62 static void avc_stop_thread (void *thread);
63 static void *avc_alloc_lock (void);
64 static void avc_get_lock (void *lock);
65 static void avc_release_lock (void *lock);
66 static void avc_free_lock (void *lock);
68 /* AVC callback structures for use in avc_init. */
69 static const struct avc_memory_callback mem_cb =
71 .func_malloc = dbus_malloc,
72 .func_free = dbus_free
74 static const struct avc_log_callback log_cb =
76 .func_log = log_callback,
77 .func_audit = log_audit_callback
79 static const struct avc_thread_callback thread_cb =
81 .func_create_thread = avc_create_thread,
82 .func_stop_thread = avc_stop_thread
84 static const struct avc_lock_callback lock_cb =
86 .func_alloc_lock = avc_alloc_lock,
87 .func_get_lock = avc_get_lock,
88 .func_release_lock = avc_release_lock,
89 .func_free_lock = avc_free_lock
91 #endif /* HAVE_SELINUX */
94 * Log callback to log denial messages from the AVC.
95 * This is used in avc_init. Logs to both standard
98 * @param fmt the format string
99 * @param variable argument list
103 log_callback (const char *fmt, ...)
107 vsyslog (LOG_INFO, fmt, ap);
112 * On a policy reload we need to reparse the SELinux configuration file, since
113 * this could have changed. Send a SIGHUP to reload all configs.
116 policy_reload_callback (u_int32_t event, security_id_t ssid,
117 security_id_t tsid, security_class_t tclass,
118 access_vector_t perms, access_vector_t *out_retained)
120 if (event == AVC_CALLBACK_RESET)
121 return raise (SIGHUP);
127 * Log any auxiliary data
130 log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft)
132 DBusString *audmsg = data;
133 _dbus_string_copy_to_buffer (audmsg, buf, bufleft);
134 _dbus_string_free (audmsg);
139 * Create thread to notify the AVC of enforcing and policy reload
140 * changes via netlink.
142 * @param run the thread run function
143 * @return pointer to the thread
146 avc_create_thread (void (*run) (void))
150 rc = pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
153 _dbus_warn ("Failed to start AVC thread: %s\n", _dbus_strerror (rc));
156 return &avc_notify_thread;
159 /* Stop AVC netlink thread. */
161 avc_stop_thread (void *thread)
163 pthread_cancel (*(pthread_t *) thread);
166 /* Allocate a new AVC lock. */
168 avc_alloc_lock (void)
170 pthread_mutex_t *avc_mutex;
172 avc_mutex = dbus_new (pthread_mutex_t, 1);
173 if (avc_mutex == NULL)
175 _dbus_warn ("Could not create mutex: %s\n", _dbus_strerror (errno));
178 pthread_mutex_init (avc_mutex, NULL);
183 /* Acquire an AVC lock. */
185 avc_get_lock (void *lock)
187 pthread_mutex_lock (lock);
190 /* Release an AVC lock. */
192 avc_release_lock (void *lock)
194 pthread_mutex_unlock (lock);
197 /* Free an AVC lock. */
199 avc_free_lock (void *lock)
201 pthread_mutex_destroy (lock);
204 #endif /* HAVE_SELINUX */
207 * Return whether or not SELinux is enabled; must be
208 * called after bus_selinux_init.
211 bus_selinux_enabled (void)
214 return selinux_enabled;
217 #endif /* HAVE_SELINUX */
221 * Do early initialization; determine whether SELinux is enabled.
224 bus_selinux_pre_init (void)
228 _dbus_assert (bus_sid == SECSID_WILD);
230 /* Determine if we are running an SELinux kernel. */
231 r = is_selinux_enabled ();
234 _dbus_warn ("Could not tell if SELinux is enabled: %s\n",
235 _dbus_strerror (errno));
239 selinux_enabled = r != 0;
247 * Initialize the user space access vector cache (AVC) for D-BUS and set up
251 bus_selinux_full_init (void)
256 _dbus_assert (bus_sid == SECSID_WILD);
258 if (!selinux_enabled)
260 _dbus_verbose ("SELinux not enabled in this kernel.\n");
264 _dbus_verbose ("SELinux is enabled in this kernel.\n");
266 avc_entry_ref_init (&aeref);
267 if (avc_init ("avc", &mem_cb, &log_cb, &thread_cb, &lock_cb) < 0)
269 _dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
274 openlog ("dbus", LOG_PERROR, LOG_USER);
275 _dbus_verbose ("Access Vector Cache (AVC) started.\n");
278 if (avc_add_callback (policy_reload_callback, AVC_CALLBACK_RESET,
279 NULL, NULL, 0, 0) < 0)
281 _dbus_warn ("Failed to add policy reload callback: %s\n",
282 _dbus_strerror (errno));
288 bus_sid = SECSID_WILD;
290 if (getcon (&bus_context) < 0)
292 _dbus_verbose ("Error getting context of bus: %s\n",
293 _dbus_strerror (errno));
297 if (avc_context_to_sid (bus_context, &bus_sid) < 0)
299 _dbus_verbose ("Error getting SID from bus context: %s\n",
300 _dbus_strerror (errno));
301 freecon (bus_context);
305 freecon (bus_context);
310 #endif /* HAVE_SELINUX */
314 * Decrement SID reference count.
316 * @param sid the SID to decrement
319 bus_selinux_id_unref (BusSELinuxID *sid)
322 if (!selinux_enabled)
325 _dbus_assert (sid != NULL);
327 sidput (SELINUX_SID_FROM_BUS (sid));
328 #endif /* HAVE_SELINUX */
332 bus_selinux_id_ref (BusSELinuxID *sid)
335 if (!selinux_enabled)
338 _dbus_assert (sid != NULL);
340 sidget (SELINUX_SID_FROM_BUS (sid));
341 #endif /* HAVE_SELINUX */
345 * Determine if the SELinux security policy allows the given sender
346 * security context to go to the given recipient security context.
347 * This function determines if the requested permissions are to be
348 * granted from the connection to the message bus or to another
349 * optionally supplied security identifier (e.g. for a service
350 * context). Currently these permissions are either send_msg or
351 * acquire_svc in the dbus class.
353 * @param sender_sid source security context
354 * @param override_sid is the target security context. If SECSID_WILD this will
355 * use the context of the bus itself (e.g. the default).
356 * @param target_class is the target security class.
357 * @param requested is the requested permissions.
358 * @returns #TRUE if security policy allows the send.
362 bus_selinux_check (BusSELinuxID *sender_sid,
363 BusSELinuxID *override_sid,
364 security_class_t target_class,
365 access_vector_t requested,
370 if (!selinux_enabled)
375 if (spid && _dbus_string_append (auxdata, " spid="))
376 _dbus_string_append_uint (auxdata, spid);
377 if (tpid && _dbus_string_append (auxdata, " tpid="))
378 _dbus_string_append_uint (auxdata, tpid);
381 /* Make the security check. AVC checks enforcing mode here as well. */
382 if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
384 SELINUX_SID_FROM_BUS (override_sid) :
385 SELINUX_SID_FROM_BUS (bus_sid),
386 target_class, requested, &aeref, auxdata) < 0)
388 _dbus_verbose ("SELinux denying due to security policy.\n");
394 #endif /* HAVE_SELINUX */
397 * Returns true if the given connection can acquire a service,
398 * assuming the given security ID is needed for that service.
400 * @param connection connection that wants to own the service
401 * @param service_sid the SID of the service from the table
402 * @returns #TRUE if acquire is permitted.
405 bus_selinux_allows_acquire_service (DBusConnection *connection,
406 BusSELinuxID *service_sid,
407 const char *service_name)
410 BusSELinuxID *connection_sid;
414 if (!selinux_enabled)
417 connection_sid = bus_connection_get_selinux_id (connection);
418 if (!dbus_connection_get_unix_process_id (connection, &spid))
421 auxdata = dbus_new0 (DBusString, 1);
424 if (!_dbus_string_init (auxdata))
429 else if (_dbus_string_append (auxdata, "service="))
430 _dbus_string_append (auxdata, service_name);
433 return bus_selinux_check (connection_sid,
442 #endif /* HAVE_SELINUX */
446 * Check if SELinux security controls allow the message to be sent to a
447 * particular connection based on the security context of the sender and
448 * that of the receiver. The destination connection need not be the
449 * addressed recipient, it could be an "eavesdropper"
451 * @param sender the sender of the message.
452 * @param proposed_recipient the connection the message is to be sent to.
453 * @returns whether to allow the send
456 bus_selinux_allows_send (DBusConnection *sender,
457 DBusConnection *proposed_recipient,
459 const char *interface,
461 const char *error_name,
462 const char *destination)
465 BusSELinuxID *recipient_sid;
466 BusSELinuxID *sender_sid;
467 unsigned long spid, tpid;
470 if (!selinux_enabled)
473 if (!dbus_connection_get_unix_process_id (sender, &spid))
475 if (!dbus_connection_get_unix_process_id (proposed_recipient, &tpid))
478 auxdata = dbus_new0 (DBusString, 1);
481 if (!_dbus_string_init (auxdata))
488 if (_dbus_string_append (auxdata, "msgtype="))
489 _dbus_string_append (auxdata, msgtype);
490 if (interface && _dbus_string_append (auxdata, " interface="))
491 _dbus_string_append (auxdata, interface);
492 if (member && _dbus_string_append (auxdata, " member="))
493 _dbus_string_append (auxdata, member);
494 if (error_name && _dbus_string_append (auxdata, " error_name="))
495 _dbus_string_append (auxdata, error_name);
496 if (destination && _dbus_string_append (auxdata, " dest="))
497 _dbus_string_append (auxdata, destination);
501 sender_sid = bus_connection_get_selinux_id (sender);
502 /* A NULL proposed_recipient means the bus itself. */
503 if (proposed_recipient)
504 recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
506 recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);
508 return bus_selinux_check (sender_sid, recipient_sid,
509 SECCLASS_DBUS, DBUS__SEND_MSG,
510 spid, tpid, auxdata);
513 #endif /* HAVE_SELINUX */
517 * Gets the security context of a connection to the bus. It is up to
518 * the caller to freecon() when they are done.
520 * @param connection the connection to get the context of.
521 * @param con the location to store the security context.
522 * @returns #TRUE if context is successfully obtained.
526 bus_connection_read_selinux_context (DBusConnection *connection,
531 if (!selinux_enabled)
534 _dbus_assert (connection != NULL);
536 if (!dbus_connection_get_unix_fd (connection, &fd))
538 _dbus_verbose ("Failed to get file descriptor of socket.\n");
542 if (getpeercon (fd, con) < 0)
544 _dbus_verbose ("Error getting context of socket peer: %s\n",
545 _dbus_strerror (errno));
549 _dbus_verbose ("Successfully read connection context.\n");
552 #endif /* HAVE_SELINUX */
555 * Read the SELinux ID from the connection.
557 * @param connection the connection to read from
558 * @returns the SID if successfully determined, #NULL otherwise.
561 bus_selinux_init_connection_id (DBusConnection *connection,
568 if (!selinux_enabled)
571 if (!bus_connection_read_selinux_context (connection, &con))
573 dbus_set_error (error, DBUS_ERROR_FAILED,
574 "Failed to read an SELinux context from connection");
575 _dbus_verbose ("Error getting peer context.\n");
579 _dbus_verbose ("Converting context to SID to store on connection\n");
581 if (avc_context_to_sid (con, &sid) < 0)
586 dbus_set_error (error, DBUS_ERROR_FAILED,
587 "Error getting SID from context \"%s\": %s\n",
588 con, _dbus_strerror (errno));
590 _dbus_warn ("Error getting SID from context \"%s\": %s\n",
591 con, _dbus_strerror (errno));
598 return BUS_SID_FROM_SELINUX (sid);
601 #endif /* HAVE_SELINUX */
606 * Function for freeing hash table data. These SIDs
607 * should no longer be referenced.
610 bus_selinux_id_table_free_value (BusSELinuxID *sid)
613 /* NULL sometimes due to how DBusHashTable works */
615 bus_selinux_id_unref (sid);
616 #endif /* HAVE_SELINUX */
620 * Creates a new table mapping service names to security ID.
621 * A security ID is a "compiled" security context, a security
622 * context is just a string.
624 * @returns the new table or #NULL if no memory
627 bus_selinux_id_table_new (void)
629 return _dbus_hash_table_new (DBUS_HASH_STRING,
630 (DBusFreeFunction) dbus_free,
631 (DBusFreeFunction) bus_selinux_id_table_free_value);
635 * Hashes a service name and service context into the service SID
636 * table as a string and a SID.
638 * @param service_name is the name of the service.
639 * @param service_context is the context of the service.
640 * @param service_table is the table to hash them into.
641 * @return #FALSE if not enough memory
644 bus_selinux_id_table_insert (DBusHashTable *service_table,
645 const char *service_name,
646 const char *service_context)
653 if (!selinux_enabled)
659 key = _dbus_strdup (service_name);
663 if (avc_context_to_sid ((char *) service_context, &sid) < 0)
667 _dbus_warn ("Error getting SID from context \"%s\": %s\n",
668 (char *) service_context,
669 _dbus_strerror (errno));
673 if (!_dbus_hash_table_insert_string (service_table,
675 BUS_SID_FROM_SELINUX (sid)))
678 _dbus_verbose ("Parsed \tservice: %s \n\t\tcontext: %s\n",
682 /* These are owned by the hash, so clear them to avoid unref */
689 if (sid != SECSID_WILD)
698 #endif /* HAVE_SELINUX */
703 * Find the security identifier associated with a particular service
704 * name. Return a pointer to this SID, or #NULL/SECSID_WILD if the
705 * service is not found in the hash table. This should be nearly a
706 * constant time operation. If SELinux support is not available,
707 * always return NULL.
709 * @param service_table the hash table to check for service name.
710 * @param service_name the name of the service to look for.
711 * @returns the SELinux ID associated with the service
714 bus_selinux_id_table_lookup (DBusHashTable *service_table,
715 const DBusString *service_name)
720 sid = SECSID_WILD; /* default context */
722 if (!selinux_enabled)
725 _dbus_verbose ("Looking up service SID for %s\n",
726 _dbus_string_get_const_data (service_name));
728 sid = _dbus_hash_table_lookup_string (service_table,
729 _dbus_string_get_const_data (service_name));
731 if (sid == SECSID_WILD)
732 _dbus_verbose ("Service %s not found\n",
733 _dbus_string_get_const_data (service_name));
735 _dbus_verbose ("Service %s found\n",
736 _dbus_string_get_const_data (service_name));
738 return BUS_SID_FROM_SELINUX (sid);
739 #endif /* HAVE_SELINUX */
744 * Get the SELinux policy root. This is used to find the D-BUS
745 * specific config file within the policy.
748 bus_selinux_get_policy_root (void)
751 return selinux_policy_root ();
754 #endif /* HAVE_SELINUX */
758 * For debugging: Print out the current hash table of service SIDs.
761 bus_selinux_id_table_print (DBusHashTable *service_table)
763 #ifdef DBUS_ENABLE_VERBOSE_MODE
767 if (!selinux_enabled)
770 _dbus_verbose ("Service SID Table:\n");
771 _dbus_hash_iter_init (service_table, &iter);
772 while (_dbus_hash_iter_next (&iter))
774 const char *key = _dbus_hash_iter_get_string_key (&iter);
775 security_id_t sid = _dbus_hash_iter_get_value (&iter);
776 _dbus_verbose ("The key is %s\n", key);
777 _dbus_verbose ("The context is %s\n", sid->ctx);
778 _dbus_verbose ("The refcount is %d\n", sid->refcnt);
780 #endif /* HAVE_SELINUX */
781 #endif /* DBUS_ENABLE_VERBOSE_MODE */
785 #ifdef DBUS_ENABLE_VERBOSE_MODE
788 * Print out some AVC statistics.
791 bus_avc_print_stats (void)
793 struct avc_cache_stats cstats;
795 if (!selinux_enabled)
798 _dbus_verbose ("AVC Statistics:\n");
799 avc_cache_stats (&cstats);
801 _dbus_verbose ("AVC Cache Statistics:\n");
802 _dbus_verbose ("Entry lookups: %d\n", cstats.entry_lookups);
803 _dbus_verbose ("Entry hits: %d\n", cstats.entry_hits);
804 _dbus_verbose ("Entry misses %d\n", cstats.entry_misses);
805 _dbus_verbose ("Entry discards: %d\n", cstats.entry_discards);
806 _dbus_verbose ("CAV lookups: %d\n", cstats.cav_lookups);
807 _dbus_verbose ("CAV hits: %d\n", cstats.cav_hits);
808 _dbus_verbose ("CAV probes: %d\n", cstats.cav_probes);
809 _dbus_verbose ("CAV misses: %d\n", cstats.cav_misses);
811 #endif /* HAVE_SELINUX */
812 #endif /* DBUS_ENABLE_VERBOSE_MODE */
816 * Destroy the AVC before we terminate.
819 bus_selinux_shutdown (void)
822 if (!selinux_enabled)
826 bus_sid = SECSID_WILD;
828 #ifdef DBUS_ENABLE_VERBOSE_MODE
829 bus_avc_print_stats ();
830 #endif /* DBUS_ENABLE_VERBOSE_MODE */
833 #endif /* HAVE_SELINUX */