On 03/12/2013 10:45 AM, Daniel Wagner wrote:
From: Daniel Wagner <daniel.wag...@bmw-carit.de>

After removing one or more rules the builtin hooks need to be updated
accordingly. iptables_flush_chain() and iptables_delete_rule()
share a common code part.
---
  src/iptables.c | 66 ++++++++++++++++++++++++----------------------------------
  1 file changed, 27 insertions(+), 39 deletions(-)

diff --git a/src/iptables.c b/src/iptables.c
index 5e24efb..96a575c 100644
--- a/src/iptables.c
+++ b/src/iptables.c
@@ -515,6 +515,29 @@ static int remove_table_entry(struct connman_iptables 
*table,
        return removed;
  }

+static void delete_update_hooks(struct connman_iptables *table,
+                               int builtin, GList *chain_head,
+                               int removed)
+{
+       struct connman_iptables_entry *e;
+       GList *list;
+
+       e = chain_head->data;
+       e->builtin = builtin;
+
+       table->underflow[builtin] -= removed;
+
+       for (list = chain_head->next; list; list = list->next) {
+               e = list->data;
+
+               if (e->builtin < 0)
+                       continue;
+
+               table->hook_entry[e->builtin] -= removed;
+               table->underflow[e->builtin] -= removed;
+       }
+}
+
  static int iptables_flush_chain(struct connman_iptables *table,
                                                const char *name)
  {
@@ -552,26 +575,8 @@ static int iptables_flush_chain(struct connman_iptables 
*table,
                list = next;
        }

-       if (builtin >= 0) {
-               struct connman_iptables_entry *e;
-
-               entry = list->data;
-
-               entry->builtin = builtin;
-
-               table->underflow[builtin] -= removed;
-
-               for (list = chain_tail; list; list = list->next) {
-                       e = list->data;
-
-                       builtin = e->builtin;
-                       if (builtin < 0)
-                               continue;
-
-                       table->hook_entry[builtin] -= removed;
-                       table->underflow[builtin] -= removed;
-               }
-       }
+       if (builtin >= 0)
+               delete_update_hooks(table, builtin, chain_head, removed);

        update_offsets(table);

@@ -1034,25 +1039,8 @@ static int iptables_delete_rule(struct connman_iptables 
*table,

        removed += remove_table_entry(table, entry);

-       if (builtin >= 0) {
-               list = list->next;
-               if (list) {
-                       entry = list->data;
-                       entry->builtin = builtin;
-               }

We have here hidden bug. If we remove the first rule in the table then list == chain_head, and we just removed that entry with remove_table_entry(). That means the pointer 'list' has been modified in remove_table_entry.


-
-               table->underflow[builtin] -= removed;
-               for (list = chain_tail; list; list = list->next) {
-                       entry = list->data;
-
-                       builtin = entry->builtin;
-                       if (builtin < 0)
-                               continue;
-
-                       table->hook_entry[builtin] -= removed;
-                       table->underflow[builtin] -= removed;
-               }
-       }
+       if (builtin >= 0)
+               delete_update_hooks(table, builtin, chain_head, removed);

And here I do the same mistake be assuming chain_head is still valid. An updated version is on the way.


_______________________________________________
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman

Reply via email to