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