Coverage report for bus/selinux.c.gcov
-: 0:Source:selinux.c
-: 0:Graph:selinux.gcno
-: 0:Data:selinux.gcda
-: 0:Runs:10117
-: 0:Programs:2
-: 1:/* -*- mode: C; c-file-style: "gnu" -*-
-: 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., 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, ...)
function log_callback called 1 returned 100% blocks executed 100%
1: 105:{
-: 106: va_list ap;
1: 107: va_start(ap, fmt);
call 0 returned 100%
1: 108: vsyslog (LOG_INFO, fmt, ap);
call 0 returned 100%
1: 109: va_end(ap);
call 0 returned 100%
1: 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)
function policy_reload_callback called 0 returned 0% blocks executed 0%
#####: 120:{
#####: 121: if (event == AVC_CALLBACK_RESET)
branch 0 never executed
branch 1 never executed
#####: 122: return raise (SIGHUP);
call 0 never executed
-: 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)
function log_audit_callback called 0 returned 0% blocks executed 0%
#####: 132:{
#####: 133: DBusString *audmsg = data;
#####: 134: _dbus_string_copy_to_buffer (audmsg, buf, bufleft);
call 0 never executed
#####: 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))
function avc_create_thread called 1 returned 100% blocks executed 50%
1: 146:{
-: 147: int rc;
-: 148:
1: 149: rc = pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
call 0 returned 100%
1: 150: if (rc != 0)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
-: 151: {
#####: 152: _dbus_warn ("Failed to start AVC thread: %s\n", _dbus_strerror (rc));
call 0 never executed
call 1 never executed
#####: 153: exit (1);
call 0 never executed
-: 154: }
1: 155: return &avc_notify_thread;
-: 156:}
-: 157:
-: 158:/* Stop AVC netlink thread. */
-: 159:static void
-: 160:avc_stop_thread (void *thread)
function avc_stop_thread called 1 returned 100% blocks executed 100%
1: 161:{
1: 162: pthread_cancel (*(pthread_t *) thread);
call 0 returned 100%
1: 163:}
-: 164:
-: 165:/* Allocate a new AVC lock. */
-: 166:static void *
-: 167:avc_alloc_lock (void)
function avc_alloc_lock called 2 returned 100% blocks executed 50%
2: 168:{
-: 169: pthread_mutex_t *avc_mutex;
-: 170:
2: 171: avc_mutex = dbus_new (pthread_mutex_t, 1);
call 0 returned 100%
2: 172: if (avc_mutex == NULL)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
-: 173: {
#####: 174: _dbus_warn ("Could not create mutex: %s\n", _dbus_strerror (errno));
call 0 never executed
call 1 never executed
call 2 never executed
#####: 175: exit (1);
call 0 never executed
-: 176: }
2: 177: pthread_mutex_init (avc_mutex, NULL);
call 0 returned 100%
-: 178:
2: 179: return avc_mutex;
-: 180:}
-: 181:
-: 182:/* Acquire an AVC lock. */
-: 183:static void
-: 184:avc_get_lock (void *lock)
function avc_get_lock called 8 returned 100% blocks executed 100%
8: 185:{
8: 186: pthread_mutex_lock (lock);
call 0 returned 100%
8: 187:}
-: 188:
-: 189:/* Release an AVC lock. */
-: 190:static void
-: 191:avc_release_lock (void *lock)
function avc_release_lock called 8 returned 100% blocks executed 100%
8: 192:{
8: 193: pthread_mutex_unlock (lock);
call 0 returned 100%
8: 194:}
-: 195:
-: 196:/* Free an AVC lock. */
-: 197:static void
-: 198:avc_free_lock (void *lock)
function avc_free_lock called 2 returned 100% blocks executed 100%
2: 199:{
2: 200: pthread_mutex_destroy (lock);
call 0 returned 100%
2: 201: dbus_free (lock);
call 0 returned 100%
2: 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)
function bus_selinux_enabled called 2 returned 100% blocks executed 100%
2: 211:{
-: 212:#ifdef HAVE_SELINUX
2: 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)
function bus_selinux_pre_init called 1 returned 100% blocks executed 56%
1: 224:{
-: 225:#ifdef HAVE_SELINUX
-: 226: int r;
1: 227: _dbus_assert (bus_sid == SECSID_WILD);
call 0 returned 100%
-: 228:
-: 229: /* Determine if we are running an SELinux kernel. */
1: 230: r = is_selinux_enabled ();
call 0 returned 100%
1: 231: if (r < 0)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
-: 232: {
#####: 233: _dbus_warn ("Could not tell if SELinux is enabled: %s\n",
call 0 never executed
call 1 never executed
call 2 never executed
-: 234: _dbus_strerror (errno));
#####: 235: return FALSE;
-: 236: }
-: 237:
1: 238: selinux_enabled = r != 0;
1: 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)
function bus_selinux_full_init called 3 returned 100% blocks executed 53%
3: 251:{
-: 252:#ifdef HAVE_SELINUX
-: 253: char *bus_context;
-: 254:
3: 255: _dbus_assert (bus_sid == SECSID_WILD);
call 0 returned 100%
-: 256:
3: 257: if (!selinux_enabled)
branch 0 taken 67% (fallthrough)
branch 1 taken 33%
-: 258: {
2: 259: _dbus_verbose ("SELinux not enabled in this kernel.\n");
call 0 returned 100%
2: 260: return TRUE;
-: 261: }
-: 262:
1: 263: _dbus_verbose ("SELinux is enabled in this kernel.\n");
call 0 returned 100%
-: 264:
1: 265: avc_entry_ref_init (&aeref);
1: 266: if (avc_init ("avc", &mem_cb, &log_cb, &thread_cb, &lock_cb) < 0)
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 267: {
#####: 268: _dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
call 0 never executed
#####: 269: return FALSE;
-: 270: }
-: 271: else
-: 272: {
1: 273: openlog ("dbus", LOG_PERROR, LOG_USER);
call 0 returned 100%
1: 274: _dbus_verbose ("Access Vector Cache (AVC) started.\n");
call 0 returned 100%
-: 275: }
-: 276:
1: 277: if (avc_add_callback (policy_reload_callback, AVC_CALLBACK_RESET,
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 278: NULL, NULL, 0, 0) < 0)
-: 279: {
#####: 280: _dbus_warn ("Failed to add policy reload callback: %s\n",
call 0 never executed
call 1 never executed
call 2 never executed
-: 281: _dbus_strerror (errno));
#####: 282: avc_destroy ();
call 0 never executed
#####: 283: return FALSE;
-: 284: }
-: 285:
1: 286: bus_context = NULL;
1: 287: bus_sid = SECSID_WILD;
-: 288:
1: 289: if (getcon (&bus_context) < 0)
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 290: {
#####: 291: _dbus_verbose ("Error getting context of bus: %s\n",
call 0 never executed
call 1 never executed
call 2 never executed
-: 292: _dbus_strerror (errno));
#####: 293: return FALSE;
-: 294: }
-: 295:
1: 296: if (avc_context_to_sid (bus_context, &bus_sid) < 0)
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 297: {
#####: 298: _dbus_verbose ("Error getting SID from bus context: %s\n",
call 0 never executed
call 1 never executed
call 2 never executed
-: 299: _dbus_strerror (errno));
#####: 300: freecon (bus_context);
call 0 never executed
#####: 301: return FALSE;
-: 302: }
-: 303:
1: 304: freecon (bus_context);
call 0 returned 100%
-: 305:
1: 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)
function bus_selinux_id_unref called 1 returned 100% blocks executed 80%
1: 319:{
-: 320:#ifdef HAVE_SELINUX
1: 321: if (!selinux_enabled)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 322: return;
-: 323:
1: 324: _dbus_assert (sid != NULL);
call 0 returned 100%
-: 325:
1: 326: sidput (SELINUX_SID_FROM_BUS (sid));
call 0 returned 100%
-: 327:#endif /* HAVE_SELINUX */
-: 328:}
-: 329:
-: 330:void
-: 331:bus_selinux_id_ref (BusSELinuxID *sid)
function bus_selinux_id_ref called 0 returned 0% blocks executed 0%
#####: 332:{
-: 333:#ifdef HAVE_SELINUX
#####: 334: if (!selinux_enabled)
branch 0 never executed
branch 1 never executed
#####: 335: return;
-: 336:
#####: 337: _dbus_assert (sid != NULL);
call 0 never executed
-: 338:
#####: 339: sidget (SELINUX_SID_FROM_BUS (sid));
call 0 never executed
-: 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)
function bus_selinux_check called 2 returned 100% blocks executed 64%
2: 366:{
2: 367: if (!selinux_enabled)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 368: return TRUE;
-: 369:
-: 370: /* Make the security check. AVC checks enforcing mode here as well. */
2: 371: if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
call 2 returned 100%
branch 3 taken 0% (fallthrough)
branch 4 taken 100%
-: 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");
call 0 never executed
#####: 378: return FALSE;
-: 379: }
-: 380: else
2: 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)
function bus_selinux_allows_acquire_service called 1950 returned 100% blocks executed 10%
1950: 398:{
-: 399:#ifdef HAVE_SELINUX
-: 400: BusSELinuxID *connection_sid;
-: 401: unsigned long spid;
-: 402: DBusString auxdata;
-: 403: dbus_bool_t ret;
-: 404:
1950: 405: if (!selinux_enabled)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
1950: 406: return TRUE;
-: 407:
#####: 408: connection_sid = bus_connection_get_selinux_id (connection);
call 0 never executed
#####: 409: if (!dbus_connection_get_unix_process_id (connection, &spid))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 410: spid = 0;
-: 411:
#####: 412: if (!_dbus_string_init (&auxdata))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 413: goto oom;
-: 414:
#####: 415: if (!_dbus_string_append (&auxdata, "service="))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 416: goto oom;
-: 417:
#####: 418: if (!_dbus_string_append (&auxdata, service_name))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 419: goto oom;
-: 420:
#####: 421: if (spid)
branch 0 never executed
branch 1 never executed
-: 422: {
#####: 423: if (!_dbus_string_append (&auxdata, " spid="))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 424: goto oom;
-: 425:
#####: 426: if (!_dbus_string_append_uint (&auxdata, spid))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 427: goto oom;
-: 428: }
-: 429:
#####: 430: ret = bus_selinux_check (connection_sid,
call 0 never executed
-: 431: service_sid,
-: 432: SECCLASS_DBUS,
-: 433: DBUS__ACQUIRE_SVC,
-: 434: &auxdata);
-: 435:
#####: 436: _dbus_string_free (&auxdata);
call 0 never executed
#####: 437: return ret;
-: 438:
#####: 439: oom:
#####: 440: _dbus_string_free (&auxdata);
call 0 never executed
#####: 441: BUS_SET_OOM (error);
call 0 never executed
#####: 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)
function bus_selinux_allows_send called 54033 returned 100% blocks executed 57%
54033: 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:
54033: 477: if (!selinux_enabled)
branch 0 taken 99% (fallthrough)
branch 1 taken 1%
54031: 478: return TRUE;
-: 479:
2: 480: if (!sender || !dbus_connection_get_unix_process_id (sender, &spid))
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
call 2 returned 100%
branch 3 taken 0% (fallthrough)
branch 4 taken 100%
#####: 481: spid = 0;
2: 482: if (!proposed_recipient || !dbus_connection_get_unix_process_id (proposed_recipient, &tpid))
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
call 2 never executed
branch 3 never executed
branch 4 never executed
2: 483: tpid = 0;
-: 484:
2: 485: string_alloced = FALSE;
2: 486: if (!_dbus_string_init (&auxdata))
call 0 returned 100%
branch 1 taken 100% (fallthrough)
branch 2 taken 0%
#####: 487: goto oom;
2: 488: string_alloced = TRUE;
-: 489:
2: 490: if (!_dbus_string_append (&auxdata, "msgtype="))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 491: goto oom;
-: 492:
2: 493: if (!_dbus_string_append (&auxdata, msgtype))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 494: goto oom;
-: 495:
2: 496: if (interface)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
-: 497: {
2: 498: if (!_dbus_string_append (&auxdata, " interface="))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 499: goto oom;
2: 500: if (!_dbus_string_append (&auxdata, interface))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 501: goto oom;
-: 502: }
-: 503:
2: 504: if (member)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
-: 505: {
2: 506: if (!_dbus_string_append (&auxdata, " member="))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 507: goto oom;
2: 508: if (!_dbus_string_append (&auxdata, member))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 509: goto oom;
-: 510: }
-: 511:
2: 512: if (error_name)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
-: 513: {
#####: 514: if (!_dbus_string_append (&auxdata, " error_name="))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 515: goto oom;
#####: 516: if (!_dbus_string_append (&auxdata, error_name))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 517: goto oom;
-: 518: }
-: 519:
2: 520: if (destination)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
-: 521: {
2: 522: if (!_dbus_string_append (&auxdata, " dest="))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 523: goto oom;
2: 524: if (!_dbus_string_append (&auxdata, destination))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 525: goto oom;
-: 526: }
-: 527:
2: 528: if (spid)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
-: 529: {
2: 530: if (!_dbus_string_append (&auxdata, " spid="))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 531: goto oom;
-: 532:
2: 533: if (!_dbus_string_append_uint (&auxdata, spid))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 534: goto oom;
-: 535: }
-: 536:
2: 537: if (tpid)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
-: 538: {
#####: 539: if (!_dbus_string_append (&auxdata, " tpid="))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 540: goto oom;
-: 541:
#####: 542: if (!_dbus_string_append_uint (&auxdata, tpid))
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 543: goto oom;
-: 544: }
-: 545:
2: 546: sender_sid = bus_connection_get_selinux_id (sender);
call 0 returned 100%
-: 547: /* A NULL proposed_recipient means the bus itself. */
2: 548: if (proposed_recipient)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 549: recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
call 0 never executed
-: 550: else
2: 551: recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);
-: 552:
2: 553: ret = bus_selinux_check (sender_sid,
call 0 returned 100%
-: 554: recipient_sid,
-: 555: SECCLASS_DBUS,
-: 556: DBUS__SEND_MSG,
-: 557: &auxdata);
-: 558:
2: 559: _dbus_string_free (&auxdata);
call 0 returned 100%
-: 560:
2: 561: return ret;
-: 562:
#####: 563: oom:
#####: 564: if (string_alloced)
branch 0 never executed
branch 1 never executed
#####: 565: _dbus_string_free (&auxdata);
call 0 never executed
#####: 566: BUS_SET_OOM (error);
call 0 never executed
#####: 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)
function bus_selinux_append_context called 0 returned 0% blocks executed 0%
#####: 578:{
-: 579:#ifdef HAVE_SELINUX
-: 580: char *context;
-: 581:
#####: 582: if (avc_sid_to_context (SELINUX_SID_FROM_BUS (sid), &context) < 0)
call 0 never executed
branch 1 never executed
branch 2 never executed
-: 583: {
#####: 584: if (errno == ENOMEM)
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 585: BUS_SET_OOM (error);
call 0 never executed
-: 586: else
#####: 587: dbus_set_error (error, DBUS_ERROR_FAILED,
call 0 never executed
call 1 never executed
call 2 never executed
-: 588: "Error getting context from SID: %s\n",
-: 589: _dbus_strerror (errno));
#####: 590: return FALSE;
-: 591: }
#####: 592: if (!dbus_message_append_args (message,
call 0 never executed
call 1 never executed
branch 2 never executed
branch 3 never executed
-: 593: DBUS_TYPE_ARRAY,
-: 594: DBUS_TYPE_BYTE,
-: 595: &context,
-: 596: strlen (context),
-: 597: DBUS_TYPE_INVALID))
-: 598: {
#####: 599: _DBUS_SET_OOM (error);
call 0 never executed
#####: 600: return FALSE;
-: 601: }
#####: 602: freecon (context);
call 0 never executed
#####: 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)
function bus_connection_read_selinux_context called 1 returned 100% blocks executed 56%
1: 621:{
-: 622: int fd;
-: 623:
1: 624: if (!selinux_enabled)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 625: return FALSE;
-: 626:
1: 627: _dbus_assert (connection != NULL);
call 0 returned 100%
-: 628:
1: 629: if (!dbus_connection_get_unix_fd (connection, &fd))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 630: {
#####: 631: _dbus_verbose ("Failed to get file descriptor of socket.\n");
call 0 never executed
#####: 632: return FALSE;
-: 633: }
-: 634:
1: 635: if (getpeercon (fd, con) < 0)
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 636: {
#####: 637: _dbus_verbose ("Error getting context of socket peer: %s\n",
call 0 never executed
call 1 never executed
call 2 never executed
-: 638: _dbus_strerror (errno));
#####: 639: return FALSE;
-: 640: }
-: 641:
1: 642: _dbus_verbose ("Successfully read connection context.\n");
call 0 returned 100%
1: 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)
function bus_selinux_init_connection_id called 7884 returned 100% blocks executed 42%
7884: 656:{
-: 657:#ifdef HAVE_SELINUX
-: 658: char *con;
-: 659: security_id_t sid;
-: 660:
7884: 661: if (!selinux_enabled)
branch 0 taken 99% (fallthrough)
branch 1 taken 1%
7883: 662: return NULL;
-: 663:
1: 664: if (!bus_connection_read_selinux_context (connection, &con))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 665: {
#####: 666: dbus_set_error (error, DBUS_ERROR_FAILED,
call 0 never executed
-: 667: "Failed to read an SELinux context from connection");
#####: 668: _dbus_verbose ("Error getting peer context.\n");
call 0 never executed
#####: 669: return NULL;
-: 670: }
-: 671:
1: 672: _dbus_verbose ("Converting context to SID to store on connection\n");
call 0 returned 100%
-: 673:
1: 674: if (avc_context_to_sid (con, &sid) < 0)
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 675: {
#####: 676: if (errno == ENOMEM)
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 677: BUS_SET_OOM (error);
call 0 never executed
-: 678: else
#####: 679: dbus_set_error (error, DBUS_ERROR_FAILED,
call 0 never executed
call 1 never executed
call 2 never executed
-: 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",
call 0 never executed
call 1 never executed
call 2 never executed
-: 684: con, _dbus_strerror (errno));
-: 685:
#####: 686: freecon (con);
call 0 never executed
#####: 687: return NULL;
-: 688: }
-: 689:
1: 690: freecon (con);
call 0 returned 100%
1: 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)
function bus_selinux_id_table_free_value called 0 returned 0% blocks executed 0%
#####: 704:{
-: 705:#ifdef HAVE_SELINUX
-: 706: /* NULL sometimes due to how DBusHashTable works */
#####: 707: if (sid)
branch 0 never executed
branch 1 never executed
#####: 708: bus_selinux_id_unref (sid);
call 0 never executed
-: 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)
function bus_selinux_id_table_new called 3 returned 100% blocks executed 100%
3: 721:{
3: 722: return _dbus_hash_table_new (DBUS_HASH_STRING,
call 0 returned 100%
-: 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)
function bus_selinux_id_table_insert called 0 returned 0% blocks executed 0%
#####: 740:{
-: 741:#ifdef HAVE_SELINUX
-: 742: dbus_bool_t retval;
-: 743: security_id_t sid;
-: 744: char *key;
-: 745:
#####: 746: if (!selinux_enabled)
branch 0 never executed
branch 1 never executed
#####: 747: return TRUE;
-: 748:
#####: 749: sid = SECSID_WILD;
#####: 750: retval = FALSE;
-: 751:
#####: 752: key = _dbus_strdup (service_name);
call 0 never executed
#####: 753: if (key == NULL)
branch 0 never executed
branch 1 never executed
#####: 754: return retval;
-: 755:
#####: 756: if (avc_context_to_sid ((char *) service_context, &sid) < 0)
call 0 never executed
branch 1 never executed
branch 2 never executed
-: 757: {
#####: 758: if (errno == ENOMEM)
call 0 never executed
branch 1 never executed
branch 2 never executed
#####: 759: return FALSE;
#####: 760: _dbus_warn ("Error getting SID from context \"%s\": %s\n",
call 0 never executed
call 1 never executed
call 2 never executed
-: 761: (char *) service_context,
-: 762: _dbus_strerror (errno));
#####: 763: goto out;
-: 764: }
-: 765:
#####: 766: if (!_dbus_hash_table_insert_string (service_table,
call 0 never executed
branch 1 never executed
branch 2 never executed
-: 767: key,
-: 768: BUS_SID_FROM_SELINUX (sid)))
#####: 769: goto out;
-: 770:
#####: 771: _dbus_verbose ("Parsed \tservice: %s \n\t\tcontext: %s\n",
call 0 never executed
-: 772: key,
-: 773: sid->ctx);
-: 774:
-: 775: /* These are owned by the hash, so clear them to avoid unref */
#####: 776: key = NULL;
#####: 777: sid = SECSID_WILD;
-: 778:
#####: 779: retval = TRUE;
-: 780:
#####: 781: out:
#####: 782: if (sid != SECSID_WILD)
branch 0 never executed
branch 1 never executed
#####: 783: sidput (sid);
call 0 never executed
-: 784:
#####: 785: if (key)
branch 0 never executed
branch 1 never executed
#####: 786: dbus_free (key);
call 0 never executed
-: 787:
#####: 788: return retval;
-: 789:#else
-: 790: return TRUE;
-: 791:#endif /* HAVE_SELINUX */
-: 792:}
-: 793:
-: 794:
-: 795:/**
-: 796: * Find the security identifier associated with a particular service
-: 797: * name. Return a pointer to this SID, or #NULL/SECSID_WILD if the
-: 798: * service is not found in the hash table. This should be nearly a
-: 799: * constant time operation. If SELinux support is not available,
-: 800: * always return NULL.
-: 801: *
-: 802: * @param service_table the hash table to check for service name.
-: 803: * @param service_name the name of the service to look for.
-: 804: * @returns the SELinux ID associated with the service
-: 805: */
-: 806:BusSELinuxID*
-: 807:bus_selinux_id_table_lookup (DBusHashTable *service_table,
-: 808: const DBusString *service_name)
function bus_selinux_id_table_lookup called 1950 returned 100% blocks executed 23%
1950: 809:{
-: 810:#ifdef HAVE_SELINUX
-: 811: security_id_t sid;
-: 812:
1950: 813: sid = SECSID_WILD; /* default context */
-: 814:
1950: 815: if (!selinux_enabled)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
1950: 816: return NULL;
-: 817:
#####: 818: _dbus_verbose ("Looking up service SID for %s\n",
call 0 never executed
call 1 never executed
-: 819: _dbus_string_get_const_data (service_name));
-: 820:
#####: 821: sid = _dbus_hash_table_lookup_string (service_table,
call 0 never executed
call 1 never executed
-: 822: _dbus_string_get_const_data (service_name));
-: 823:
#####: 824: if (sid == SECSID_WILD)
branch 0 never executed
branch 1 never executed
#####: 825: _dbus_verbose ("Service %s not found\n",
call 0 never executed
call 1 never executed
-: 826: _dbus_string_get_const_data (service_name));
-: 827: else
#####: 828: _dbus_verbose ("Service %s found\n",
call 0 never executed
call 1 never executed
-: 829: _dbus_string_get_const_data (service_name));
-: 830:
#####: 831: return BUS_SID_FROM_SELINUX (sid);
-: 832:#endif /* HAVE_SELINUX */
-: 833: return NULL;
-: 834:}
-: 835:
-: 836:/**
-: 837: * Get the SELinux policy root. This is used to find the D-BUS
-: 838: * specific config file within the policy.
-: 839: */
-: 840:const char *
-: 841:bus_selinux_get_policy_root (void)
function bus_selinux_get_policy_root called 0 returned 0% blocks executed 0%
#####: 842:{
-: 843:#ifdef HAVE_SELINUX
#####: 844: return selinux_policy_root ();
call 0 never executed
-: 845:#else
-: 846: return NULL;
-: 847:#endif /* HAVE_SELINUX */
-: 848:}
-: 849:
-: 850:/**
-: 851: * For debugging: Print out the current hash table of service SIDs.
-: 852: */
-: 853:void
-: 854:bus_selinux_id_table_print (DBusHashTable *service_table)
function bus_selinux_id_table_print called 0 returned 0% blocks executed 0%
#####: 855:{
-: 856:#ifdef DBUS_ENABLE_VERBOSE_MODE
-: 857:#ifdef HAVE_SELINUX
-: 858: DBusHashIter iter;
-: 859:
#####: 860: if (!selinux_enabled)
branch 0 never executed
branch 1 never executed
#####: 861: return;
-: 862:
#####: 863: _dbus_verbose ("Service SID Table:\n");
call 0 never executed
#####: 864: _dbus_hash_iter_init (service_table, &iter);
call 0 never executed
#####: 865: while (_dbus_hash_iter_next (&iter))
call 0 never executed
branch 1 never executed
branch 2 never executed
-: 866: {
#####: 867: const char *key = _dbus_hash_iter_get_string_key (&iter);
call 0 never executed
#####: 868: security_id_t sid = _dbus_hash_iter_get_value (&iter);
call 0 never executed
#####: 869: _dbus_verbose ("The key is %s\n", key);
call 0 never executed
#####: 870: _dbus_verbose ("The context is %s\n", sid->ctx);
call 0 never executed
#####: 871: _dbus_verbose ("The refcount is %d\n", sid->refcnt);
call 0 never executed
-: 872: }
-: 873:#endif /* HAVE_SELINUX */
-: 874:#endif /* DBUS_ENABLE_VERBOSE_MODE */
-: 875:}
-: 876:
-: 877:
-: 878:#ifdef DBUS_ENABLE_VERBOSE_MODE
-: 879:#ifdef HAVE_SELINUX
-: 880:/**
-: 881: * Print out some AVC statistics.
-: 882: */
-: 883:static void
-: 884:bus_avc_print_stats (void)
function bus_avc_print_stats called 1 returned 100% blocks executed 93%
1: 885:{
-: 886: struct avc_cache_stats cstats;
-: 887:
1: 888: if (!selinux_enabled)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 889: return;
-: 890:
1: 891: _dbus_verbose ("AVC Statistics:\n");
call 0 returned 100%
1: 892: avc_cache_stats (&cstats);
call 0 returned 100%
1: 893: avc_av_stats ();
call 0 returned 100%
1: 894: _dbus_verbose ("AVC Cache Statistics:\n");
call 0 returned 100%
1: 895: _dbus_verbose ("Entry lookups: %d\n", cstats.entry_lookups);
call 0 returned 100%
1: 896: _dbus_verbose ("Entry hits: %d\n", cstats.entry_hits);
call 0 returned 100%
1: 897: _dbus_verbose ("Entry misses %d\n", cstats.entry_misses);
call 0 returned 100%
1: 898: _dbus_verbose ("Entry discards: %d\n", cstats.entry_discards);
call 0 returned 100%
1: 899: _dbus_verbose ("CAV lookups: %d\n", cstats.cav_lookups);
call 0 returned 100%
1: 900: _dbus_verbose ("CAV hits: %d\n", cstats.cav_hits);
call 0 returned 100%
1: 901: _dbus_verbose ("CAV probes: %d\n", cstats.cav_probes);
call 0 returned 100%
1: 902: _dbus_verbose ("CAV misses: %d\n", cstats.cav_misses);
call 0 returned 100%
-: 903:}
-: 904:#endif /* HAVE_SELINUX */
-: 905:#endif /* DBUS_ENABLE_VERBOSE_MODE */
-: 906:
-: 907:
-: 908:/**
-: 909: * Destroy the AVC before we terminate.
-: 910: */
-: 911:void
-: 912:bus_selinux_shutdown (void)
function bus_selinux_shutdown called 1 returned 100% blocks executed 88%
1: 913:{
-: 914:#ifdef HAVE_SELINUX
1: 915: if (!selinux_enabled)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 916: return;
-: 917:
1: 918: _dbus_verbose ("AVC shutdown\n");
call 0 returned 100%
-: 919:
1: 920: if (bus_sid != SECSID_WILD)
branch 0 taken 100% (fallthrough)
branch 1 taken 0%
-: 921: {
1: 922: sidput (bus_sid);
call 0 returned 100%
1: 923: bus_sid = SECSID_WILD;
-: 924:
-: 925:#ifdef DBUS_ENABLE_VERBOSE_MODE
1: 926: bus_avc_print_stats ();
call 0 returned 100%
-: 927:#endif /* DBUS_ENABLE_VERBOSE_MODE */
-: 928:
1: 929: avc_destroy ();
call 0 returned 100%
-: 930: }
-: 931:#endif /* HAVE_SELINUX */
-: 932:}
-: 933: