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