1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
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
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:
48: static dbus_bool_t selinux_enabled = FALSE;
49:
50:
51: static struct avc_entry_ref aeref;
52:
53:
54: static security_id_t bus_sid = SECSID_WILD;
55:
56:
57: static pthread_t avc_notify_thread;
58:
59:
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:
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
93:
94:
95:
96:
97:
98:
99:
100:
101:
102: #ifdef HAVE_SELINUX
103: static void
104: log_callback (const char *fmt, ...)
105: {
106: va_list ap;
107: va_start(ap, fmt);
108: vsyslog (LOG_INFO, fmt, ap);
109: va_end(ap);
110: }
111:
112:
113:
114:
115:
116: static int
117: policy_reload_callback (u_int32_t event, security_id_t ssid,
118: security_id_t tsid, security_class_t tclass,
119: access_vector_t perms, access_vector_t *out_retained)
120: {
121: if (event == AVC_CALLBACK_RESET)
122: return raise (SIGHUP);
123:
124: return 0;
125: }
126:
127:
128:
129:
130: static void
131: log_audit_callback (void *data, security_class_t class, char *buf, size_t bufleft)
132: {
133: DBusString *audmsg = data;
134: _dbus_string_copy_to_buffer (audmsg, buf, bufleft);
135: }
136:
137:
138:
139:
140:
141:
142:
143:
144: static void *
145: avc_create_thread (void (*run) (void))
146: {
147: int rc;
148:
149: rc = pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
150: if (rc != 0)
151: {
152: _dbus_warn ("Failed to start AVC thread: %s\n", _dbus_strerror (rc));
153: exit (1);
154: }
155: return &avc_notify_thread;
156: }
157:
158:
159: static void
160: avc_stop_thread (void *thread)
161: {
162: pthread_cancel (*(pthread_t *) thread);
163: }
164:
165:
166: static void *
167: avc_alloc_lock (void)
168: {
169: pthread_mutex_t *avc_mutex;
170:
171: avc_mutex = dbus_new (pthread_mutex_t, 1);
172: if (avc_mutex == NULL)
173: {
174: _dbus_warn ("Could not create mutex: %s\n", _dbus_strerror (errno));
175: exit (1);
176: }
177: pthread_mutex_init (avc_mutex, NULL);
178:
179: return avc_mutex;
180: }
181:
182:
183: static void
184: avc_get_lock (void *lock)
185: {
186: pthread_mutex_lock (lock);
187: }
188:
189:
190: static void
191: avc_release_lock (void *lock)
192: {
193: pthread_mutex_unlock (lock);
194: }
195:
196:
197: static void
198: avc_free_lock (void *lock)
199: {
200: pthread_mutex_destroy (lock);
201: dbus_free (lock);
202: }
203: #endif
204:
205:
206:
207:
208:
209: dbus_bool_t
210: bus_selinux_enabled (void)
211: {
212: #ifdef HAVE_SELINUX
213: return selinux_enabled;
214: #else
215: return FALSE;
216: #endif
217: }
218:
219:
220:
221:
222: dbus_bool_t
223: bus_selinux_pre_init (void)
224: {
225: #ifdef HAVE_SELINUX
226: int r;
227: _dbus_assert (bus_sid == SECSID_WILD);
228:
229:
230: r = is_selinux_enabled ();
231: if (r < 0)
232: {
233: _dbus_warn ("Could not tell if SELinux is enabled: %s\n",
234: _dbus_strerror (errno));
235: return FALSE;
236: }
237:
238: selinux_enabled = r != 0;
239: return TRUE;
240: #else
241: return TRUE;
242: #endif
243: }
244:
245:
246:
247:
248:
249: dbus_bool_t
250: bus_selinux_full_init (void)
251: {
252: #ifdef HAVE_SELINUX
253: char *bus_context;
254:
255: _dbus_assert (bus_sid == SECSID_WILD);
256:
257: if (!selinux_enabled)
258: {
259: _dbus_verbose ("SELinux not enabled in this kernel.\n");
260: return TRUE;
261: }
262:
263: _dbus_verbose ("SELinux is enabled in this kernel.\n");
264:
265: avc_entry_ref_init (&aeref);
266: if (avc_init ("avc", &mem_cb, &log_cb, &thread_cb, &lock_cb) < 0)
267: {
268: _dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
269: return FALSE;
270: }
271: else
272: {
273: openlog ("dbus", LOG_PERROR, LOG_USER);
274: _dbus_verbose ("Access Vector Cache (AVC) started.\n");
275: }
276:
277: if (avc_add_callback (policy_reload_callback, AVC_CALLBACK_RESET,
278: NULL, NULL, 0, 0) < 0)
279: {
280: _dbus_warn ("Failed to add policy reload callback: %s\n",
281: _dbus_strerror (errno));
282: avc_destroy ();
283: return FALSE;
284: }
285:
286: bus_context = NULL;
287: bus_sid = SECSID_WILD;
288:
289: if (getcon (&bus_context) < 0)
290: {
291: _dbus_verbose ("Error getting context of bus: %s\n",
292: _dbus_strerror (errno));
293: return FALSE;
294: }
295:
296: if (avc_context_to_sid (bus_context, &bus_sid) < 0)
297: {
298: _dbus_verbose ("Error getting SID from bus context: %s\n",
299: _dbus_strerror (errno));
300: freecon (bus_context);
301: return FALSE;
302: }
303:
304: freecon (bus_context);
305:
306: return TRUE;
307: #else
308: return TRUE;
309: #endif
310: }
311:
312:
313:
314:
315:
316:
317: void
318: bus_selinux_id_unref (BusSELinuxID *sid)
319: {
320: #ifdef HAVE_SELINUX
321: if (!selinux_enabled)
322: return;
323:
324: _dbus_assert (sid != NULL);
325:
326: sidput (SELINUX_SID_FROM_BUS (sid));
327: #endif
328: }
329:
330: void
331: bus_selinux_id_ref (BusSELinuxID *sid)
332: {
333: #ifdef HAVE_SELINUX
334: if (!selinux_enabled)
335: return;
336:
337: _dbus_assert (sid != NULL);
338:
339: sidget (SELINUX_SID_FROM_BUS (sid));
340: #endif
341: }
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359: #ifdef HAVE_SELINUX
360: static dbus_bool_t
361: bus_selinux_check (BusSELinuxID *sender_sid,
362: BusSELinuxID *override_sid,
363: security_class_t target_class,
364: access_vector_t requested,
365: DBusString *auxdata)
366: {
367: if (!selinux_enabled)
368: return TRUE;
369:
370:
371: if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
372: override_sid ?
373: SELINUX_SID_FROM_BUS (override_sid) :
374: SELINUX_SID_FROM_BUS (bus_sid),
375: target_class, requested, &aeref, auxdata) < 0)
376: {
377: _dbus_verbose ("SELinux denying due to security policy.\n");
378: return FALSE;
379: }
380: else
381: return TRUE;
382: }
383: #endif
384:
385:
386:
387:
388:
389:
390:
391:
392:
393: dbus_bool_t
394: bus_selinux_allows_acquire_service (DBusConnection *connection,
395: BusSELinuxID *service_sid,
396: const char *service_name,
397: DBusError *error)
398: {
399: #ifdef HAVE_SELINUX
400: BusSELinuxID *connection_sid;
401: unsigned long spid;
402: DBusString auxdata;
403: dbus_bool_t ret;
404:
405: if (!selinux_enabled)
406: return TRUE;
407:
408: connection_sid = bus_connection_get_selinux_id (connection);
409: if (!dbus_connection_get_unix_process_id (connection, &spid))
410: spid = 0;
411:
412: if (!_dbus_string_init (&auxdata))
413: goto oom;
414:
415: if (!_dbus_string_append (&auxdata, "service="))
416: goto oom;
417:
418: if (!_dbus_string_append (&auxdata, service_name))
419: goto oom;
420:
421: if (spid)
422: {
423: if (!_dbus_string_append (&auxdata, " spid="))
424: goto oom;
425:
426: if (!_dbus_string_append_uint (&auxdata, spid))
427: goto oom;
428: }
429:
430: ret = bus_selinux_check (connection_sid,
431: service_sid,
432: SECCLASS_DBUS,
433: DBUS__ACQUIRE_SVC,
434: &auxdata);
435:
436: _dbus_string_free (&auxdata);
437: return ret;
438:
439: oom:
440: _dbus_string_free (&auxdata);
441: BUS_SET_OOM (error);
442: return FALSE;
443:
444: #else
445: return TRUE;
446: #endif
447: }
448:
449:
450:
451:
452:
453:
454:
455:
456:
457:
458:
459: dbus_bool_t
460: bus_selinux_allows_send (DBusConnection *sender,
461: DBusConnection *proposed_recipient,
462: const char *msgtype,
463: const char *interface,
464: const char *member,
465: const char *error_name,
466: const char *destination,
467: DBusError *error)
468: {
469: #ifdef HAVE_SELINUX
470: BusSELinuxID *recipient_sid;
471: BusSELinuxID *sender_sid;
472: unsigned long spid, tpid;
473: DBusString auxdata;
474: dbus_bool_t ret;
475: dbus_bool_t string_alloced;
476:
477: if (!selinux_enabled)
478: return TRUE;
479:
480: if (!sender || !dbus_connection_get_unix_process_id (sender, &spid))
481: spid = 0;
482: if (!proposed_recipient || !dbus_connection_get_unix_process_id (proposed_recipient, &tpid))
483: tpid = 0;
484:
485: string_alloced = FALSE;
486: if (!_dbus_string_init (&auxdata))
487: goto oom;
488: string_alloced = TRUE;
489:
490: if (!_dbus_string_append (&auxdata, "msgtype="))
491: goto oom;
492:
493: if (!_dbus_string_append (&auxdata, msgtype))
494: goto oom;
495:
496: if (interface)
497: {
498: if (!_dbus_string_append (&auxdata, " interface="))
499: goto oom;
500: if (!_dbus_string_append (&auxdata, interface))
501: goto oom;
502: }
503:
504: if (member)
505: {
506: if (!_dbus_string_append (&auxdata, " member="))
507: goto oom;
508: if (!_dbus_string_append (&auxdata, member))
509: goto oom;
510: }
511:
512: if (error_name)
513: {
514: if (!_dbus_string_append (&auxdata, " error_name="))
515: goto oom;
516: if (!_dbus_string_append (&auxdata, error_name))
517: goto oom;
518: }
519:
520: if (destination)
521: {
522: if (!_dbus_string_append (&auxdata, " dest="))
523: goto oom;
524: if (!_dbus_string_append (&auxdata, destination))
525: goto oom;
526: }
527:
528: if (spid)
529: {
530: if (!_dbus_string_append (&auxdata, " spid="))
531: goto oom;
532:
533: if (!_dbus_string_append_uint (&auxdata, spid))
534: goto oom;
535: }
536:
537: if (tpid)
538: {
539: if (!_dbus_string_append (&auxdata, " tpid="))
540: goto oom;
541:
542: if (!_dbus_string_append_uint (&auxdata, tpid))
543: goto oom;
544: }
545:
546: sender_sid = bus_connection_get_selinux_id (sender);
547:
548: if (proposed_recipient)
549: recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
550: else
551: recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);
552:
553: ret = bus_selinux_check (sender_sid,
554: recipient_sid,
555: SECCLASS_DBUS,
556: DBUS__SEND_MSG,
557: &auxdata);
558:
559: _dbus_string_free (&auxdata);
560:
561: return ret;
562:
563: oom:
564: if (string_alloced)
565: _dbus_string_free (&auxdata);
566: BUS_SET_OOM (error);
567: return FALSE;
568:
569: #else
570: return TRUE;
571: #endif
572: }
573:
574: dbus_bool_t
575: bus_selinux_append_context (DBusMessage *message,
576: BusSELinuxID *sid,
577: DBusError *error)
578: {
579: #ifdef HAVE_SELINUX
580: char *context;
581:
582: if (avc_sid_to_context (SELINUX_SID_FROM_BUS (sid), &context) < 0)
583: {
584: if (errno == ENOMEM)
585: BUS_SET_OOM (error);
586: else
587: dbus_set_error (error, DBUS_ERROR_FAILED,
588: "Error getting context from SID: %s\n",
589: _dbus_strerror (errno));
590: return FALSE;
591: }
592: if (!dbus_message_append_args (message,
593: DBUS_TYPE_ARRAY,
594: DBUS_TYPE_BYTE,
595: &context,
596: strlen (context),
597: DBUS_TYPE_INVALID))
598: {
599: _DBUS_SET_OOM (error);
600: return FALSE;
601: }
602: freecon (context);
603: return TRUE;
604: #else
605: return TRUE;
606: #endif
607: }
608:
609:
610:
611:
612:
613:
614:
615:
616:
617: #ifdef HAVE_SELINUX
618: static dbus_bool_t
619: bus_connection_read_selinux_context (DBusConnection *connection,
620: char **con)
621: {
622: int fd;
623:
624: if (!selinux_enabled)
625: return FALSE;
626:
627: _dbus_assert (connection != NULL);
628:
629: if (!dbus_connection_get_unix_fd (connection, &fd))
630: {
631: _dbus_verbose ("Failed to get file descriptor of socket.\n");
632: return FALSE;
633: }