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 (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., 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. */ 64 static dbus_bool_t selinux_enabled = FALSE; 65 66 /* Store an avc_entry_ref to speed AVC decisions. */ 67 static struct avc_entry_ref aeref; 68 69 /* Store the SID of the bus itself to use as the default. */ 70 static security_id_t bus_sid = SECSID_WILD; 71 72 /* Thread to listen for SELinux status changes via netlink. */ 73 static pthread_t avc_notify_thread; 74 75 /* Prototypes for AVC callback functions. */ 76 static void log_callback (const char *fmt, ...); 77 static void log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft); 78 static void *avc_create_thread (void (*run) (void)); 79 static void avc_stop_thread (void *thread); 80 static void *avc_alloc_lock (void); 81 static void avc_get_lock (void *lock); 82 static void avc_release_lock (void *lock); 83 static void avc_free_lock (void *lock); 84 85 /* AVC callback structures for use in avc_init. */ 86 static const struct avc_memory_callback mem_cb = 87 { 88 .func_malloc = dbus_malloc, 89 .func_free = dbus_free 90 }; 91 static const struct avc_log_callback log_cb = 92 { 93 .func_log = log_callback, 94 .func_audit = log_audit_callback 95 }; 96 static const struct avc_thread_callback thread_cb = 97 { 98 .func_create_thread = avc_create_thread, 99 .func_stop_thread = avc_stop_thread 100 }; 101 static 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 121 static int audit_fd = -1; 122 #endif 123 124 void 125 bus_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 143 static void 144 log_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 */ 175 static int 176 policy_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 */ 189 static void 190 log_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 */ 216 static void * 217 avc_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. */ 231 static void 232 avc_stop_thread (void *thread) 233 { 234 pthread_cancel (*(pthread_t *) thread); 235 } 236 237 /* Allocate a new AVC lock. */ 238 static void * 239 avc_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. */ 255 static void 256 avc_get_lock (void *lock) 257 { 258 pthread_mutex_lock (lock); 259 } 260 261 /* Release an AVC lock. */ 262 static void 263 avc_release_lock (void *lock) 264 { 265 pthread_mutex_unlock (lock); 266 } 267 268 /* Free an AVC lock. */ 269 static void 270 avc_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 */ 281 dbus_bool_t 282 bus_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 */ 294 dbus_bool_t 295 bus_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 */ 321 dbus_bool_t 322 bus_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 */ 387 void 388 bus_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 400 void 401 bus_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 430 static dbus_bool_t 431 bus_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 */ 473 dbus_bool_t 474 bus_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 */ 539 dbus_bool_t 540 bus_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 654 dbus_bool_t 655 bus_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 698 static dbus_bool_t 699 bus_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 */ 733 BusSELinuxID* 734 bus_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 */ 782 static void 783 bus_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 */ 799 DBusHashTable* 800 bus_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 */ 816 dbus_bool_t 817 bus_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 */ 890 BusSELinuxID* 891 bus_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 */ 924 const char * 925 bus_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 */ 937 void 938 bus_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 */ 967 static void 968 bus_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 */ 995 void 996 bus_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 */ 1033 dbus_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