1 From: Brian McGillion <brian.mcgillion@intel.com>
2 Date: Mon, 6 Feb 2012 18:48:30 +0200
3 Subject: Enforce smack policy from conf file
6 bus/config-parser.c | 38 ++++++++++----
7 bus/policy.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++---
9 bus/smack.c | 111 +++++++++++++++++++++++++++++++++++++++++
11 5 files changed, 278 insertions(+), 19 deletions(-)
13 diff --git a/bus/config-parser.c b/bus/config-parser.c
14 index 07e8fbb..d7ba549 100644
15 --- a/bus/config-parser.c
16 +++ b/bus/config-parser.c
17 @@ -43,6 +43,7 @@ typedef enum
25 @@ -64,7 +65,11 @@ typedef struct
29 - unsigned long gid_uid_or_at_console;
32 + unsigned long gid_uid_or_at_console;
38 @@ -150,6 +155,8 @@ element_free (Element *e)
40 if (e->type == ELEMENT_LIMIT)
41 dbus_free (e->d.limit.name);
42 + else if (e->type == ELEMENT_POLICY && e->d.policy.type == POLICY_SMACK)
43 + dbus_free (e->d.policy.smack_label);
47 @@ -972,6 +979,7 @@ start_busconfig_child (BusConfigParser *parser,
50 const char *at_console;
53 if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
55 @@ -988,20 +996,16 @@ start_busconfig_child (BusConfigParser *parser,
60 "at_console", &at_console,
64 - if (((context && user) ||
65 - (context && group) ||
66 - (context && at_console)) ||
68 - (user && at_console)) ||
69 - (group && at_console) ||
70 - !(context || user || group || at_console))
71 + if (((context != NULL) + (user != NULL) + (group != NULL) +
72 + (smack != NULL) + (at_console != NULL)) != 1)
74 dbus_set_error (error, DBUS_ERROR_FAILED,
75 - "<policy> element must have exactly one of (context|user|group|at_console) attributes");
76 + "<policy> element must have exactly one of (context|user|group|smack|at_console) attributes");
80 @@ -1047,6 +1051,16 @@ start_busconfig_child (BusConfigParser *parser,
81 _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
84 + else if (smack != NULL)
86 + e->d.policy.type = POLICY_SMACK;
87 + e->d.policy.smack_label = _dbus_strdup (smack);
88 + if (e->d.policy.smack_label == NULL)
90 + BUS_SET_OOM (error);
94 else if (at_console != NULL)
97 @@ -1631,8 +1645,10 @@ append_rule_from_element (BusConfigParser *parser,
104 + if (!bus_policy_append_smack_rule (parser->policy, pe->d.policy.smack_label, rule))
108 if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
110 diff --git a/bus/policy.c b/bus/policy.c
111 index 379cea9..836354a 100644
115 #include "services.h"
119 #include <dbus/dbus-list.h>
120 #include <dbus/dbus-hash.h>
121 #include <dbus/dbus-internals.h>
122 @@ -126,12 +127,13 @@ struct BusPolicy
126 - DBusList *default_rules; /**< Default policy rules */
127 - DBusList *mandatory_rules; /**< Mandatory policy rules */
128 - DBusHashTable *rules_by_uid; /**< per-UID policy rules */
129 - DBusHashTable *rules_by_gid; /**< per-GID policy rules */
130 - DBusList *at_console_true_rules; /**< console user policy rules where at_console="true"*/
131 - DBusList *at_console_false_rules; /**< console user policy rules where at_console="false"*/
132 + DBusList *default_rules; /**< Default policy rules */
133 + DBusList *mandatory_rules; /**< Mandatory policy rules */
134 + DBusHashTable *rules_by_uid; /**< per-UID policy rules */
135 + DBusHashTable *rules_by_gid; /**< per-GID policy rules */
136 + DBusHashTable *rules_by_smack_label; /**< per-SMACK label policy rules */
137 + DBusList *at_console_true_rules; /**< console user policy rules where at_console="true"*/
138 + DBusList *at_console_false_rules; /**< console user policy rules where at_console="false"*/
142 @@ -181,6 +183,14 @@ bus_policy_new (void)
143 if (policy->rules_by_gid == NULL)
146 +#ifdef DBUS_ENABLE_SMACK
147 + policy->rules_by_smack_label = _dbus_hash_table_new (DBUS_HASH_STRING,
148 + (DBusFreeFunction) dbus_free,
149 + free_rule_list_func);
150 + if (policy->rules_by_smack_label == NULL)
157 @@ -230,7 +240,13 @@ bus_policy_unref (BusPolicy *policy)
158 _dbus_hash_table_unref (policy->rules_by_gid);
159 policy->rules_by_gid = NULL;
163 + if (policy->rules_by_smack_label)
165 + _dbus_hash_table_unref (policy->rules_by_smack_label);
166 + policy->rules_by_smack_label = NULL;
172 @@ -356,6 +372,24 @@ bus_policy_create_client_policy (BusPolicy *policy,
176 + if (policy->rules_by_smack_label &&
177 + _dbus_hash_table_get_n_entries (policy->rules_by_smack_label) > 0)
180 + dbus_bool_t nomem_err = FALSE;
182 + list = bus_smack_generate_allowed_list(connection, policy->rules_by_smack_label, &nomem_err);
186 + nomem_err = !add_list_to_client (list, client);
187 + _dbus_list_clear (list);
194 if (!add_list_to_client (&policy->mandatory_rules,
197 @@ -576,6 +610,66 @@ bus_policy_append_group_rule (BusPolicy *policy,
201 +#ifdef DBUS_ENABLE_SMACK
203 +get_list_string (DBusHashTable *table,
211 + list = _dbus_hash_table_lookup_string (table, key);
217 + list = dbus_new0 (DBusList*, 1);
221 + new_key = _dbus_strdup (key);
222 + if (new_key == NULL)
228 + if (!_dbus_hash_table_insert_string (table, new_key, list))
231 + dbus_free (new_key);
241 +bus_policy_append_smack_rule (BusPolicy *policy,
243 + BusPolicyRule *rule)
245 +#ifdef DBUS_ENABLE_SMACK
248 + list = get_list_string (policy->rules_by_smack_label, label);
252 + if (!_dbus_list_append (list, rule))
255 + bus_policy_rule_ref (rule);
262 bus_policy_append_console_rule (BusPolicy *policy,
263 dbus_bool_t at_console,
264 @@ -653,6 +747,31 @@ merge_id_hash (DBusHashTable *dest,
268 +#ifdef DBUS_ENABLE_SMACK
270 +merge_string_hash (DBusHashTable *dest,
271 + DBusHashTable *to_absorb)
275 + _dbus_hash_iter_init (to_absorb, &iter);
276 + while (_dbus_hash_iter_next (&iter))
278 + const char *absorb_label = _dbus_hash_iter_get_string_key(&iter);
279 + DBusList **list = _dbus_hash_iter_get_value (&iter);
280 + DBusList **target = get_list_string (dest, absorb_label);
282 + if (target == NULL)
285 + if (!append_copy_of_policy_list (target, list))
294 bus_policy_merge (BusPolicy *policy,
295 BusPolicy *to_absorb)
296 @@ -685,6 +804,12 @@ bus_policy_merge (BusPolicy *policy,
297 to_absorb->rules_by_gid))
300 +#ifdef DBUS_ENABLE_SMACK
301 + if (!merge_string_hash (policy->rules_by_smack_label,
302 + to_absorb->rules_by_smack_label))
309 @@ -873,7 +998,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
315 /* policy->rules is in the order the rules appeared
316 * in the config file, i.e. last rule that applies wins
318 diff --git a/bus/policy.h b/bus/policy.h
319 index 3ff6f48..20d0a39 100644
322 @@ -130,6 +130,9 @@ dbus_bool_t bus_policy_append_user_rule (BusPolicy *policy,
323 dbus_bool_t bus_policy_append_group_rule (BusPolicy *policy,
325 BusPolicyRule *rule);
326 +dbus_bool_t bus_policy_append_smack_rule (BusPolicy *policy,
328 + BusPolicyRule *rule);
329 dbus_bool_t bus_policy_append_console_rule (BusPolicy *policy,
330 dbus_bool_t at_console,
331 BusPolicyRule *rule);
332 diff --git a/bus/smack.c b/bus/smack.c
333 index b8542c2..d4546a3 100644
337 #include "connection.h"
338 #include "services.h"
342 #ifdef DBUS_ENABLE_SMACK
343 #include <sys/smack.h>
346 +#define SMACK_WRITE "W"
347 +#define SMACK_READ "R"
348 +#define SMACK_READ_WRITE "RW"
351 #ifdef DBUS_ENABLE_SMACK
353 bus_smack_get_label (DBusConnection *connection)
354 @@ -130,3 +136,108 @@ err:
359 +#ifdef DBUS_ENABLE_SMACK
361 +bus_smack_has_access (const char *subject, const char *object,
362 + const char *access)
364 + return (smack_have_access (subject, object, access) == 1 ? TRUE : FALSE);
370 + * Calculate the list of rules that apply to a connection.
372 + * @param connection The inbound conenction
373 + * @param rules_by_smack_label The table of object labels -> rules mapping
374 + * @param nomem_err (out) If a nomem situation is encountered this value is set to TRUE.
375 + * @returns the list of permitted rules if it exists and no errors were encountered otherwise NULL.
378 +bus_smack_generate_allowed_list (DBusConnection *connection,
379 + DBusHashTable *rules_by_smack_label,
380 + dbus_bool_t *nomem_err)
382 +#ifdef DBUS_ENABLE_SMACK
383 + char *subject_label;
385 + dbus_bool_t is_allowed;
386 + DBusList **allowed_list;
388 + /* the label of the subject, is the label on the new connection,
389 + either the service itself or one of its clients */
390 + subject_label = bus_smack_get_label (connection);
391 + if (subject_label == NULL)
394 + allowed_list = dbus_new0 (DBusList*, 1);
395 + if (allowed_list == NULL)
398 + /* Iterate over all the smack labels we have parsed from the .conf files */
399 + _dbus_hash_iter_init (rules_by_smack_label, &iter);
400 + while (_dbus_hash_iter_next (&iter))
403 + const char *object_label = _dbus_hash_iter_get_string_key (&iter);
404 + /* the list here is all the rules that are 'protected'
405 + by the SMACK label named $object_label */
406 + DBusList **list = _dbus_hash_iter_get_value (&iter);
408 + link = _dbus_list_get_first_link (list);
409 + while (link != NULL)
411 + BusPolicyRule *rule = link->data;
412 + link = _dbus_list_get_next_link (list, link);
413 + is_allowed = FALSE;
415 + switch (rule->type)
417 + case BUS_POLICY_RULE_OWN:
418 + is_allowed = bus_smack_has_access (subject_label,
422 + case BUS_POLICY_RULE_SEND:
423 + is_allowed = bus_smack_has_access (subject_label,
427 + case BUS_POLICY_RULE_RECEIVE:
428 + is_allowed = bus_smack_has_access (subject_label,
438 + if (!_dbus_list_append (allowed_list, rule))
441 + bus_policy_rule_ref (rule);
444 + _dbus_verbose ("permission request subject (%s) -> object (%s) : %s", subject_label, object_label, (is_allowed ? "GRANTED" : "REJECTED"));
448 + dbus_free(subject_label);
449 + return allowed_list;
452 + if (allowed_list != NULL)
453 + _dbus_list_clear (allowed_list);
455 + dbus_free(subject_label);
463 diff --git a/bus/smack.h b/bus/smack.h
464 index 04a4a2a..6b1dfad 100644
471 +#include <dbus/dbus-hash.h>
473 dbus_bool_t bus_smack_handle_get_connection_context (DBusConnection *connection,
474 BusTransaction *transaction,
475 DBusMessage *message,
478 +DBusList **bus_smack_generate_allowed_list (DBusConnection *connection,
479 + DBusHashTable *label_rules,
480 + dbus_bool_t *error);