mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 13:28:02 +02:00
2004-07-24 Havoc Pennington <hp@redhat.com>
SELinux support from Matthew Rickard <mjricka@epoch.ncsc.mil> * bus/selinux.c, bus/selinux.h: new file encapsulating selinux functionality * configure.in: add --enable-selinux * bus/policy.c (bus_policy_merge): add FIXME to a comment * bus/main.c (main): initialize and shut down selinux * bus/connection.c: store SELinux ID on each connection, to avoid repeated getting of the string context and converting it into an ID * bus/bus.c (bus_context_get_policy): new accessor, though it isn't used (bus_context_check_security_policy): check whether the security context of sender connection can send to the security context of recipient connection * bus/config-parser.c: add parsing for <selinux> and <associate> * dbus/dbus-transport.c (_dbus_transport_get_unix_fd): to implement dbus_connection_get_unix_fd() * dbus/dbus-connection.c (dbus_connection_get_unix_fd): new function, used by the selinux stuff
This commit is contained in:
parent
4076d31c71
commit
1e9b185b0c
24 changed files with 1266 additions and 26 deletions
31
ChangeLog
31
ChangeLog
|
|
@ -1,3 +1,34 @@
|
|||
2004-07-24 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
SELinux support from Matthew Rickard <mjricka@epoch.ncsc.mil>
|
||||
|
||||
* bus/selinux.c, bus/selinux.h: new file encapsulating selinux
|
||||
functionality
|
||||
|
||||
* configure.in: add --enable-selinux
|
||||
|
||||
* bus/policy.c (bus_policy_merge): add FIXME to a comment
|
||||
|
||||
* bus/main.c (main): initialize and shut down selinux
|
||||
|
||||
* bus/connection.c: store SELinux ID on each connection, to avoid
|
||||
repeated getting of the string context and converting it into
|
||||
an ID
|
||||
|
||||
* bus/bus.c (bus_context_get_policy): new accessor, though it
|
||||
isn't used
|
||||
(bus_context_check_security_policy): check whether the security
|
||||
context of sender connection can send to the security context of
|
||||
recipient connection
|
||||
|
||||
* bus/config-parser.c: add parsing for <selinux> and <associate>
|
||||
|
||||
* dbus/dbus-transport.c (_dbus_transport_get_unix_fd): to
|
||||
implement dbus_connection_get_unix_fd()
|
||||
|
||||
* dbus/dbus-connection.c (dbus_connection_get_unix_fd): new
|
||||
function, used by the selinux stuff
|
||||
|
||||
2004-07-29 Olivier Andrieu <oliv__a@users.sourceforge.net>
|
||||
|
||||
* bus/config-loader-libxml.c: complete the implementation of
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ EFENCE=
|
|||
|
||||
CONFIG_IN_FILES= \
|
||||
session.conf.in \
|
||||
system.conf.in
|
||||
system.conf.in
|
||||
|
||||
config_DATA= \
|
||||
session.conf \
|
||||
|
|
@ -44,6 +44,8 @@ BUS_SOURCES= \
|
|||
expirelist.h \
|
||||
policy.c \
|
||||
policy.h \
|
||||
selinux.h \
|
||||
selinux.c \
|
||||
services.c \
|
||||
services.h \
|
||||
signals.c \
|
||||
|
|
|
|||
49
bus/bus.c
49
bus/bus.c
|
|
@ -29,6 +29,7 @@
|
|||
#include "policy.h"
|
||||
#include "config-parser.h"
|
||||
#include "signals.h"
|
||||
#include "selinux.h"
|
||||
#include <dbus/dbus-list.h>
|
||||
#include <dbus/dbus-hash.h>
|
||||
#include <dbus/dbus-internals.h>
|
||||
|
|
@ -403,6 +404,7 @@ process_config_every_time (BusContext *context,
|
|||
{
|
||||
DBusString full_address;
|
||||
DBusList *link;
|
||||
DBusHashTable *service_sid_table;
|
||||
|
||||
dbus_bool_t retval;
|
||||
|
||||
|
|
@ -480,6 +482,11 @@ process_config_every_time (BusContext *context,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
service_sid_table = bus_config_parser_steal_service_sid_table (parser);
|
||||
bus_registry_set_service_sid_table (context->registry,
|
||||
service_sid_table);
|
||||
_dbus_hash_table_unref (service_sid_table);
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
retval = TRUE;
|
||||
|
||||
|
|
@ -569,6 +576,13 @@ bus_context_new (const DBusString *config_file,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
context->registry = bus_registry_new (context);
|
||||
if (context->registry == NULL)
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (!load_config (context, FALSE, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
|
|
@ -637,13 +651,6 @@ bus_context_new (const DBusString *config_file,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
context->registry = bus_registry_new (context);
|
||||
if (context->registry == NULL)
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
context->matchmaker = bus_matchmaker_new ();
|
||||
if (context->matchmaker == NULL)
|
||||
{
|
||||
|
|
@ -958,6 +965,12 @@ bus_context_allow_user (BusContext *context,
|
|||
uid);
|
||||
}
|
||||
|
||||
BusPolicy *
|
||||
bus_context_get_policy (BusContext *context)
|
||||
{
|
||||
return context->policy;
|
||||
}
|
||||
|
||||
BusClientPolicy*
|
||||
bus_context_create_client_policy (BusContext *context,
|
||||
DBusConnection *connection,
|
||||
|
|
@ -1088,6 +1101,28 @@ bus_context_check_security_policy (BusContext *context,
|
|||
|
||||
if (sender != NULL)
|
||||
{
|
||||
/* First verify the SELinux access controls. If allowed then
|
||||
* go on with the standard checks.
|
||||
*/
|
||||
if (!bus_selinux_allows_send (sender, proposed_recipient))
|
||||
{
|
||||
const char *dest = dbus_message_get_destination (message);
|
||||
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
|
||||
"An SELinux policy prevents this sender "
|
||||
"from sending this message to this recipient "
|
||||
"(rejected message had interface \"%s\" "
|
||||
"member \"%s\" error name \"%s\" destination \"%s\")",
|
||||
dbus_message_get_interface (message) ?
|
||||
dbus_message_get_interface (message) : "(unset)",
|
||||
dbus_message_get_member (message) ?
|
||||
dbus_message_get_member (message) : "(unset)",
|
||||
dbus_message_get_error_name (message) ?
|
||||
dbus_message_get_error_name (message) : "(unset)",
|
||||
dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
|
||||
_dbus_verbose ("SELinux security check denying send to service\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (bus_connection_is_active (sender))
|
||||
{
|
||||
sender_policy = bus_connection_get_policy (sender);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ typedef struct BusPolicy BusPolicy;
|
|||
typedef struct BusClientPolicy BusClientPolicy;
|
||||
typedef struct BusPolicyRule BusPolicyRule;
|
||||
typedef struct BusRegistry BusRegistry;
|
||||
typedef struct BusSELinuxID BusSELinuxID;
|
||||
typedef struct BusService BusService;
|
||||
typedef struct BusTransaction BusTransaction;
|
||||
typedef struct BusMatchmaker BusMatchmaker;
|
||||
|
|
@ -78,8 +79,11 @@ BusActivation* bus_context_get_activation (BusContext
|
|||
BusMatchmaker* bus_context_get_matchmaker (BusContext *context);
|
||||
DBusLoop* bus_context_get_loop (BusContext *context);
|
||||
DBusUserDatabase* bus_context_get_user_database (BusContext *context);
|
||||
|
||||
dbus_bool_t bus_context_allow_user (BusContext *context,
|
||||
unsigned long uid);
|
||||
BusPolicy* bus_context_get_policy (BusContext *context);
|
||||
|
||||
BusClientPolicy* bus_context_create_client_policy (BusContext *context,
|
||||
DBusConnection *connection,
|
||||
DBusError *error);
|
||||
|
|
@ -101,5 +105,4 @@ dbus_bool_t bus_context_check_security_policy (BusContext
|
|||
DBusMessage *message,
|
||||
DBusError *error);
|
||||
|
||||
|
||||
#endif /* BUS_BUS_H */
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "test.h"
|
||||
#include "utils.h"
|
||||
#include "policy.h"
|
||||
#include "selinux.h"
|
||||
#include <dbus/dbus-list.h>
|
||||
#include <dbus/dbus-internals.h>
|
||||
#include <string.h>
|
||||
|
|
@ -44,7 +45,9 @@ typedef enum
|
|||
ELEMENT_PIDFILE,
|
||||
ELEMENT_SERVICEDIR,
|
||||
ELEMENT_INCLUDEDIR,
|
||||
ELEMENT_TYPE
|
||||
ELEMENT_TYPE,
|
||||
ELEMENT_SELINUX,
|
||||
ELEMENT_ASSOCIATE
|
||||
} ElementType;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -117,6 +120,8 @@ struct BusConfigParser
|
|||
|
||||
DBusList *included_files; /**< Included files stack */
|
||||
|
||||
DBusHashTable *service_sid_table; /**< Map service names to SELinux contexts */
|
||||
|
||||
unsigned int fork : 1; /**< TRUE to fork into daemon mode */
|
||||
|
||||
unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */
|
||||
|
|
@ -157,6 +162,10 @@ element_type_to_name (ElementType type)
|
|||
return "includedir";
|
||||
case ELEMENT_TYPE:
|
||||
return "type";
|
||||
case ELEMENT_SELINUX:
|
||||
return "selinux";
|
||||
case ELEMENT_ASSOCIATE:
|
||||
return "associate";
|
||||
}
|
||||
|
||||
_dbus_assert_not_reached ("bad element type");
|
||||
|
|
@ -235,6 +244,7 @@ merge_included (BusConfigParser *parser,
|
|||
DBusError *error)
|
||||
{
|
||||
DBusList *link;
|
||||
DBusHashTable *table;
|
||||
|
||||
if (!bus_policy_merge (parser->policy,
|
||||
included->policy))
|
||||
|
|
@ -242,6 +252,17 @@ merge_included (BusConfigParser *parser,
|
|||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
table = bus_selinux_id_table_union (parser->service_sid_table,
|
||||
included->service_sid_table);
|
||||
if (table == NULL)
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_dbus_hash_table_unref (parser->service_sid_table);
|
||||
parser->service_sid_table = table;
|
||||
|
||||
if (included->user != NULL)
|
||||
{
|
||||
|
|
@ -317,12 +338,17 @@ bus_config_parser_new (const DBusString *basedir,
|
|||
}
|
||||
|
||||
if (((parser->policy = bus_policy_new ()) == NULL) ||
|
||||
!_dbus_string_copy (basedir, 0, &parser->basedir, 0))
|
||||
!_dbus_string_copy (basedir, 0, &parser->basedir, 0) ||
|
||||
((parser->service_sid_table = bus_selinux_id_table_new ()) == NULL))
|
||||
{
|
||||
if (parser->policy)
|
||||
bus_policy_unref (parser->policy);
|
||||
|
||||
_dbus_string_free (&parser->basedir);
|
||||
|
||||
if (parser->service_sid_table == NULL)
|
||||
_dbus_hash_table_unref (parser->service_sid_table);
|
||||
|
||||
dbus_free (parser);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -428,6 +454,9 @@ bus_config_parser_unref (BusConfigParser *parser)
|
|||
if (parser->policy)
|
||||
bus_policy_unref (parser->policy);
|
||||
|
||||
if (parser->service_sid_table)
|
||||
_dbus_hash_table_unref (parser->service_sid_table);
|
||||
|
||||
dbus_free (parser);
|
||||
}
|
||||
}
|
||||
|
|
@ -658,7 +687,7 @@ start_busconfig_child (BusConfigParser *parser,
|
|||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp (element_name, "includedir") == 0)
|
||||
|
|
@ -841,6 +870,22 @@ start_busconfig_child (BusConfigParser *parser,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp (element_name, "selinux") == 0)
|
||||
{
|
||||
Element *e;
|
||||
const char *name;
|
||||
|
||||
if (!check_no_attributes (parser, "selinux", attribute_names, attribute_values, error))
|
||||
return FALSE;
|
||||
|
||||
if (push_element (parser, ELEMENT_SELINUX) == NULL)
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
|
|
@ -1390,6 +1435,58 @@ start_policy_child (BusConfigParser *parser,
|
|||
}
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
start_selinux_child (BusConfigParser *parser,
|
||||
const char *element_name,
|
||||
const char **attribute_names,
|
||||
const char **attribute_values,
|
||||
DBusError *error)
|
||||
{
|
||||
if (strcmp (element_name, "associate") == 0)
|
||||
{
|
||||
const char *own;
|
||||
const char *context;
|
||||
|
||||
if (!locate_attributes (parser, "associate",
|
||||
attribute_names,
|
||||
attribute_values,
|
||||
error,
|
||||
"own", &own,
|
||||
"context", &context,
|
||||
NULL))
|
||||
return FALSE;
|
||||
|
||||
if (push_element (parser, ELEMENT_ASSOCIATE) == NULL)
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (own == NULL || context == NULL)
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
"Element <associate> must have attributes own=\"<servicename>\" and context=\"<selinux context>\"");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!bus_selinux_id_table_insert (parser->service_sid_table,
|
||||
own, context))
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
"Element <%s> not allowed inside <%s> in configuration file",
|
||||
element_name, "selinux");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
dbus_bool_t
|
||||
bus_config_parser_start_element (BusConfigParser *parser,
|
||||
const char *element_name,
|
||||
|
|
@ -1440,6 +1537,12 @@ bus_config_parser_start_element (BusConfigParser *parser,
|
|||
attribute_names, attribute_values,
|
||||
error);
|
||||
}
|
||||
else if (t == ELEMENT_SELINUX)
|
||||
{
|
||||
return start_selinux_child (parser, element_name,
|
||||
attribute_names, attribute_values,
|
||||
error);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
|
|
@ -1635,6 +1738,8 @@ bus_config_parser_end_element (BusConfigParser *parser,
|
|||
case ELEMENT_ALLOW:
|
||||
case ELEMENT_DENY:
|
||||
case ELEMENT_FORK:
|
||||
case ELEMENT_SELINUX:
|
||||
case ELEMENT_ASSOCIATE:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1867,6 +1972,8 @@ bus_config_parser_content (BusConfigParser *parser,
|
|||
case ELEMENT_ALLOW:
|
||||
case ELEMENT_DENY:
|
||||
case ELEMENT_FORK:
|
||||
case ELEMENT_SELINUX:
|
||||
case ELEMENT_ASSOCIATE:
|
||||
if (all_whitespace (content))
|
||||
return TRUE;
|
||||
else
|
||||
|
|
@ -2160,6 +2267,20 @@ bus_config_parser_get_limits (BusConfigParser *parser,
|
|||
*limits = parser->limits;
|
||||
}
|
||||
|
||||
DBusHashTable*
|
||||
bus_config_parser_steal_service_sid_table (BusConfigParser *parser)
|
||||
{
|
||||
DBusHashTable *table;
|
||||
|
||||
_dbus_assert (parser->service_sid_table != NULL); /* can only steal once */
|
||||
|
||||
table = parser->service_sid_table;
|
||||
|
||||
parser->service_sid_table = NULL;
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
@ -2494,6 +2615,8 @@ config_parsers_equal (const BusConfigParser *a,
|
|||
|
||||
/* FIXME: compare policy */
|
||||
|
||||
/* FIXME: compare service selinux ID table */
|
||||
|
||||
if (! limits_equal (&a->limits, &b->limits))
|
||||
return FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <dbus/dbus.h>
|
||||
#include <dbus/dbus-string.h>
|
||||
#include <dbus/dbus-list.h>
|
||||
#include <dbus/dbus-hash.h>
|
||||
#include "bus.h"
|
||||
|
||||
/* Whatever XML library we're using just pushes data into this API */
|
||||
|
|
@ -70,6 +71,8 @@ BusPolicy* bus_config_parser_steal_policy (BusConfigParser *parser);
|
|||
void bus_config_parser_get_limits (BusConfigParser *parser,
|
||||
BusLimits *limits);
|
||||
|
||||
DBusHashTable* bus_config_parser_steal_service_sid_table (BusConfigParser *parser);
|
||||
|
||||
/* Loader functions (backended off one of the XML parsers). Returns a
|
||||
* finished ConfigParser.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "utils.h"
|
||||
#include "signals.h"
|
||||
#include "expirelist.h"
|
||||
#include "selinux.h"
|
||||
#include <dbus/dbus-list.h>
|
||||
#include <dbus/dbus-hash.h>
|
||||
#include <dbus/dbus-timeout.h>
|
||||
|
|
@ -75,6 +76,8 @@ typedef struct
|
|||
DBusPreallocatedSend *oom_preallocated;
|
||||
BusClientPolicy *policy;
|
||||
|
||||
BusSELinuxID *selinux_id;
|
||||
|
||||
long connection_tv_sec; /**< Time when we connected (seconds component) */
|
||||
long connection_tv_usec; /**< Time when we connected (microsec component) */
|
||||
int stamp; /**< connections->stamp last time we were traversed */
|
||||
|
|
@ -401,6 +404,9 @@ free_connection_data (void *data)
|
|||
|
||||
if (d->policy)
|
||||
bus_client_policy_unref (d->policy);
|
||||
|
||||
if (d->selinux_id)
|
||||
bus_selinux_id_unref (d->selinux_id);
|
||||
|
||||
dbus_free (d->name);
|
||||
|
||||
|
|
@ -539,6 +545,7 @@ bus_connections_setup_connection (BusConnections *connections,
|
|||
{
|
||||
BusConnectionData *d;
|
||||
dbus_bool_t retval;
|
||||
DBusError error;
|
||||
|
||||
d = dbus_new0 (BusConnectionData, 1);
|
||||
|
||||
|
|
@ -562,6 +569,20 @@ bus_connections_setup_connection (BusConnections *connections,
|
|||
}
|
||||
|
||||
retval = FALSE;
|
||||
|
||||
dbus_error_init (&error);
|
||||
d->selinux_id = bus_selinux_init_connection_id (connection,
|
||||
&error);
|
||||
if (dbus_error_is_set (&error))
|
||||
{
|
||||
/* This is a bit bogus because we pretend all errors
|
||||
* are OOM; this is done because we know that in bus.c
|
||||
* an OOM error disconnects the connection, which is
|
||||
* the same thing we want on any other error.
|
||||
*/
|
||||
dbus_error_free (&error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dbus_connection_set_watch_functions (connection,
|
||||
add_connection_watch,
|
||||
|
|
@ -639,7 +660,11 @@ bus_connections_setup_connection (BusConnections *connections,
|
|||
|
||||
out:
|
||||
if (!retval)
|
||||
{
|
||||
{
|
||||
if (d->selinux_id)
|
||||
bus_selinux_id_unref (d->selinux_id);
|
||||
d->selinux_id = NULL;
|
||||
|
||||
if (!dbus_connection_set_watch_functions (connection,
|
||||
NULL, NULL, NULL,
|
||||
connection,
|
||||
|
|
@ -1008,6 +1033,18 @@ bus_connection_get_matchmaker (DBusConnection *connection)
|
|||
return bus_context_get_matchmaker (d->connections->context);
|
||||
}
|
||||
|
||||
BusSELinuxID*
|
||||
bus_connection_get_selinux_id (DBusConnection *connection)
|
||||
{
|
||||
BusConnectionData *d;
|
||||
|
||||
d = BUS_CONNECTION_DATA (connection);
|
||||
|
||||
_dbus_assert (d != NULL);
|
||||
|
||||
return d->selinux_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the connection is registered with the message bus.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* connection.h Client connections
|
||||
*
|
||||
* Copyright (C) 2003 Red Hat, Inc.
|
||||
* Copyright (C) 2003, 2004 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.0
|
||||
*
|
||||
|
|
@ -50,6 +50,7 @@ BusConnections* bus_connection_get_connections (DBusConnection
|
|||
BusRegistry* bus_connection_get_registry (DBusConnection *connection);
|
||||
BusActivation* bus_connection_get_activation (DBusConnection *connection);
|
||||
BusMatchmaker* bus_connection_get_matchmaker (DBusConnection *connection);
|
||||
BusSELinuxID* bus_connection_get_selinux_id (DBusConnection *connection);
|
||||
dbus_bool_t bus_connections_check_limits (BusConnections *connections,
|
||||
DBusConnection *requesting_completion,
|
||||
DBusError *error);
|
||||
|
|
|
|||
|
|
@ -463,6 +463,110 @@ received" are evaluated separately.
|
|||
Be careful with send_interface/receive_interface, because the
|
||||
interface field in messages is optional.
|
||||
|
||||
.TP
|
||||
.I "<selinux>"
|
||||
|
||||
.PP
|
||||
The <selinux> element contains settings related to Security Enhanced Linux.
|
||||
More details below.
|
||||
|
||||
.TP
|
||||
.I "<associate>"
|
||||
|
||||
.PP
|
||||
An <associate> element appears below an <selinux> element and
|
||||
creates a mapping. Right now only one kind of association is possible:
|
||||
.nf
|
||||
<associate own="org.freedesktop.Foobar" context="foo_t"/>
|
||||
.fi
|
||||
|
||||
.PP
|
||||
This means that if a connection asks to own the service
|
||||
"org.freedesktop.Foobar" then the source context will be the context
|
||||
of the connection and the target context will be "foo_t" - see the
|
||||
short discussion of SELinux below.
|
||||
|
||||
.PP
|
||||
Note, the context here is the target context when acquiring a service,
|
||||
NOT the context of the connection owning the service.
|
||||
|
||||
.PP
|
||||
There's currently no way to set a default for owning any service, if
|
||||
we add this syntax it will look like:
|
||||
.nf
|
||||
<associate own="*" context="foo_t"/>
|
||||
.fi
|
||||
If you find a reason this is useful, let the developers know.
|
||||
Right now the default will be the security context of the bus itself.
|
||||
|
||||
.PP
|
||||
If two <associate> elements specify the same service name,
|
||||
the element appearing later in the configuration file will
|
||||
be used.
|
||||
|
||||
.SH SELinux
|
||||
|
||||
.PP
|
||||
See http://www.nsa.gov/selinux/ for full details on SELinux. Some useful excerpts:
|
||||
|
||||
.IP "" 8
|
||||
Every subject (process) and object (e.g. file, socket, IPC object,
|
||||
etc) in the system is assigned a collection of security attributes,
|
||||
known as a security context. A security context contains all of the
|
||||
security attributes associated with a particular subject or object
|
||||
that are relevant to the security policy.
|
||||
|
||||
.IP "" 8
|
||||
In order to better encapsulate security contexts and to provide
|
||||
greater efficiency, the policy enforcement code of SELinux typically
|
||||
handles security identifiers (SIDs) rather than security contexts. A
|
||||
SID is an integer that is mapped by the security server to a security
|
||||
context at runtime.
|
||||
|
||||
.IP "" 8
|
||||
When a security decision is required, the policy enforcement code
|
||||
passes a pair of SIDs (typically the SID of a subject and the SID of
|
||||
an object, but sometimes a pair of subject SIDs or a pair of object
|
||||
SIDs), and an object security class to the security server. The object
|
||||
security class indicates the kind of object, e.g. a process, a regular
|
||||
file, a directory, a TCP socket, etc.
|
||||
|
||||
.IP "" 8
|
||||
Access decisions specify whether or not a permission is granted for a
|
||||
given pair of SIDs and class. Each object class has a set of
|
||||
associated permissions defined to control operations on objects with
|
||||
that class.
|
||||
|
||||
.PP
|
||||
D-BUS performs SELinux security checks in two places.
|
||||
|
||||
.PP
|
||||
First, any time a message is routed from one connection to another
|
||||
connection, the bus daemon will check permissions with the security context of
|
||||
the first connection as source, security context of the second connection
|
||||
as target, object class "dbus" and requested permission "send_msg".
|
||||
|
||||
.PP
|
||||
If a security context is not available for a connection
|
||||
(impossible when using UNIX domain sockets), then the target
|
||||
context used is the context of the bus daemon itself.
|
||||
There is currently no way to change this default, because we're
|
||||
assuming that only UNIX domain sockets will be used to
|
||||
connect to the systemwide bus. If this changes, we'll
|
||||
probably add a way to set the default connection context.
|
||||
|
||||
.PP
|
||||
Second, any time a connection asks to own a service,
|
||||
the bus daemon will check permissions with the security
|
||||
context of the connection as source, the security context specified
|
||||
for the service name with an <associate> element as target, object
|
||||
class "dbus" and requested permission "acquire_svc".
|
||||
|
||||
.PP
|
||||
If the service name has no security context associated in the
|
||||
configuration file, the security context of the bus daemon
|
||||
itself will be used.
|
||||
|
||||
.SH AUTHOR
|
||||
See http://www.freedesktop.org/software/dbus/doc/AUTHORS
|
||||
|
||||
|
|
|
|||
10
bus/main.c
10
bus/main.c
|
|
@ -28,6 +28,7 @@
|
|||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include "selinux.h"
|
||||
|
||||
static BusContext *context;
|
||||
|
||||
|
|
@ -371,7 +372,13 @@ main (int argc, char **argv)
|
|||
print_pid_fd = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!bus_selinux_init ())
|
||||
{
|
||||
_dbus_warn ("SELinux initialization failed\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
dbus_error_init (&error);
|
||||
context = bus_context_new (&config_file, force_fork,
|
||||
print_addr_fd, print_pid_fd,
|
||||
|
|
@ -395,6 +402,7 @@ main (int argc, char **argv)
|
|||
|
||||
bus_context_shutdown (context);
|
||||
bus_context_unref (context);
|
||||
bus_selinux_shutdown ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
11
bus/policy.c
11
bus/policy.c
|
|
@ -177,7 +177,7 @@ bus_policy_new (void)
|
|||
free_rule_list_func);
|
||||
if (policy->rules_by_gid == NULL)
|
||||
goto failed;
|
||||
|
||||
|
||||
return policy;
|
||||
|
||||
failed:
|
||||
|
|
@ -594,9 +594,10 @@ dbus_bool_t
|
|||
bus_policy_merge (BusPolicy *policy,
|
||||
BusPolicy *to_absorb)
|
||||
{
|
||||
/* Not properly atomic, but as used for configuration files
|
||||
* we don't rely on it.
|
||||
*/
|
||||
/* FIXME Not properly atomic, but as used for configuration files we
|
||||
* don't rely on it quite so much.
|
||||
*/
|
||||
|
||||
if (!append_copy_of_policy_list (&policy->default_rules,
|
||||
&to_absorb->default_rules))
|
||||
return FALSE;
|
||||
|
|
@ -670,7 +671,7 @@ bus_client_policy_unref (BusClientPolicy *policy)
|
|||
NULL);
|
||||
|
||||
_dbus_list_clear (&policy->rules);
|
||||
|
||||
|
||||
dbus_free (policy);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
658
bus/selinux.c
Normal file
658
bus/selinux.c
Normal file
|
|
@ -0,0 +1,658 @@
|
|||
/* selinux.c SELinux security checks for D-BUS
|
||||
*
|
||||
* Author: Matthew Rickard <mjricka@epoch.ncsc.mil>
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.0
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <dbus/dbus-internals.h>
|
||||
#include <dbus/dbus-string.h>
|
||||
#include "selinux.h"
|
||||
#include "services.h"
|
||||
#include "policy.h"
|
||||
#include "config-parser.h"
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/avc.h>
|
||||
#include <selinux/av_permissions.h>
|
||||
#include <selinux/flask.h>
|
||||
#include <stdarg.h>
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
#define BUS_SID_FROM_SELINUX(sid) ((BusSELinuxID*) (sid))
|
||||
#define SELINUX_SID_FROM_BUS(sid) ((security_id_t) (sid))
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
/* Store the value telling us if SELinux is enabled in the kernel. */
|
||||
static dbus_bool_t selinux_enabled = FALSE;
|
||||
|
||||
/* Store an avc_entry_ref to speed AVC decisions. */
|
||||
static struct avc_entry_ref aeref;
|
||||
|
||||
static security_id_t bus_sid = SECSID_WILD;
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
/**
|
||||
* Log callback to log denial messages from the AVC.
|
||||
* This is used in avc_init. Logs to both standard
|
||||
* error and syslogd.
|
||||
*
|
||||
* @param fmt the format string
|
||||
* @param variable argument list
|
||||
*/
|
||||
#ifdef HAVE_SELINUX
|
||||
static void
|
||||
log_callback (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsyslog (LOG_INFO, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the user space access vector cache (AVC) for D-BUS and set up
|
||||
* logging callbacks.
|
||||
*/
|
||||
dbus_bool_t
|
||||
bus_selinux_init (void)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
struct avc_log_callback log_cb = {(void*)log_callback, NULL};
|
||||
int r;
|
||||
char *bus_context;
|
||||
|
||||
_dbus_assert (bus_sid == SECSID_WILD);
|
||||
|
||||
/* Determine if we are running an SELinux kernel. */
|
||||
r = is_selinux_enabled ();
|
||||
if (r < 0)
|
||||
{
|
||||
_dbus_warn ("Could not tell if SELinux is enabled: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
selinux_enabled = r != 0;
|
||||
|
||||
if (!selinux_enabled)
|
||||
{
|
||||
_dbus_verbose ("SELinux not enabled in this kernel.\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_dbus_verbose ("SELinux is enabled in this kernel.\n");
|
||||
|
||||
avc_entry_ref_init (&aeref);
|
||||
if (avc_init ("avc", NULL, &log_cb, NULL, NULL) < 0)
|
||||
{
|
||||
_dbus_warn ("Failed to start Access Vector Cache (AVC).\n");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
openlog ("dbus", LOG_PERROR, LOG_USER);
|
||||
_dbus_verbose ("Access Vector Cache (AVC) started.\n");
|
||||
}
|
||||
|
||||
bus_context = NULL;
|
||||
bus_sid = SECSID_WILD;
|
||||
|
||||
if (getcon (&bus_context) < 0)
|
||||
{
|
||||
_dbus_verbose ("Error getting context of bus: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (avc_context_to_sid (bus_context, &bus_sid) < 0)
|
||||
{
|
||||
_dbus_verbose ("Error getting SID from bus context: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
freecon (bus_context);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
freecon (bus_context);
|
||||
|
||||
return TRUE;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decrement SID reference count.
|
||||
*
|
||||
* @param sid the SID to decrement
|
||||
*/
|
||||
void
|
||||
bus_selinux_id_unref (BusSELinuxID *sid)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!selinux_enabled)
|
||||
return;
|
||||
|
||||
_dbus_assert (sid != NULL);
|
||||
|
||||
sidput (SELINUX_SID_FROM_BUS (sid));
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
void
|
||||
bus_selinux_id_ref (BusSELinuxID *sid)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!selinux_enabled)
|
||||
return;
|
||||
|
||||
_dbus_assert (sid != NULL);
|
||||
|
||||
sidget (SELINUX_SID_FROM_BUS (sid));
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the SELinux security policy allows the given sender
|
||||
* security context to go to the given recipient security context.
|
||||
* This function determines if the requested permissions are to be
|
||||
* granted from the connection to the message bus or to another
|
||||
* optionally supplied security identifier (e.g. for a service
|
||||
* context). Currently these permissions are either send_msg or
|
||||
* acquire_svc in the dbus class.
|
||||
*
|
||||
* @param sender_sid source security context
|
||||
* @param override_sid is the target security context. If SECSID_WILD this will
|
||||
* use the context of the bus itself (e.g. the default).
|
||||
* @param target_class is the target security class.
|
||||
* @param requested is the requested permissions.
|
||||
* @returns #TRUE if security policy allows the send.
|
||||
*/
|
||||
#ifdef HAVE_SELINUX
|
||||
static dbus_bool_t
|
||||
bus_selinux_check (BusSELinuxID *sender_sid,
|
||||
BusSELinuxID *override_sid,
|
||||
security_class_t target_class,
|
||||
access_vector_t requested)
|
||||
{
|
||||
if (!selinux_enabled)
|
||||
return TRUE;
|
||||
|
||||
/* Make the security check. AVC checks enforcing mode here as well. */
|
||||
if (avc_has_perm (SELINUX_SID_FROM_BUS (sender_sid),
|
||||
override_sid ?
|
||||
SELINUX_SID_FROM_BUS (override_sid) :
|
||||
SELINUX_SID_FROM_BUS (bus_sid),
|
||||
target_class, requested, &aeref, NULL) < 0)
|
||||
{
|
||||
_dbus_verbose ("SELinux denying due to security policy.\n");
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
/**
|
||||
* Returns true if the given connection can acquire a service,
|
||||
* assuming the given security ID is needed for that service.
|
||||
*
|
||||
* @param connection connection that wants to own the service
|
||||
* @param service_sid the SID of the service from the table
|
||||
* @returns #TRUE if acquire is permitted.
|
||||
*/
|
||||
dbus_bool_t
|
||||
bus_selinux_allows_acquire_service (DBusConnection *connection,
|
||||
BusSELinuxID *service_sid)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
BusSELinuxID *connection_sid;
|
||||
|
||||
if (!selinux_enabled)
|
||||
return TRUE;
|
||||
|
||||
connection_sid = bus_connection_get_selinux_id (connection);
|
||||
|
||||
return bus_selinux_check (connection_sid,
|
||||
service_sid,
|
||||
SECCLASS_DBUS,
|
||||
DBUS__ACQUIRE_SVC);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if SELinux security controls allow the message to be sent to a
|
||||
* particular connection based on the security context of the sender and
|
||||
* that of the receiver. The destination connection need not be the
|
||||
* addressed recipient, it could be an "eavesdropper"
|
||||
*
|
||||
* @param sender the sender of the message.
|
||||
* @param proposed_recipient the connection the message is to be sent to.
|
||||
* @returns whether to allow the send
|
||||
*/
|
||||
dbus_bool_t
|
||||
bus_selinux_allows_send (DBusConnection *sender,
|
||||
DBusConnection *proposed_recipient)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
BusSELinuxID *recipient_sid;
|
||||
BusSELinuxID *sender_sid;
|
||||
|
||||
if (!selinux_enabled)
|
||||
return TRUE;
|
||||
|
||||
sender_sid = bus_connection_get_selinux_id (sender);
|
||||
/* A NULL proposed_recipient means the bus itself. */
|
||||
if (proposed_recipient)
|
||||
recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
|
||||
else
|
||||
recipient_sid = BUS_SID_FROM_SELINUX (bus_sid);
|
||||
|
||||
return bus_selinux_check (sender_sid, recipient_sid,
|
||||
SECCLASS_DBUS, DBUS__SEND_MSG);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the security context of a connection to the bus. It is up to
|
||||
* the caller to freecon() when they are done.
|
||||
*
|
||||
* @param connection the connection to get the context of.
|
||||
* @param con the location to store the security context.
|
||||
* @returns #TRUE if context is successfully obtained.
|
||||
*/
|
||||
#ifdef HAVE_SELINUX
|
||||
static dbus_bool_t
|
||||
bus_connection_read_selinux_context (DBusConnection *connection,
|
||||
char **con)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (!selinux_enabled)
|
||||
return FALSE;
|
||||
|
||||
_dbus_assert (connection != NULL);
|
||||
|
||||
if (!dbus_connection_get_unix_fd (connection, &fd))
|
||||
{
|
||||
_dbus_verbose ("Failed to get file descriptor of socket.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (getpeercon (fd, con) < 0)
|
||||
{
|
||||
_dbus_verbose ("Error getting context of socket peer: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_dbus_verbose ("Successfully read connection context.\n");
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
/**
|
||||
* Read the SELinux ID from the connection.
|
||||
*
|
||||
* @param connection the connection to read from
|
||||
* @returns the SID if successfully determined, #NULL otherwise.
|
||||
*/
|
||||
BusSELinuxID*
|
||||
bus_selinux_init_connection_id (DBusConnection *connection,
|
||||
DBusError *error)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
char *con;
|
||||
security_id_t sid;
|
||||
|
||||
if (!selinux_enabled)
|
||||
return NULL;
|
||||
|
||||
if (!bus_connection_read_selinux_context (connection, &con))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
"Failed to read an SELinux context from connection");
|
||||
_dbus_verbose ("Error getting peer context.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_dbus_verbose ("Converting context to SID to store on connection\n");
|
||||
|
||||
if (avc_context_to_sid (con, &sid) < 0)
|
||||
{
|
||||
if (errno == ENOMEM)
|
||||
BUS_SET_OOM (error);
|
||||
else
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
"Error getting SID from context: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
|
||||
_dbus_warn ("Error getting SID from context: %s\n",
|
||||
_dbus_strerror (errno));
|
||||
|
||||
freecon (con);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
freecon (con);
|
||||
return BUS_SID_FROM_SELINUX (sid);
|
||||
#else
|
||||
return NULL;
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
|
||||
/* Function for freeing hash table data. These SIDs
|
||||
* should no longer be referenced.
|
||||
*/
|
||||
static void
|
||||
bus_selinux_id_table_free_value (BusSELinuxID *sid)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
/* NULL sometimes due to how DBusHashTable works */
|
||||
if (sid)
|
||||
bus_selinux_id_unref (sid);
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new table mapping service names to security ID.
|
||||
* A security ID is a "compiled" security context, a security
|
||||
* context is just a string.
|
||||
*
|
||||
* @returns the new table or #NULL if no memory
|
||||
*/
|
||||
DBusHashTable*
|
||||
bus_selinux_id_table_new (void)
|
||||
{
|
||||
return _dbus_hash_table_new (DBUS_HASH_STRING,
|
||||
(DBusFreeFunction) dbus_free,
|
||||
(DBusFreeFunction) bus_selinux_id_table_free_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes a service name and service context into the service SID
|
||||
* table as a string and a SID.
|
||||
*
|
||||
* @param service_name is the name of the service.
|
||||
* @param service_context is the context of the service.
|
||||
* @param service_table is the table to hash them into.
|
||||
* @return #FALSE if not enough memory
|
||||
*/
|
||||
dbus_bool_t
|
||||
bus_selinux_id_table_insert (DBusHashTable *service_table,
|
||||
const char *service_name,
|
||||
const char *service_context)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
dbus_bool_t retval;
|
||||
security_id_t sid;
|
||||
char *key;
|
||||
|
||||
if (!selinux_enabled)
|
||||
return TRUE;
|
||||
|
||||
sid = SECSID_WILD;
|
||||
retval = FALSE;
|
||||
|
||||
key = _dbus_strdup (service_name);
|
||||
if (key == NULL)
|
||||
return retval;
|
||||
|
||||
if (avc_context_to_sid (service_context, &sid) < 0)
|
||||
{
|
||||
_dbus_assert (errno == ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_dbus_hash_table_insert_string (service_table,
|
||||
key,
|
||||
BUS_SID_FROM_SELINUX (sid)))
|
||||
goto out;
|
||||
|
||||
_dbus_verbose ("Parsed \tservice: %s \n\t\tcontext: %s\n",
|
||||
key,
|
||||
sid->ctx);
|
||||
|
||||
/* These are owned by the hash, so clear them to avoid unref */
|
||||
key = NULL;
|
||||
sid = SECSID_WILD;
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
out:
|
||||
if (sid != SECSID_WILD)
|
||||
sidput (sid);
|
||||
|
||||
if (key)
|
||||
dbus_free (key);
|
||||
|
||||
return retval;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the security identifier associated with a particular service
|
||||
* name. Return a pointer to this SID, or #NULL/SECSID_WILD if the
|
||||
* service is not found in the hash table. This should be nearly a
|
||||
* constant time operation. If SELinux support is not available,
|
||||
* always return NULL.
|
||||
*
|
||||
* @todo This should return a const security_id_t since we don't
|
||||
* want the caller to mess with it.
|
||||
*
|
||||
* @param service_table the hash table to check for service name.
|
||||
* @param service_name the name of the service to look for.
|
||||
* @returns the SELinux ID associated with the service
|
||||
*/
|
||||
BusSELinuxID*
|
||||
bus_selinux_id_table_lookup (DBusHashTable *service_table,
|
||||
const DBusString *service_name)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
security_id_t sid;
|
||||
|
||||
sid = SECSID_WILD; /* default context */
|
||||
|
||||
if (!selinux_enabled)
|
||||
return NULL;
|
||||
|
||||
_dbus_verbose ("Looking up service SID for %s\n",
|
||||
_dbus_string_get_const_data (service_name));
|
||||
|
||||
sid = _dbus_hash_table_lookup_string (service_table,
|
||||
_dbus_string_get_const_data (service_name));
|
||||
|
||||
if (sid == SECSID_WILD)
|
||||
_dbus_verbose ("Service %s not found\n",
|
||||
_dbus_string_get_const_data (service_name));
|
||||
else
|
||||
_dbus_verbose ("Service %s found\n",
|
||||
_dbus_string_get_const_data (service_name));
|
||||
|
||||
return BUS_SID_FROM_SELINUX (sid);
|
||||
#endif /* HAVE_SELINUX */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
static dbus_bool_t
|
||||
bus_selinux_id_table_copy_over (DBusHashTable *dest,
|
||||
DBusHashTable *override)
|
||||
{
|
||||
const char *key;
|
||||
char *key_copy;
|
||||
BusSELinuxID *sid;
|
||||
DBusHashIter iter;
|
||||
|
||||
_dbus_hash_iter_init (override, &iter);
|
||||
while (_dbus_hash_iter_next (&iter))
|
||||
{
|
||||
key = _dbus_hash_iter_get_string_key (&iter);
|
||||
sid = _dbus_hash_iter_get_value (&iter);
|
||||
|
||||
key_copy = _dbus_strdup (key);
|
||||
if (key_copy == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!_dbus_hash_table_insert_string (dest,
|
||||
key_copy,
|
||||
sid))
|
||||
{
|
||||
dbus_free (key_copy);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bus_selinux_id_ref (sid);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
/**
|
||||
* Creates the union of the two tables (each table maps a service
|
||||
* name to a security ID). In case of the same service name in
|
||||
* both tables, the security ID from "override" will be used.
|
||||
*
|
||||
* @param base the base table
|
||||
* @param override the table that takes precedence in the merge
|
||||
* @returns the new table, or #NULL if out of memory
|
||||
*/
|
||||
DBusHashTable*
|
||||
bus_selinux_id_table_union (DBusHashTable *base,
|
||||
DBusHashTable *override)
|
||||
{
|
||||
DBusHashTable *combined_table;
|
||||
|
||||
combined_table = bus_selinux_id_table_new ();
|
||||
|
||||
if (combined_table == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!selinux_enabled)
|
||||
return combined_table;
|
||||
|
||||
if (!bus_selinux_id_table_copy_over (combined_table, base))
|
||||
{
|
||||
_dbus_hash_table_unref (combined_table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!bus_selinux_id_table_copy_over (combined_table, override))
|
||||
{
|
||||
_dbus_hash_table_unref (combined_table);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
return combined_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* For debugging: Print out the current hash table of service SIDs.
|
||||
*/
|
||||
void
|
||||
bus_selinux_id_table_print (DBusHashTable *service_table)
|
||||
{
|
||||
#ifdef DBUS_ENABLE_VERBOSE_MODE
|
||||
#ifdef HAVE_SELINUX
|
||||
DBusHashIter iter;
|
||||
|
||||
if (!selinux_enabled)
|
||||
return;
|
||||
|
||||
_dbus_verbose ("Service SID Table:\n");
|
||||
_dbus_hash_iter_init (service_table, &iter);
|
||||
while (_dbus_hash_iter_next (&iter))
|
||||
{
|
||||
const char *key = _dbus_hash_iter_get_string_key (&iter);
|
||||
security_id_t sid = _dbus_hash_iter_get_value (&iter);
|
||||
_dbus_verbose ("The key is %s\n", key);
|
||||
_dbus_verbose ("The context is %s\n", sid->ctx);
|
||||
_dbus_verbose ("The refcount is %d\n", sid->refcnt);
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
#endif /* DBUS_ENABLE_VERBOSE_MODE */
|
||||
}
|
||||
|
||||
|
||||
#ifdef DBUS_ENABLE_VERBOSE_MODE
|
||||
#ifdef HAVE_SELINUX
|
||||
/**
|
||||
* Print out some AVC statistics.
|
||||
*/
|
||||
static void
|
||||
bus_avc_print_stats (void)
|
||||
{
|
||||
struct avc_cache_stats cstats;
|
||||
|
||||
if (!selinux_enabled)
|
||||
return;
|
||||
|
||||
_dbus_verbose ("AVC Statistics:\n");
|
||||
avc_cache_stats (&cstats);
|
||||
avc_av_stats ();
|
||||
_dbus_verbose ("AVC Cache Statistics:\n");
|
||||
_dbus_verbose ("Entry lookups: %d\n", cstats.entry_lookups);
|
||||
_dbus_verbose ("Entry hits: %d\n", cstats.entry_hits);
|
||||
_dbus_verbose ("Entry misses %d\n", cstats.entry_misses);
|
||||
_dbus_verbose ("Entry discards: %d\n", cstats.entry_discards);
|
||||
_dbus_verbose ("CAV lookups: %d\n", cstats.cav_lookups);
|
||||
_dbus_verbose ("CAV hits: %d\n", cstats.cav_hits);
|
||||
_dbus_verbose ("CAV probes: %d\n", cstats.cav_probes);
|
||||
_dbus_verbose ("CAV misses: %d\n", cstats.cav_misses);
|
||||
}
|
||||
#endif /* HAVE_SELINUX */
|
||||
#endif /* DBUS_ENABLE_VERBOSE_MODE */
|
||||
|
||||
|
||||
/**
|
||||
* Destroy the AVC before we terminate.
|
||||
*/
|
||||
void
|
||||
bus_selinux_shutdown (void)
|
||||
{
|
||||
#ifdef HAVE_SELINUX
|
||||
if (!selinux_enabled)
|
||||
return;
|
||||
|
||||
sidput (bus_sid);
|
||||
bus_sid = SECSID_WILD;
|
||||
|
||||
#ifdef DBUS_ENABLE_VERBOSE_MODE
|
||||
bus_avc_print_stats ();
|
||||
#endif /* DBUS_ENABLE_VERBOSE_MODE */
|
||||
|
||||
avc_destroy ();
|
||||
#endif /* HAVE_SELINUX */
|
||||
}
|
||||
|
||||
60
bus/selinux.h
Normal file
60
bus/selinux.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/* selinux.h SELinux security check headers for D-BUS
|
||||
*
|
||||
* Author: Matthew Rickard <mjricka@epoch.ncsc.mil>
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.0
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BUS_SELINUX_H
|
||||
#define BUS_SELINUX_H
|
||||
|
||||
#include <dbus/dbus-hash.h>
|
||||
#include <dbus/dbus-connection.h>
|
||||
#include "services.h"
|
||||
|
||||
dbus_bool_t bus_selinux_init (void);
|
||||
void bus_selinux_shutdown (void);
|
||||
|
||||
void bus_selinux_id_ref (BusSELinuxID *sid);
|
||||
void bus_selinux_id_unref (BusSELinuxID *sid);
|
||||
|
||||
DBusHashTable* bus_selinux_id_table_new (void);
|
||||
BusSELinuxID* bus_selinux_id_table_lookup (DBusHashTable *service_table,
|
||||
const DBusString *service_name);
|
||||
dbus_bool_t bus_selinux_id_table_insert (DBusHashTable *service_table,
|
||||
const char *service_name,
|
||||
const char *service_context);
|
||||
DBusHashTable* bus_selinux_id_table_union (DBusHashTable *base,
|
||||
DBusHashTable *override);
|
||||
void bus_selinux_id_table_print (DBusHashTable *service_table);
|
||||
|
||||
|
||||
|
||||
dbus_bool_t bus_selinux_allows_acquire_service (DBusConnection *connection,
|
||||
BusSELinuxID *service_sid);
|
||||
dbus_bool_t bus_selinux_allows_send (DBusConnection *sender,
|
||||
DBusConnection *proposed_recipient);
|
||||
|
||||
|
||||
|
||||
BusSELinuxID* bus_selinux_init_connection_id (DBusConnection *connection,
|
||||
DBusError *error);
|
||||
|
||||
|
||||
|
||||
#endif /* BUS_SELINUX_H */
|
||||
|
|
@ -31,6 +31,8 @@
|
|||
#include "utils.h"
|
||||
#include "activation.h"
|
||||
#include "policy.h"
|
||||
#include "bus.h"
|
||||
#include "selinux.h"
|
||||
|
||||
struct BusService
|
||||
{
|
||||
|
|
@ -51,6 +53,8 @@ struct BusRegistry
|
|||
|
||||
DBusHashTable *service_hash;
|
||||
DBusMemPool *service_pool;
|
||||
|
||||
DBusHashTable *service_sid_table;
|
||||
};
|
||||
|
||||
BusRegistry*
|
||||
|
|
@ -75,6 +79,8 @@ bus_registry_new (BusContext *context)
|
|||
if (registry->service_pool == NULL)
|
||||
goto failed;
|
||||
|
||||
registry->service_sid_table = NULL;
|
||||
|
||||
return registry;
|
||||
|
||||
failed:
|
||||
|
|
@ -103,7 +109,9 @@ bus_registry_unref (BusRegistry *registry)
|
|||
_dbus_hash_table_unref (registry->service_hash);
|
||||
if (registry->service_pool)
|
||||
_dbus_mem_pool_free (registry->service_pool);
|
||||
|
||||
if (registry->service_sid_table)
|
||||
_dbus_hash_table_unref (registry->service_sid_table);
|
||||
|
||||
dbus_free (registry);
|
||||
}
|
||||
}
|
||||
|
|
@ -263,6 +271,7 @@ bus_registry_acquire_service (BusRegistry *registry,
|
|||
BusClientPolicy *policy;
|
||||
BusService *service;
|
||||
BusActivation *activation;
|
||||
BusSELinuxID *sid;
|
||||
|
||||
retval = FALSE;
|
||||
|
||||
|
|
@ -292,6 +301,24 @@ bus_registry_acquire_service (BusRegistry *registry,
|
|||
policy = bus_connection_get_policy (connection);
|
||||
_dbus_assert (policy != NULL);
|
||||
|
||||
/* Note that if sid is #NULL then the bus's own context gets used
|
||||
* in bus_connection_selinux_allows_acquire_service()
|
||||
*/
|
||||
sid = bus_selinux_id_table_lookup (registry->service_sid_table,
|
||||
service_name);
|
||||
|
||||
if (!bus_selinux_allows_acquire_service (connection, sid))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
|
||||
"Connection \"%s\" is not allowed to own the service \"%s\" due "
|
||||
"to SELinux policy",
|
||||
bus_connection_is_active (connection) ?
|
||||
bus_connection_get_name (connection) :
|
||||
"(inactive)",
|
||||
service_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!bus_client_policy_check_can_own (policy, connection,
|
||||
service_name))
|
||||
{
|
||||
|
|
@ -387,6 +414,19 @@ bus_registry_acquire_service (BusRegistry *registry,
|
|||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
bus_registry_set_service_sid_table (BusRegistry *registry,
|
||||
DBusHashTable *table)
|
||||
{
|
||||
_dbus_assert (registry->service_sid_table != table);
|
||||
|
||||
if (registry->service_sid_table)
|
||||
_dbus_hash_table_unref (registry->service_sid_table);
|
||||
|
||||
registry->service_sid_table = table;
|
||||
_dbus_hash_table_ref (table);
|
||||
}
|
||||
|
||||
static void
|
||||
bus_service_unlink_owner (BusService *service,
|
||||
DBusConnection *owner)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <dbus/dbus.h>
|
||||
#include <dbus/dbus-string.h>
|
||||
#include <dbus/dbus-hash.h>
|
||||
#include "connection.h"
|
||||
#include "bus.h"
|
||||
|
||||
|
|
@ -55,6 +56,8 @@ dbus_bool_t bus_registry_acquire_service (BusRegistry *registry
|
|||
dbus_uint32_t *result,
|
||||
BusTransaction *transaction,
|
||||
DBusError *error);
|
||||
void bus_registry_set_service_sid_table (BusRegistry *registry,
|
||||
DBusHashTable *table);
|
||||
|
||||
BusService* bus_service_ref (BusService *service);
|
||||
void bus_service_unref (BusService *service);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <dbus/dbus-string.h>
|
||||
#include <dbus/dbus-sysdeps.h>
|
||||
#include <dbus/dbus-internals.h>
|
||||
#include "selinux.h"
|
||||
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
static void
|
||||
|
|
@ -69,6 +70,9 @@ main (int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!bus_selinux_init ())
|
||||
die ("could not init selinux support");
|
||||
|
||||
_dbus_string_init_const (&test_data_dir, dir);
|
||||
|
||||
#if 0
|
||||
|
|
@ -119,6 +123,8 @@ main (int argc, char **argv)
|
|||
check_memleaks (argv[0]);
|
||||
|
||||
printf ("%s: Success\n", argv[0]);
|
||||
|
||||
bus_selinux_shutdown ();
|
||||
|
||||
return 0;
|
||||
#else /* DBUS_BUILD_TESTS */
|
||||
|
|
|
|||
40
configure.in
40
configure.in
|
|
@ -38,7 +38,7 @@ AC_ARG_ENABLE(gcj, [ --enable-gcj build gcj bindings],ena
|
|||
AC_ARG_ENABLE(mono, [ --enable-mono build mono bindings],enable_mono=$enableval,enable_mono=auto)
|
||||
AC_ARG_ENABLE(mono_docs, [ --enable-mono-docs build mono docs],enable_mono_docs=$enableval,enable_mono_docs=auto)
|
||||
AC_ARG_ENABLE(python, [ --enable-python build python bindings],enable_python=$enableval,enable_python=auto)
|
||||
|
||||
AC_ARG_ENABLE(selinux, [ --enable-selinux build with SELinux support],enable_selinux=$enableval,enable_selinux=auto)
|
||||
|
||||
AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use])
|
||||
AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install])
|
||||
|
|
@ -690,6 +690,40 @@ if $dbus_use_libxml; then
|
|||
XML_CFLAGS=$LIBXML_CFLAGS
|
||||
fi
|
||||
|
||||
# SELinux detection
|
||||
if test x$enable_selinux = xno ; then
|
||||
have_selinux=no;
|
||||
else
|
||||
# See if we have SELinux library
|
||||
AC_CHECK_LIB(selinux, is_selinux_enabled,
|
||||
have_selinux=yes, have_selinux=no)
|
||||
|
||||
# see if we have the SELinux header with the new D-BUS stuff in it
|
||||
if test x$have_selinux = xyes ; then
|
||||
AC_EGREP_HEADER(DBUS__ACQUIRE_SVC, av_permissions.h,
|
||||
have_selinux=yes, have_selinux=no)
|
||||
fi
|
||||
|
||||
if test x$enable_selinux = xauto ; then
|
||||
if test x$have_selinux = xno ; then
|
||||
AC_MSG_WARN([Sufficiently new SELinux library not found])
|
||||
fi
|
||||
else
|
||||
if test x$have_selinux = xno ; then
|
||||
AC_MSG_ERROR([SElinux explicitly required, and SELinux library not found])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_SELINUX, test x$have_selinux = xyes)
|
||||
|
||||
if test x$have_selinux = xyes ; then
|
||||
SELINUX_LIBS=-lselinux
|
||||
AC_DEFINE(HAVE_SELINUX,1,[SELinux support])
|
||||
else
|
||||
SELINUX_LIBS=
|
||||
fi
|
||||
|
||||
#### Set up final flags
|
||||
DBUS_CLIENT_CFLAGS=
|
||||
DBUS_CLIENT_LIBS=
|
||||
|
|
@ -697,7 +731,7 @@ AC_SUBST(DBUS_CLIENT_CFLAGS)
|
|||
AC_SUBST(DBUS_CLIENT_LIBS)
|
||||
|
||||
DBUS_BUS_CFLAGS=$XML_CFLAGS
|
||||
DBUS_BUS_LIBS=$XML_LIBS
|
||||
DBUS_BUS_LIBS="$XML_LIBS $SELINUX_LIBS"
|
||||
AC_SUBST(DBUS_BUS_CFLAGS)
|
||||
AC_SUBST(DBUS_BUS_LIBS)
|
||||
|
||||
|
|
@ -1076,7 +1110,6 @@ fi
|
|||
|
||||
AM_CONDITIONAL(HAVE_PYTHON, test x$have_python = xyes)
|
||||
|
||||
|
||||
AC_OUTPUT([
|
||||
Doxyfile
|
||||
dbus/dbus-arch-deps.h
|
||||
|
|
@ -1167,6 +1200,7 @@ echo "
|
|||
Building Qt bindings: ${have_qt}
|
||||
Building GLib bindings: ${have_glib}
|
||||
Building Python bindings: ${have_python}
|
||||
Building SELinux support: ${have_selinux}
|
||||
Building Mono bindings: ${enable_mono}
|
||||
Building Mono docs: ${enable_mono_docs}
|
||||
Building GTK+ tools: ${have_gtk}
|
||||
|
|
|
|||
|
|
@ -2952,6 +2952,37 @@ dbus_connection_set_dispatch_status_function (DBusConnection *connec
|
|||
(*old_free_data) (old_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UNIX file descriptor of the connection, if any. This can
|
||||
* be used for SELinux access control checks with getpeercon() for
|
||||
* example. DO NOT read or write to the file descriptor, or try to
|
||||
* select() on it; use DBusWatch for main loop integration. Not all
|
||||
* connections will have a file descriptor. So for adding descriptors
|
||||
* to the main loop, use dbus_watch_get_fd() and so forth.
|
||||
*
|
||||
* @param connection the connection
|
||||
* @param fd return location for the file descriptor.
|
||||
* @returns #TRUE if fd is successfully obtained.
|
||||
*/
|
||||
dbus_bool_t
|
||||
dbus_connection_get_unix_fd (DBusConnection *connection,
|
||||
int *fd)
|
||||
{
|
||||
dbus_bool_t retval;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, FALSE);
|
||||
_dbus_return_val_if_fail (connection->transport != NULL, FALSE);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
retval = _dbus_transport_get_unix_fd (connection->transport,
|
||||
fd);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the UNIX user ID of the connection if any.
|
||||
* Returns #TRUE if the uid is filled in.
|
||||
|
|
|
|||
|
|
@ -242,6 +242,9 @@ dbus_bool_t dbus_connection_list_registered (DBusConnection
|
|||
const char *parent_path,
|
||||
char ***child_entries);
|
||||
|
||||
dbus_bool_t dbus_connection_get_unix_fd (DBusConnection *connection,
|
||||
int *fd);
|
||||
|
||||
DBUS_END_DECLS;
|
||||
|
||||
#endif /* DBUS_CONNECTION_H */
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ struct DBusTransportVTable
|
|||
|
||||
void (* live_messages_changed) (DBusTransport *transport);
|
||||
/**< Outstanding messages counter changed */
|
||||
|
||||
dbus_bool_t (* get_unix_fd) (DBusTransport *transport,
|
||||
int *fd_p);
|
||||
/**< Get UNIX file descriptor */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -102,6 +106,7 @@ struct DBusTransport
|
|||
|
||||
DBusAllowUnixUserFunction unix_user_function; /**< Function for checking whether a user is authorized. */
|
||||
void *unix_user_data; /**< Data for unix_user_function */
|
||||
|
||||
DBusFreeFunction free_unix_user_data; /**< Function to free unix_user_data */
|
||||
|
||||
unsigned int disconnected : 1; /**< #TRUE if we are disconnected. */
|
||||
|
|
|
|||
|
|
@ -948,6 +948,18 @@ unix_live_messages_changed (DBusTransport *transport)
|
|||
check_read_watch (transport);
|
||||
}
|
||||
|
||||
|
||||
static dbus_bool_t
|
||||
unix_get_unix_fd (DBusTransport *transport,
|
||||
int *fd_p)
|
||||
{
|
||||
DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport;
|
||||
|
||||
*fd_p = unix_transport->fd;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DBusTransportVTable unix_vtable = {
|
||||
unix_finalize,
|
||||
unix_handle_watch,
|
||||
|
|
@ -955,7 +967,8 @@ static DBusTransportVTable unix_vtable = {
|
|||
unix_connection_set,
|
||||
unix_messages_pending,
|
||||
unix_do_iteration,
|
||||
unix_live_messages_changed
|
||||
unix_live_messages_changed,
|
||||
unix_get_unix_fd
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -636,6 +636,35 @@ _dbus_transport_messages_pending (DBusTransport *transport,
|
|||
_dbus_transport_unref (transport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the UNIX file descriptor, if any.
|
||||
*
|
||||
* @param transport the transport
|
||||
* @param fd_p pointer to fill in with the descriptor
|
||||
* @returns #TRUE if a descriptor was available
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_transport_get_unix_fd (DBusTransport *transport,
|
||||
int *fd_p)
|
||||
{
|
||||
dbus_bool_t retval;
|
||||
|
||||
if (transport->vtable->get_unix_fd == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (transport->disconnected)
|
||||
return FALSE;
|
||||
|
||||
_dbus_transport_ref (transport);
|
||||
|
||||
retval = (* transport->vtable->get_unix_fd) (transport,
|
||||
fd_p);
|
||||
|
||||
_dbus_transport_unref (transport);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a single poll()/select() on the transport's file
|
||||
* descriptors and then reads/writes data as appropriate,
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ void _dbus_transport_set_max_received_size (DBusTransport
|
|||
long _dbus_transport_get_max_received_size (DBusTransport *transport);
|
||||
dbus_bool_t _dbus_transport_get_unix_user (DBusTransport *transport,
|
||||
unsigned long *uid);
|
||||
dbus_bool_t _dbus_transport_get_unix_fd (DBusTransport *transport,
|
||||
int *fd_p);
|
||||
|
||||
dbus_bool_t _dbus_transport_get_unix_process_id (DBusTransport *transport,
|
||||
unsigned long *pid);
|
||||
void _dbus_transport_set_unix_user_function (DBusTransport *transport,
|
||||
|
|
|
|||
|
|
@ -21,5 +21,12 @@
|
|||
<limit name="max_connections_per_user">64</limit>
|
||||
<limit name="max_pending_activations">64</limit>
|
||||
<limit name="max_services_per_connection">256</limit>
|
||||
|
||||
|
||||
<selinux>
|
||||
<associate own="org.freedesktop.FrobationaryMeasures"
|
||||
context="my_selinux_context_t"/>
|
||||
<associate own="org.freedesktop.BlahBlahBlah"
|
||||
context="foo_t"/>
|
||||
</selinux>
|
||||
|
||||
</busconfig>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue