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 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. */ 64static dbus_bool_t selinux_enabled = FALSE; 65 66/* Store an avc_entry_ref to speed AVC decisions. */ 67static struct avc_entry_ref aeref; 68 69/* Store the SID of the bus itself to use as the default. */ 70static security_id_t bus_sid = SECSID_WILD; 71 72/* Thread to listen for SELinux status changes via netlink. */ 73static pthread_t avc_notify_thread; 74 75/* Prototypes for AVC callback functions. */ 76static void log_callback (const char *fmt, ...); 77static void log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft); 78static void *avc_create_thread (void (*run) (void)); 79static void avc_stop_thread (void *thread); 80static void *avc_alloc_lock (void); 81static void avc_get_lock (void *lock); 82static void avc_release_lock (void *lock); 83static void avc_free_lock (void *lock); 84 85/* AVC callback structures for use in avc_init. */ 86static const struct avc_memory_callback mem_cb = 87{ 88 .func_malloc = dbus_malloc, 89 .func_free = dbus_free 90}; 91static const struct avc_log_callback log_cb = 92{ 93 .func_log = log_callback, 94 .func_audit = log_audit_callback 95}; 96static const struct avc_thread_callback thread_cb = 97{ 98 .func_create_thread = avc_create_thread, 99 .func_stop_thread = avc_stop_thread 100}; 101static 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 121static int audit_fd = -1; 122#endif 123 124void 125bus_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 143static void 144log_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_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 */ 175static int 176policy_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 */ 189static void 190log_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 */ 216static void * 217avc_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. */ 231static void 232avc_stop_thread (void *thread) 233{ 234 pthread_cancel (*(pthread_t *) thread); 235} 236 237/* Allocate a new AVC lock. */ 238static void * 239avc_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. */ 255static void 256avc_get_lock (void *lock) 257{ 258 pthread_mutex_lock (lock); 259} 260 261/* Release an AVC lock. */ 262static void 263avc_release_lock (void *lock) 264{ 265 pthread_mutex_unlock (lock); 266} 267 268/* Free an AVC lock. */ 269static void 270avc_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 */ 281dbus_bool_t 282bus_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 */ 294dbus_bool_t 295bus_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 */ 321dbus_bool_t 322bus_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 openlog ("dbus", LOG_PERROR, LOG_USER); 346 _dbus_verbose ("Access Vector Cache (AVC) started.\n"); 347 } 348 349 if (avc_add_callback (policy_reload_callback, AVC_CALLBACK_RESET, 350 NULL, NULL, 0, 0) < 0) 351 { 352 _dbus_warn ("Failed to add policy reload callback: %s\n", 353 _dbus_strerror (errno)); 354 avc_destroy (); 355 return FALSE; 356 } 357 358 bus_context = NULL; 359 bus_sid = SECSID_WILD; 360 361 if (getcon (&bus_context) < 0) 362 { 363 _dbus_verbose ("Error getting context of bus: %s\n", 364 _dbus_strerror (errno)); 365 return FALSE; 366 } 367 368 if (avc_context_to_sid (bus_context, &bus_sid) < 0) 369 { 370 _dbus_verbose ("Error getting SID from bus context: %s\n", 371 _dbus_strerror (errno)); 372 freecon (bus_context); 373 return FALSE; 374 } 375 376 freecon (bus_context); 377 378#endif /* HAVE_SELINUX */ 379 return TRUE; 380} 381 382/** 383 * Decrement SID reference count. 384 * 385 * @param sid the SID to decrement 386 */ 387void 388bus_selinux_id_unref (BusSELinuxID *sid) 389{ 390#ifdef HAVE_SELINUX 391 if (!selinux_enabled) 392 return; 393 394 _dbus_assert (sid != NULL); 395 396 sidput (SELINUX_SID_FROM_BUS (sid)); 397#endif /* HAVE_SELINUX */ 398} 399 400void 401bus_selinux_id_ref (BusSELinuxID *sid) 402{ 403#ifdef HAVE_SELINUX 404 if (!selinux_enabled) 405 return; 406 407 _dbus_assert (sid != NULL); 408 409 sidget (SELINUX_SID_FROM_BUS (sid)); 410#endif /* HAVE_SELINUX */ 411} 412 413/** 414 * Determine if the SELinux security policy allows the given sender 415 * security context to go to the given recipient security context. 416 * This function determines if the requested permissions are to be 417 * granted from the connection to the message bus or to another 418 * optionally supplied security identifier (e.g. for a service 419 * context). Currently these permissions are either send_msg or 420 * acquire_svc in the dbus class. 421 * 422 * @param sender_sid source security context 423 * @param override_sid is the target security context. If SECSID_WILD this will 424 * use the context of the bus itself (e.g. the default). 425 * @param target_class is the target security class. 426 * @param requested is the requested permissions. 427 * @returns #TRUE if security policy allows the send. 428 */ 429#ifdef HAVE_SELINUX 430static dbus_bool_t 431bus_selinux_check (BusSELinuxID *sender_sid, 432 BusSELinuxID *override_sid, 433 security_class_t target_class, 434 access_vector_t requested, 435 DBusString *auxdata) 436{ 437 if (!selinux_enabled) 438 return TRUE; 439 440 /* Make the security check. AVC checks enforcing mode here as well. */ 441 if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid), 442 override_sid ? 443 SELINUX_SID_FROM_BUS (override_sid) : 444 SELINUX_SID_FROM_BUS (bus_sid), 445 target_class, requested, &aeref, auxdata) < 0) 446 { 447 switch (errno) 448 { 449 case EACCES: 450 _dbus_verbose ("SELinux denying due to security policy.\n"); 451 return FALSE; 452 case EINVAL: 453 _dbus_verbose ("SELinux denying due to invalid security context.\n"); 454 return FALSE; 455 default: 456 _dbus_verbose ("SELinux denying due to: %s\n", _dbus_strerror (errno)); 457 return FALSE; 458 } 459 } 460 else 461 return TRUE; 462} 463#endif /* HAVE_SELINUX */ 464 465/** 466 * Returns true if the given connection can acquire a service, 467 * assuming the given security ID is needed for that service. 468 * 469 * @param connection connection that wants to own the service 470 * @param service_sid the SID of the service from the table 471 * @returns #TRUE if acquire is permitted. 472 */ 473dbus_bool_t 474bus_selinux_allows_acquire_service (DBusConnection *connection, 475 BusSELinuxID *service_sid, 476 const char *service_name, 477 DBusError *error) 478{ 479#ifdef HAVE_SELINUX 480 BusSELinuxID *connection_sid; 481 unsigned long spid; 482 DBusString auxdata; 483 dbus_bool_t ret; 484 485 if (!selinux_enabled) 486 return TRUE; 487 488 connection_sid = bus_connection_get_selinux_id (connection); 489 if (!dbus_connection_get_unix_process_id (connection, &spid)) 490 spid = 0; 491 492 if (!_dbus_string_init (&auxdata)) 493 goto oom; 494 495 if (!_dbus_string_append (&auxdata, "service=")) 496 goto oom; 497 498 if (!_dbus_string_append (&auxdata, service_name)) 499 goto oom; 500 501 if (spid) 502 { 503 if (!_dbus_string_append (&auxdata, " spid=")) 504 goto oom; 505 506 if (!_dbus_string_append_uint (&auxdata, spid)) 507 goto oom; 508 } 509 510 ret = bus_selinux_check (connection_sid, 511 service_sid, 512 SECCLASS_DBUS, 513 DBUS__ACQUIRE_SVC, 514 &auxdata); 515 516 _dbus_string_free (&auxdata); 517 return ret; 518 519 oom: 520 _dbus_string_free (&auxdata); 521 BUS_SET_OOM (error); 522 return FALSE; 523 524#else 525 return TRUE; 526#endif /* HAVE_SELINUX */ 527} 528 529/** 530 * Check if SELinux security controls allow the message to be sent to a 531 * particular connection based on the security context of the sender and 532 * that of the receiver. The destination connection need not be the 533 * addressed recipient, it could be an "eavesdropper" 534 * 535 * @param sender the sender of the message. 536 * @param proposed_recipient the connection the message is to be sent to. 537 * @returns whether to allow the send 538 */ 539dbus_bool_t 540bus_selinux_allows_send (DBusConnection *sender, 541 DBusConnection *proposed_recipient, 542 const char *msgtype, 543 const char *interface, 544 const char *member, 545 const char *error_name, 546 const char *destination, 547 DBusError *error) 548{ 549#ifdef HAVE_SELINUX 550 BusSELinuxID *recipient_sid; 551 BusSELinuxID *sender_sid; 552 unsigned long spid, tpid; 553 DBusString auxdata; 554 dbus_bool_t ret; 555 dbus_bool_t string_alloced; 556 557 if (!selinux_enabled) 558 return TRUE; 559 560 if (!sender || !dbus_connection_get_unix_process_id (sender, &spid)) 561 spid = 0; 562 if (!proposed_recipient || !dbus_connection_get_unix_process_id (proposed_recipient, &tpid)) 563 tpid = 0; 564 565 string_alloced = FALSE; 566 if (!_dbus_string_init (&auxdata)) 567 goto oom; 568 string_alloced = TRUE; 569 570 if (!_dbus_string_append (&auxdata, "msgtype=")) 571 goto oom; 572 573 if (!_dbus_string_append (&auxdata, msgtype)) 574 goto oom; 575 576 if (interface) 577 { 578 if (!_dbus_string_append (&auxdata, " interface=")) 579 goto oom; 580 if (!_dbus_string_append (&auxdata, interface)) 581 goto oom; 582 } 583 584 if (member) 585 { 586 if (!_dbus_string_append (&auxdata, " member=")) 587 goto oom; 588 if (!_dbus_string_append (&auxdata, member)) 589 goto oom; 590 } 591 592 if (error_name) 593 { 594 if (!_dbus_string_append (&auxdata, " error_name=")) 595 goto oom; 596 if (!_dbus_string_append (&auxdata, error_name)) 597 goto oom; 598 } 599 600 if (destination) 601 { 602 if (!_dbus_string_append (&auxdata, " dest=")) 603 goto oom; 604 if (!_dbus_string_append (&auxdata, destination)) 605 goto oom; 606 } 607 608 if (spid) 609 { 610 if (!_dbus_string_append (&auxdata, " spid=")) 611 goto oom; 612 613 if (!_dbus_string_append_uint (&auxdata, spid)) 614 goto oom; 615 } 616 617 if (tpid) 618 { 619 if (!_dbus_string_append (&auxdata, " tpid=")) 620 goto oom; 621 622 if (!_dbus_string_append_uint (&auxdata, tpid)) 623 goto oom; 624 } 625 626 sender_sid = bus_connection_get_selinux_id (sender); 627 /* A NULL proposed_recipient means the bus itself. */ 628 if (proposed_recipient) 629 recipient_sid = bus_connection_get_selinux_id (proposed_recipient); 630 else 631 recipient_sid = BUS_SID_FROM_SELINUX (bus_sid); 632 633 ret = bus_selinux_check (sender_sid, 634 recipient_sid, 635 SECCLASS_DBUS, 636 DBUS__SEND_MSG, 637 &auxdata); 638 639 _dbus_string_free (&auxdata); 640 641 return ret; 642 643 oom: 644 if (string_alloced) 645 _dbus_string_free (&auxdata); 646 BUS_SET_OOM (error); 647 return FALSE; 648 649#else 650 return TRUE; 651#endif /* HAVE_SELINUX */ 652} 653 654dbus_bool_t 655bus_selinux_append_context (DBusMessage *message, 656 BusSELinuxID *sid, 657 DBusError *error) 658{ 659#ifdef HAVE_SELINUX 660 char *context; 661 662 if (avc_sid_to_context (SELINUX_SID_FROM_BUS (sid), &context) < 0) 663 { 664 if (errno == ENOMEM) 665 BUS_SET_OOM (error); 666 else 667 dbus_set_error (error, DBUS_ERROR_FAILED, 668 "Error getting context from SID: %s\n", 669 _dbus_strerror (errno)); 670 return FALSE; 671 } 672 if (!dbus_message_append_args (message, 673 DBUS_TYPE_ARRAY, 674 DBUS_TYPE_BYTE, 675 &context, 676 strlen (context), 677 DBUS_TYPE_INVALID)) 678 { 679 _DBUS_SET_OOM (error); 680 return FALSE; 681 } 682 freecon (context); 683 return TRUE; 684#else 685 return TRUE; 686#endif 687} 688 689/** 690 * Gets the security context of a connection to the bus. It is up to 691 * the caller to freecon() when they are done. 692 * 693 * @param connection the connection to get the context of. 694 * @param con the location to store the security context. 695 * @returns #TRUE if context is successfully obtained. 696 */ 697#ifdef HAVE_SELINUX 698static dbus_bool_t 699bus_connection_read_selinux_context (DBusConnection *connection, 700 char **con) 701{ 702 int fd; 703 704 if (!selinux_enabled) 705 return FALSE; 706 707 _dbus_assert (connection != NULL); 708 709 if (!dbus_connection_get_unix_fd (connection, &fd)) 710 { 711 _dbus_verbose ("Failed to get file descriptor of socket.\n"); 712 return FALSE; 713 } 714 715 if (getpeercon (fd, con) < 0) 716 { 717 _dbus_verbose ("Error getting context of socket peer: %s\n", 718 _dbus_strerror (errno)); 719 return FALSE; 720 } 721 722 _dbus_verbose ("Successfully read connection context.\n"); 723 return TRUE; 724} 725#endif /* HAVE_SELINUX */ 726 727/** 728 * Read the SELinux ID from the connection. 729 * 730 * @param connection the connection to read from 731 * @returns the SID if successfully determined, #NULL otherwise. 732 */ 733BusSELinuxID* 734bus_selinux_init_connection_id (DBusConnection *connection, 735 DBusError *error) 736{ 737#ifdef HAVE_SELINUX 738 char *con; 739 security_id_t sid; 740 741 if (!selinux_enabled) 742 return NULL; 743 744 if (!bus_connection_read_selinux_context (connection, &con)) 745 { 746 dbus_set_error (error, DBUS_ERROR_FAILED, 747 "Failed to read an SELinux context from connection"); 748 _dbus_verbose ("Error getting peer context.\n"); 749 return NULL; 750 } 751 752 _dbus_verbose ("Converting context to SID to store on connection\n"); 753 754 if (avc_context_to_sid (con, &sid) < 0) 755 { 756 if (errno == ENOMEM) 757 BUS_SET_OOM (error); 758 else 759 dbus_set_error (error, DBUS_ERROR_FAILED, 760 "Error getting SID from context \"%s\": %s\n", 761 con, _dbus_strerror (errno)); 762 763 _dbus_warn ("Error getting SID from context \"%s\": %s\n", 764 con, _dbus_strerror (errno)); 765 766 freecon (con); 767 return NULL; 768 } 769 770 freecon (con); 771 return BUS_SID_FROM_SELINUX (sid); 772#else 773 return NULL; 774#endif /* HAVE_SELINUX */ 775} 776 777 778/** 779 * Function for freeing hash table data. These SIDs 780 * should no longer be referenced. 781 */ 782static void 783bus_selinux_id_table_free_value (BusSELinuxID *sid) 784{ 785#ifdef HAVE_SELINUX 786 /* NULL sometimes due to how DBusHashTable works */ 787 if (sid) 788 bus_selinux_id_unref (sid); 789#endif /* HAVE_SELINUX */ 790} 791 792/** 793 * Creates a new table mapping service names to security ID. 794 * A security ID is a "compiled" security context, a security 795 * context is just a string. 796 * 797 * @returns the new table or #NULL if no memory 798 */ 799DBusHashTable* 800bus_selinux_id_table_new (void) 801{ 802 return _dbus_hash_table_new (DBUS_HASH_STRING, 803 (DBusFreeFunction) dbus_free, 804 (DBusFreeFunction) bus_selinux_id_table_free_value); 805} 806 807/** 808 * Hashes a service name and service context into the service SID 809 * table as a string and a SID. 810 * 811 * @param service_name is the name of the service. 812 * @param service_context is the context of the service. 813 * @param service_table is the table to hash them into. 814 * @return #FALSE if not enough memory 815 */ 816dbus_bool_t 817bus_selinux_id_table_insert (DBusHashTable *service_table, 818 const char *service_name, 819 const char *service_context) 820{ 821#ifdef HAVE_SELINUX 822 dbus_bool_t retval; 823 security_id_t sid; 824 char *key; 825 826 if (!selinux_enabled) 827 return TRUE; 828 829 sid = SECSID_WILD; 830 retval = FALSE; 831 832 key = _dbus_strdup (service_name); 833 if (key == NULL) 834 return retval; 835 836 if (avc_context_to_sid ((char *) service_context, &sid) < 0) 837 { 838 if (errno == ENOMEM) 839 { 840 dbus_free (key); 841 return FALSE; 842 } 843 844 _dbus_warn ("Error getting SID from context \"%s\": %s\n", 845 (char *) service_context, 846 _dbus_strerror (errno)); 847 goto out; 848 } 849 850 if (!_dbus_hash_table_insert_string (service_table, 851 key, 852 BUS_SID_FROM_SELINUX (sid))) 853 goto out; 854 855 _dbus_verbose ("Parsed \tservice: %s \n\t\tcontext: %s\n", 856 key, 857 sid->ctx); 858 859 /* These are owned by the hash, so clear them to avoid unref */ 860 key = NULL; 861 sid = SECSID_WILD; 862 863 retval = TRUE; 864 865 out: 866 if (sid != SECSID_WILD) 867 sidput (sid); 868 869 if (key) 870 dbus_free (key); 871 872 return retval; 873#else 874 return TRUE; 875#endif /* HAVE_SELINUX */ 876} 877 878 879/** 880 * Find the security identifier associated with a particular service 881 * name. Return a pointer to this SID, or #NULL/SECSID_WILD if the 882 * service is not found in the hash table. This should be nearly a 883 * constant time operation. If SELinux support is not available, 884 * always return NULL. 885 * 886 * @param service_table the hash table to check for service name. 887 * @param service_name the name of the service to look for. 888 * @returns the SELinux ID associated with the service 889 */ 890BusSELinuxID* 891bus_selinux_id_table_lookup (DBusHashTable *service_table, 892 const DBusString *service_name) 893{ 894#ifdef HAVE_SELINUX 895 security_id_t sid; 896 897 sid = SECSID_WILD; /* default context */ 898 899 if (!selinux_enabled) 900 return NULL; 901 902 _dbus_verbose ("Looking up service SID for %s\n", 903 _dbus_string_get_const_data (service_name)); 904 905 sid = _dbus_hash_table_lookup_string (service_table, 906 _dbus_string_get_const_data (service_name)); 907 908 if (sid == SECSID_WILD) 909 _dbus_verbose ("Service %s not found\n", 910 _dbus_string_get_const_data (service_name)); 911 else 912 _dbus_verbose ("Service %s found\n", 913 _dbus_string_get_const_data (service_name)); 914 915 return BUS_SID_FROM_SELINUX (sid); 916#endif /* HAVE_SELINUX */ 917 return NULL; 918} 919 920/** 921 * Get the SELinux policy root. This is used to find the D-Bus 922 * specific config file within the policy. 923 */ 924const char * 925bus_selinux_get_policy_root (void) 926{ 927#ifdef HAVE_SELINUX 928 return selinux_policy_root (); 929#else 930 return NULL; 931#endif /* HAVE_SELINUX */ 932} 933 934/** 935 * For debugging: Print out the current hash table of service SIDs. 936 */ 937void 938bus_selinux_id_table_print (DBusHashTable *service_table) 939{ 940#ifdef DBUS_ENABLE_VERBOSE_MODE 941#ifdef HAVE_SELINUX 942 DBusHashIter iter; 943 944 if (!selinux_enabled) 945 return; 946 947 _dbus_verbose ("Service SID Table:\n"); 948 _dbus_hash_iter_init (service_table, &iter); 949 while (_dbus_hash_iter_next (&iter)) 950 { 951 const char *key = _dbus_hash_iter_get_string_key (&iter); 952 security_id_t sid = _dbus_hash_iter_get_value (&iter); 953 _dbus_verbose ("The key is %s\n", key); 954 _dbus_verbose ("The context is %s\n", sid->ctx); 955 _dbus_verbose ("The refcount is %d\n", sid->refcnt); 956 } 957#endif /* HAVE_SELINUX */ 958#endif /* DBUS_ENABLE_VERBOSE_MODE */ 959} 960 961 962#ifdef DBUS_ENABLE_VERBOSE_MODE 963#ifdef HAVE_SELINUX 964/** 965 * Print out some AVC statistics. 966 */ 967static void 968bus_avc_print_stats (void) 969{ 970 struct avc_cache_stats cstats; 971 972 if (!selinux_enabled) 973 return; 974 975 _dbus_verbose ("AVC Statistics:\n"); 976 avc_cache_stats (&cstats); 977 avc_av_stats (); 978 _dbus_verbose ("AVC Cache Statistics:\n"); 979 _dbus_verbose ("Entry lookups: %d\n", cstats.entry_lookups); 980 _dbus_verbose ("Entry hits: %d\n", cstats.entry_hits); 981 _dbus_verbose ("Entry misses %d\n", cstats.entry_misses); 982 _dbus_verbose ("Entry discards: %d\n", cstats.entry_discards); 983 _dbus_verbose ("CAV lookups: %d\n", cstats.cav_lookups); 984 _dbus_verbose ("CAV hits: %d\n", cstats.cav_hits); 985 _dbus_verbose ("CAV probes: %d\n", cstats.cav_probes); 986 _dbus_verbose ("CAV misses: %d\n", cstats.cav_misses); 987} 988#endif /* HAVE_SELINUX */ 989#endif /* DBUS_ENABLE_VERBOSE_MODE */ 990 991 992/** 993 * Destroy the AVC before we terminate. 994 */ 995void 996bus_selinux_shutdown (void) 997{ 998#ifdef HAVE_SELINUX 999 if (!selinux_enabled) 1000 return; 1001 1002 _dbus_verbose ("AVC shutdown\n"); 1003 1004 if (bus_sid != SECSID_WILD) 1005 { 1006 sidput (bus_sid); 1007 bus_sid = SECSID_WILD; 1008 1009#ifdef DBUS_ENABLE_VERBOSE_MODE 1010 1011 if (_dbus_is_verbose()) 1012 bus_avc_print_stats (); 1013 1014#endif /* DBUS_ENABLE_VERBOSE_MODE */ 1015 1016 avc_destroy (); 1017#ifdef HAVE_LIBAUDIT 1018 audit_close (audit_fd); 1019#endif /* HAVE_LIBAUDIT */ 1020 } 1021#endif /* HAVE_SELINUX */ 1022} 1023 1024/* The !HAVE_LIBAUDIT case lives in dbus-sysdeps-util-unix.c */ 1025#ifdef HAVE_LIBAUDIT 1026/** 1027 * Changes the user and group the bus is running as. 1028 * 1029 * @param user the user to become 1030 * @param error return location for errors 1031 * @returns #FALSE on failure 1032 */ 1033dbus_bool_t 1034_dbus_change_to_daemon_user (const char *user, 1035 DBusError *error) 1036{ 1037 dbus_uid_t uid; 1038 dbus_gid_t gid; 1039 DBusString u; 1040 1041 _dbus_string_init_const (&u, user); 1042 1043 if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid)) 1044 { 1045 dbus_set_error (error, DBUS_ERROR_FAILED, 1046 "User '%s' does not appear to exist?", 1047 user); 1048 return FALSE; 1049 } 1050 1051 /* If we were root */ 1052 if (_dbus_geteuid () == 0) 1053 { 1054 int rc; 1055 1056 capng_clear (CAPNG_SELECT_BOTH); 1057 capng_update (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, 1058 CAP_AUDIT_WRITE); 1059 rc = capng_change_id (uid, gid, 0); 1060 if (rc) 1061 { 1062 switch (rc) { 1063 default: 1064 dbus_set_error (error, DBUS_ERROR_FAILED, 1065 "Failed to drop capabilities: %s\n", 1066 _dbus_strerror (errno)); 1067 break; 1068 case -4: 1069 dbus_set_error (error, _dbus_error_from_errno (errno), 1070 "Failed to set GID to %lu: %s", gid, 1071 _dbus_strerror (errno)); 1072 break; 1073 case -5: 1074 _dbus_warn ("Failed to drop supplementary groups: %s\n", 1075 _dbus_strerror (errno)); 1076 break; 1077 case -6: 1078 dbus_set_error (error, _dbus_error_from_errno (errno), 1079 "Failed to set UID to %lu: %s", uid, 1080 _dbus_strerror (errno)); 1081 break; 1082 case -7: 1083 dbus_set_error (error, _dbus_error_from_errno (errno), 1084 "Failed to unset keep-capabilities: %s\n", 1085 _dbus_strerror (errno)); 1086 break; 1087 } 1088 return FALSE; 1089 } 1090 } 1091 1092 return TRUE; 1093} 1094#endif 1095