From cdac3e058b922431f387351fd8ebf60a764485d1 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 7 Nov 2004 17:05:19 +0000 Subject: 2004-11-07 Colin Walters * bus/bus.c (load_config): Break into three separate functions: process_config_first_time_only, process_config_every_time, and process_config_postinit. (process_config_every_time): Move call of bus_registry_set_service_context_table into process_config_postinit. (process_config_postinit): New function, does any processing that needs to happen late in initialization (and also on reload). (bus_context_new): Instead of calling load_config, open config parser here and call process_config_first_time_only and process_config_every_time directly. Later, after we have forked but before changing UID, invoke bus_selinux_full_init, and then call process_config_postinit. (bus_context_reload_config): As in bus_context_new, load parse file inside here, and call process_config_every_time and process_config_postinit. * bus/services.h, bus/services.c (bus_registry_set_service_context_table): Rename from bus_registry_set_sid_table. Take string hash from config parser, and convert them here into SIDs. * bus/config-parser.c (struct BusConfigParser): Have config parser only store a mapping of service->context string. (merge_service_context_hash): New function. (merge_included): Merge context string hashes instead of using bus_selinux_id_table_union. (bus_config_parser_new): Don't use bus_selinux_id_table_new; simply create a new string hash. (bus_config_parser_unref): Unref it. (start_selinux_child): Simply insert strings into hash, don't call bus_selinux_id_table_copy_over. * bus/selinux.h, bus/selinux.c (bus_selinux_id_table_union) (bus_selinux_id_table_copy_over): Delete. --- bus/bus.c | 117 ++++++++++++++++++++++++++++++++-------------------- bus/config-parser.c | 68 ++++++++++++++++++++++-------- bus/config-parser.h | 2 +- bus/main.c | 6 --- bus/selinux.c | 96 ++++-------------------------------------- bus/selinux.h | 2 - bus/services.c | 30 ++++++++++---- bus/services.h | 4 +- 8 files changed, 158 insertions(+), 167 deletions(-) (limited to 'bus') diff --git a/bus/bus.c b/bus/bus.c index b34e635c..65e396c3 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -401,7 +401,6 @@ process_config_every_time (BusContext *context, { DBusString full_address; DBusList *link; - DBusHashTable *service_sid_table; dbus_bool_t retval; @@ -479,11 +478,6 @@ 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; @@ -493,46 +487,22 @@ process_config_every_time (BusContext *context, } static dbus_bool_t -load_config (BusContext *context, - dbus_bool_t is_reload, - DBusError *error) +process_config_postinit (BusContext *context, + BusConfigParser *parser, + DBusError *error) { - BusConfigParser *parser; - DBusString config_file; - dbus_bool_t retval; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); + DBusHashTable *service_context_table; - retval = FALSE; - parser = NULL; - - _dbus_string_init_const (&config_file, context->config_file); - parser = bus_config_load (&config_file, TRUE, NULL, error); - if (parser == NULL) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - goto failed; - } - - if (!is_reload && !process_config_first_time_only (context, parser, error)) + service_context_table = bus_config_parser_steal_service_context_table (parser); + if (!bus_registry_set_service_context_table (context->registry, + service_context_table)) { - _DBUS_ASSERT_ERROR_IS_SET (error); - goto failed; - } - - if (!process_config_every_time (context, parser, is_reload, error)) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - goto failed; + BUS_SET_OOM (error); + return FALSE; } - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - retval = TRUE; - - failed: - if (parser) - bus_config_parser_unref (parser); - return retval; + _dbus_hash_table_unref (service_context_table); + return TRUE; } BusContext* @@ -543,9 +513,13 @@ bus_context_new (const DBusString *config_file, DBusError *error) { BusContext *context; + BusConfigParser *parser; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + context = NULL; + parser = NULL; + if (!dbus_server_allocate_data_slot (&server_data_slot)) { BUS_SET_OOM (error); @@ -579,8 +553,20 @@ bus_context_new (const DBusString *config_file, BUS_SET_OOM (error); goto failed; } + + parser = bus_config_load (config_file, TRUE, NULL, error); + if (parser == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } - if (!load_config (context, FALSE, error)) + if (!process_config_first_time_only (context, parser, error)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } + if (!process_config_every_time (context, parser, FALSE, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); goto failed; @@ -723,6 +709,19 @@ bus_context_new (const DBusString *config_file, _dbus_string_free (&pid); } + + if (!bus_selinux_full_init ()) + { + _dbus_warn ("SELinux initialization failed\n"); + } + + if (!process_config_postinit (context, parser, error)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } + if (parser != NULL) + bus_config_parser_unref (parser); /* Here we change our credentials if required, * as soon as we've set up our sockets and pidfile @@ -756,6 +755,8 @@ bus_context_new (const DBusString *config_file, return context; failed: + if (parser != NULL) + bus_config_parser_unref (parser); if (context != NULL) bus_context_unref (context); @@ -769,9 +770,35 @@ dbus_bool_t bus_context_reload_config (BusContext *context, DBusError *error) { - return load_config (context, - TRUE, /* yes, we are re-loading */ - error); + BusConfigParser *parser; + DBusString config_file; + dbus_bool_t ret; + + ret = FALSE; + _dbus_string_init_const (&config_file, context->config_file); + parser = bus_config_load (&config_file, TRUE, NULL, error); + if (parser == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } + + if (!process_config_every_time (context, parser, TRUE, error)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } + if (!process_config_postinit (context, parser, error)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } + ret = TRUE; + + failed: + if (parser != NULL) + bus_config_parser_unref (parser); + return ret; } static void diff --git a/bus/config-parser.c b/bus/config-parser.c index ba1a434d..074c6218 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -123,7 +123,7 @@ struct BusConfigParser DBusList *included_files; /**< Included files stack */ - DBusHashTable *service_sid_table; /**< Map service names to SELinux contexts */ + DBusHashTable *service_context_table; /**< Map service names to SELinux contexts */ unsigned int fork : 1; /**< TRUE to fork into daemon mode */ @@ -241,13 +241,40 @@ top_element_type (BusConfigParser *parser) return ELEMENT_NONE; } +static dbus_bool_t +merge_service_context_hash (DBusHashTable *dest, + DBusHashTable *from) +{ + DBusHashIter iter; + + _dbus_hash_iter_init (from, &iter); + while (_dbus_hash_iter_next (&iter)) + { + const char *service = _dbus_hash_iter_get_string_key (&iter); + const char *context = _dbus_hash_iter_get_value (&iter); + char *service_copy; + char *context_copy; + + service_copy = _dbus_strdup (service); + if (service_copy == NULL) + return FALSE; + context_copy = _dbus_strdup (context); + if (context_copy == NULL) + return FALSE; + + if (!_dbus_hash_table_insert_string (dest, service_copy, context_copy)) + return FALSE; + } + + return TRUE; +} + static dbus_bool_t merge_included (BusConfigParser *parser, BusConfigParser *included, DBusError *error) { DBusList *link; - DBusHashTable *table; if (!bus_policy_merge (parser->policy, included->policy)) @@ -256,16 +283,12 @@ merge_included (BusConfigParser *parser, return FALSE; } - table = bus_selinux_id_table_union (parser->service_sid_table, - included->service_sid_table); - if (table == NULL) + if (!merge_service_context_hash (parser->service_context_table, + included->service_context_table)) { BUS_SET_OOM (error); return FALSE; } - - _dbus_hash_table_unref (parser->service_sid_table); - parser->service_sid_table = table; if (included->user != NULL) { @@ -342,7 +365,9 @@ bus_config_parser_new (const DBusString *basedir, if (((parser->policy = bus_policy_new ()) == NULL) || !_dbus_string_copy (basedir, 0, &parser->basedir, 0) || - ((parser->service_sid_table = bus_selinux_id_table_new ()) == NULL)) + ((parser->service_context_table = _dbus_hash_table_new (DBUS_HASH_STRING, + dbus_free, + dbus_free)) == NULL)) { if (parser->policy) bus_policy_unref (parser->policy); @@ -454,8 +479,8 @@ 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); + if (parser->service_context_table) + _dbus_hash_table_unref (parser->service_context_table); dbus_free (parser); } @@ -1510,6 +1535,8 @@ start_selinux_child (BusConfigParser *parser, { const char *own; const char *context; + char *own_copy; + char *context_copy; if (!locate_attributes (parser, "associate", attribute_names, @@ -1533,8 +1560,15 @@ start_selinux_child (BusConfigParser *parser, return FALSE; } - if (!bus_selinux_id_table_insert (parser->service_sid_table, - own, context)) + own_copy = _dbus_strdup (own); + if (own_copy == NULL) + return FALSE; + context_copy = _dbus_strdup (context); + if (context_copy == NULL) + return FALSE; + + if (!_dbus_hash_table_insert_string (parser->service_context_table, + own_copy, context_copy)) { BUS_SET_OOM (error); return FALSE; @@ -2359,15 +2393,15 @@ bus_config_parser_get_limits (BusConfigParser *parser, } DBusHashTable* -bus_config_parser_steal_service_sid_table (BusConfigParser *parser) +bus_config_parser_steal_service_context_table (BusConfigParser *parser) { DBusHashTable *table; - _dbus_assert (parser->service_sid_table != NULL); /* can only steal once */ + _dbus_assert (parser->service_context_table != NULL); /* can only steal once */ - table = parser->service_sid_table; + table = parser->service_context_table; - parser->service_sid_table = NULL; + parser->service_context_table = NULL; return table; } diff --git a/bus/config-parser.h b/bus/config-parser.h index 75004000..388704db 100644 --- a/bus/config-parser.h +++ b/bus/config-parser.h @@ -71,7 +71,7 @@ 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); +DBusHashTable* bus_config_parser_steal_service_context_table (BusConfigParser *parser); /* Loader functions (backended off one of the XML parsers). Returns a * finished ConfigParser. diff --git a/bus/main.c b/bus/main.c index 296aa63c..40ec9a07 100644 --- a/bus/main.c +++ b/bus/main.c @@ -396,12 +396,6 @@ main (int argc, char **argv) exit (1); } - if (!bus_selinux_full_init ()) - { - _dbus_warn ("SELinux initialization failed\n"); - exit (1); - } - setup_reload_pipe (bus_context_get_loop (context)); _dbus_set_signal_handler (SIGHUP, signal_handler); diff --git a/bus/selinux.c b/bus/selinux.c index 2ddbed71..0a3dec70 100644 --- a/bus/selinux.c +++ b/bus/selinux.c @@ -504,11 +504,11 @@ bus_selinux_init_connection_id (DBusConnection *connection, BUS_SET_OOM (error); else dbus_set_error (error, DBUS_ERROR_FAILED, - "Error getting SID from context: %s\n", - _dbus_strerror (errno)); + "Error getting SID from context \"%s\": %s\n", + con, _dbus_strerror (errno)); - _dbus_warn ("Error getting SID from context: %s\n", - _dbus_strerror (errno)); + _dbus_warn ("Error getting SID from context \"%s\": %s\n", + con, _dbus_strerror (errno)); freecon (con); return NULL; @@ -582,7 +582,11 @@ bus_selinux_id_table_insert (DBusHashTable *service_table, if (avc_context_to_sid ((char *) service_context, &sid) < 0) { - _dbus_assert (errno == ENOMEM); + if (errno == ENOMEM) + return FALSE; + _dbus_warn ("Error getting SID from context \"%s\": %s\n", + (char *) service_context, + _dbus_strerror (errno)); goto out; } @@ -656,88 +660,6 @@ bus_selinux_id_table_lookup (DBusHashTable *service_table, return NULL; } -/** - * Copy security ID table mapping from one table into another. - * - * @param dest the table to copy into - * @param override the table to copy from - * @returns #FALSE if out of memory - */ -#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; -} - /** * Get the SELinux policy root. This is used to find the D-BUS * specific config file within the policy. diff --git a/bus/selinux.h b/bus/selinux.h index 13122520..71271fab 100644 --- a/bus/selinux.h +++ b/bus/selinux.h @@ -42,8 +42,6 @@ BusSELinuxID* bus_selinux_id_table_lookup (DBusHashTable *service_table, 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); const char* bus_selinux_get_policy_root (void); diff --git a/bus/services.c b/bus/services.c index fb27ea0f..31041c37 100644 --- a/bus/services.c +++ b/bus/services.c @@ -417,17 +417,33 @@ bus_registry_acquire_service (BusRegistry *registry, return retval; } -void -bus_registry_set_service_sid_table (BusRegistry *registry, - DBusHashTable *table) +dbus_bool_t +bus_registry_set_service_context_table (BusRegistry *registry, + DBusHashTable *table) { - _dbus_assert (registry->service_sid_table != table); + DBusHashTable *new_table; + DBusHashIter iter; + + new_table = bus_selinux_id_table_new (); + if (!new_table) + return FALSE; + + _dbus_hash_iter_init (table, &iter); + while (_dbus_hash_iter_next (&iter)) + { + const char *service = _dbus_hash_iter_get_string_key (&iter); + const char *context = _dbus_hash_iter_get_value (&iter); + + if (!bus_selinux_id_table_insert (new_table, + service, + context)) + return FALSE; + } if (registry->service_sid_table) _dbus_hash_table_unref (registry->service_sid_table); - - registry->service_sid_table = table; - _dbus_hash_table_ref (table); + registry->service_sid_table = new_table; + return TRUE; } static void diff --git a/bus/services.h b/bus/services.h index e411aecc..f0754043 100644 --- a/bus/services.h +++ b/bus/services.h @@ -56,8 +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); +dbus_bool_t bus_registry_set_service_context_table (BusRegistry *registry, + DBusHashTable *table); BusService* bus_service_ref (BusService *service); void bus_service_unref (BusService *service); -- cgit