bus/policy: direct checking of policy, without copies 91/234091/2
authorAdrian Szyndela <adrian.s@samsung.com>
Wed, 20 May 2020 13:09:21 +0000 (15:09 +0200)
committerAdrian Szyndela <adrian.s@samsung.com>
Mon, 1 Jun 2020 09:59:55 +0000 (11:59 +0200)
Change-Id: I42926c107aae0be1a1247a61f3558122b07f9914

bus/policy.c

index 272adcf..45477b9 100644 (file)
 #include <dbus/dbus-internals.h>
 #include <dbus/dbus-message-internal.h>
 
-static dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy,
-                                                  BusPolicyRule *rule);
+struct BusClientPolicy
+{
+  int refcount;
+
+  BusPolicy *policy;
+  unsigned long *groups;
+  int n_groups;
+  dbus_uid_t uid;
+  dbus_bool_t uid_set;
+  dbus_bool_t at_console;
+};
 
 BusPolicyRule*
 bus_policy_rule_new (BusPolicyRuleType type,
@@ -246,49 +255,12 @@ bus_policy_unref (BusPolicy *policy)
     }
 }
 
-static dbus_bool_t
-add_list_to_client (DBusList        **list,
-                    BusClientPolicy  *client)
-{
-  DBusList *link;
-
-  link = _dbus_list_get_first_link (list);
-  while (link != NULL)
-    {
-      BusPolicyRule *rule = link->data;
-      link = _dbus_list_get_next_link (list, link);
-
-      switch (rule->type)
-        {
-        case BUS_POLICY_RULE_USER:
-        case BUS_POLICY_RULE_GROUP:
-          /* These aren't per-connection policies */
-          break;
-
-        case BUS_POLICY_RULE_OWN:
-        case BUS_POLICY_RULE_SEND:
-        case BUS_POLICY_RULE_RECEIVE:
-          /* These are per-connection */
-          if (!bus_client_policy_append_rule (client, rule))
-            return FALSE;
-          break;
-
-        default:
-          _dbus_assert_not_reached ("invalid rule");
-        }
-    }
-  
-  return TRUE;
-}
-
 BusClientPolicy*
 bus_policy_create_client_policy (BusPolicy      *policy,
                                  DBusConnection *connection,
                                  DBusError      *error)
 {
   BusClientPolicy *client;
-  dbus_uid_t uid;
-  dbus_bool_t at_console;
 
   _dbus_assert (dbus_connection_get_is_authenticated (connection));
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -297,82 +269,22 @@ bus_policy_create_client_policy (BusPolicy      *policy,
   if (client == NULL)
     goto nomem;
 
-  if (!add_list_to_client (&policy->default_rules,
-                           client))
-    goto nomem;
-
-  /* we avoid the overhead of looking up user's groups
-   * if we don't have any group rules anyway
-   */
   if (_dbus_hash_table_get_n_entries (policy->rules_by_gid) > 0)
     {
-      unsigned long *groups;
-      int n_groups;
-      int i;
-      
-      if (!bus_connection_get_unix_groups (connection, &groups, &n_groups, error))
+      if (!bus_connection_get_unix_groups (connection, &client->groups, &client->n_groups, error))
         goto failed;
-      
-      i = 0;
-      while (i < n_groups)
-        {
-          DBusList **list;
-          
-          list = _dbus_hash_table_lookup_uintptr (policy->rules_by_gid,
-                                                groups[i]);
-          
-          if (list != NULL)
-            {
-              if (!add_list_to_client (list, client))
-                {
-                  dbus_free (groups);
-                  goto nomem;
-                }
-            }
-          
-          ++i;
-        }
-
-      dbus_free (groups);
     }
   
-  if (dbus_connection_get_unix_user (connection, &uid))
+  if (dbus_connection_get_unix_user (connection, &client->uid))
     {
-      if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
-        {
-          DBusList **list;
-          
-          list = _dbus_hash_table_lookup_uintptr (policy->rules_by_uid,
-                                                uid);
-          
-          if (list != NULL)
-            {
-              if (!add_list_to_client (list, client))
-                goto nomem;
-            }
-        }
-
-      /* Add console rules */
-      at_console = _dbus_unix_user_is_at_console (uid, error);
+      client->uid_set = TRUE;
+      client->at_console = _dbus_unix_user_is_at_console (client->uid, error);
       
-      if (at_console)
-        {
-          if (!add_list_to_client (&policy->at_console_true_rules, client))
-            goto nomem;
-        }
-      else if (dbus_error_is_set (error) == TRUE)
-        {
+      if (dbus_error_is_set (error) == TRUE)
           goto failed;
-        }
-      else if (!add_list_to_client (&policy->at_console_false_rules, client))
-        {
-          goto nomem;
-        }
     }
 
-  if (!add_list_to_client (&policy->mandatory_rules,
-                           client))
-    goto nomem;
+  client->policy = bus_policy_ref (policy);
 
   return client;
 
@@ -703,13 +615,6 @@ bus_policy_merge (BusPolicy *policy,
   return TRUE;
 }
 
-struct BusClientPolicy
-{
-  int refcount;
-
-  DBusList *rules;
-};
-
 BusClientPolicy*
 bus_client_policy_new (void)
 {
@@ -734,15 +639,6 @@ bus_client_policy_ref (BusClientPolicy *policy)
   return policy;
 }
 
-static void
-rule_unref_foreach (void *data,
-                    void *user_data)
-{
-  BusPolicyRule *rule = data;
-
-  bus_policy_rule_unref (rule);
-}
-
 void
 bus_client_policy_unref (BusClientPolicy *policy)
 {
@@ -752,31 +648,15 @@ bus_client_policy_unref (BusClientPolicy *policy)
 
   if (policy->refcount == 0)
     {
-      _dbus_list_foreach (&policy->rules,
-                          rule_unref_foreach,
-                          NULL);
+      if (policy->policy)
+        bus_policy_unref (policy->policy);
 
-      _dbus_list_clear (&policy->rules);
+      dbus_free (policy->groups);
 
       dbus_free (policy);
     }
 }
 
-static dbus_bool_t
-bus_client_policy_append_rule (BusClientPolicy *policy,
-                               BusPolicyRule   *rule)
-{
-  _dbus_verbose ("Appending rule %p with type %d to policy %p\n",
-                 rule, rule->type, policy);
-  
-  if (!_dbus_list_append (&policy->rules, rule))
-    return FALSE;
-
-  bus_policy_rule_ref (rule);
-
-  return TRUE;
-}
-
 #define _dbus_string_append_printf_err_check(str, fmt, args...) \
     if (!_dbus_string_append_printf(str, fmt, ##args)) \
       { \
@@ -1166,6 +1046,75 @@ check_rules_list (const DBusList   *rules,
     }
 }
 
+static BusResult
+check_policy (BusClientPolicy *policy,
+              CheckRuleFunc    check_func,
+              const void      *params,
+              dbus_int32_t    *toggles,
+              dbus_bool_t     *log,
+              const char     **privilege,
+              BusPolicyRule  **matched_rule)
+{
+  BusResult result = BUS_RESULT_FALSE;
+
+  if (toggles)
+    *toggles = 0;
+
+  /* checking is in the order the rules appeared
+   * in the config file, i.e. last rule that applies wins
+   */
+
+  check_rules_list (policy->policy->default_rules, check_func, params,
+                    toggles, log, &result, privilege, matched_rule);
+
+  /* we avoid the overhead of looking up user's groups
+   * if we don't have any group rules anyway
+   */
+  if (_dbus_hash_table_get_n_entries (policy->policy->rules_by_gid) > 0)
+    {
+      int i;
+
+      for (i = 0; i < policy->n_groups; ++i)
+        {
+          const DBusList **list;
+
+          list = _dbus_hash_table_lookup_uintptr (policy->policy->rules_by_gid,
+                                                  policy->groups[i]);
+
+          if (list != NULL)
+            check_rules_list (*list, check_func, params,
+                              toggles, log, &result, privilege, matched_rule);
+        }
+    }
+
+  if (policy->uid_set)
+    {
+      if (_dbus_hash_table_get_n_entries (policy->policy->rules_by_uid) > 0)
+        {
+          const DBusList **list;
+
+          list = _dbus_hash_table_lookup_uintptr (policy->policy->rules_by_uid,
+                                                  policy->uid);
+
+          if (list != NULL)
+            check_rules_list (*list, check_func, params,
+                              toggles, log, &result, privilege, matched_rule);
+
+          if (policy->at_console)
+            check_rules_list (policy->policy->at_console_true_rules, check_func,
+                              params, toggles, log, &result, privilege, matched_rule);
+          else
+            check_rules_list (policy->policy->at_console_false_rules, check_func,
+                              params, toggles, log, &result, privilege, matched_rule);
+        }
+    }
+
+  check_rules_list (policy->policy->mandatory_rules, check_func, params,
+                    toggles, log, &result, privilege, matched_rule);
+
+  return result;
+}
+
 BusResult
 bus_client_policy_check_can_send (DBusConnection      *sender,
                                   BusClientPolicy     *policy,
@@ -1191,17 +1140,10 @@ bus_client_policy_check_can_send (DBusConnection      *sender,
   params.u.sr.peer = receiver;
   params.u.sr.message = message;
 
-  /* policy->rules is in the order the rules appeared
-   * in the config file, i.e. last rule that applies wins
-   */
-
   _dbus_verbose ("  (policy) checking send rules\n");
-  *toggles = 0;
-
-  result = BUS_RESULT_FALSE;
 
-  check_rules_list (policy->rules, check_send_rule, &params,
-                    toggles, log, &result, &privilege, &matched_rule);
+  result = check_policy (policy, check_send_rule, &params,
+                         toggles, log, &privilege, &matched_rule);
 
   if (result == BUS_RESULT_LATER)
     {
@@ -1456,17 +1398,10 @@ bus_client_policy_check_can_receive (BusClientPolicy     *policy,
     addressed_recipient != proposed_recipient &&
     dbus_message_get_destination (message) != NULL;
 
-  /* policy->rules is in the order the rules appeared
-   * in the config file, i.e. last rule that applies wins
-   */
-
   _dbus_verbose ("  (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
-  *toggles = 0;
-
-  result = BUS_RESULT_FALSE;
 
-  check_rules_list (policy->rules, check_receive_rule, &params,
-                    toggles, NULL, &result, &privilege, &matched_rule);
+  result = check_policy (policy, check_receive_rule, &params,
+                         toggles, NULL, &privilege, &matched_rule);
 
   if (result == BUS_RESULT_LATER)
     {
@@ -1556,14 +1491,8 @@ bus_client_policy_check_can_own (BusClientPolicy  *policy,
   params.type = PARAM_OWN;
   params.u.name = service_name;
   
-  /* policy->rules is in the order the rules appeared
-   * in the config file, i.e. last rule that applies wins
-   */
-
-  result = BUS_RESULT_FALSE;
-
-  check_rules_list (policy->rules, check_own_rule, &params,
-                    NULL, NULL, &result, &privilege, NULL);
+  result = check_policy (policy, check_own_rule, &params,
+                         NULL, NULL, &privilege, NULL);
 
   if (result == BUS_RESULT_LATER)
     {