iptables: Fix invalid access to list after removing first rule
authorDaniel Wagner <daniel.wagner@bmw-carit.de>
Tue, 12 Mar 2013 17:16:45 +0000 (18:16 +0100)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Mon, 18 Mar 2013 12:31:26 +0000 (14:31 +0200)
The list pointer is invalid after remove_table_entry(). Since
we entering the 'if' body only for the first rule in a builtin
chain we can safely update list to point to the next element.

src/iptables.c

index 5e24efb0eeed98c7685e54d456d39a007b99e7b1..2c6580bec0c11c1fa3ea0416092ed84760ffc0ce 100644 (file)
@@ -1022,6 +1022,22 @@ static int iptables_delete_rule(struct connman_iptables *table,
        entry = chain_head->data;
        builtin = entry->builtin;
 
+       if (builtin >= 0 && list == chain_head) {
+               /*
+                * We are about to remove the first rule in the
+                * chain. In this case we need to store the builtin
+                * value to the new chain_head.
+                *
+                * Note, for builtin chains, chain_head->next is
+                * always valid. A builtin chain has always a policy
+                * rule at the end.
+                */
+               chain_head = chain_head->next;
+
+               entry = chain_head->data;
+               entry->builtin = builtin;
+       }
+
        entry = list->data;
        if (entry == NULL)
                return -EINVAL;
@@ -1035,12 +1051,6 @@ 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;
-               }
-
                table->underflow[builtin] -= removed;
                for (list = chain_tail; list; list = list->next) {
                        entry = list->data;