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