diff options
author | Vadim Kochan <vadim4j@gmail.com> | 2017-12-19 00:38:18 +0200 |
---|---|---|
committer | Tobias Klauser <tklauser@distanz.ch> | 2017-12-19 10:06:43 +0100 |
commit | 6e850d43799e0ed00a87313b826211fe57d03a03 (patch) | |
tree | 5ecd82a3e29f65bb04a459b170e4ee6f7cfe2fe1 | |
parent | 642b2d816562ee0588aefa0947a4ee23600adbc5 (diff) |
flowtop: Fix use-after-free on filter reload
There is missing logic which removes flow entry from
related proc's entry while destroying global flows list on
filter reloading, hence add common __flow_list_del_entry which
handles this logic for both cases - when ct destroyed or filter
changed.
This is a 2nd fix for issue #183.
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r-- | flowtop.c | 30 |
1 files changed, 16 insertions, 14 deletions
@@ -470,20 +470,24 @@ static struct flow_entry *flow_list_find_id(struct flow_list *fl, uint32_t id) return NULL; } +static void __flow_list_del_entry(struct flow_list *fl, struct flow_entry *n) +{ + if (n->proc) { + cds_list_del_rcu(&n->proc_head); + n->proc->flows_count--; + } + + cds_list_del_rcu(&n->entry); + call_rcu(&n->rcu, flow_entry_xfree_rcu); +} + static int flow_list_del_entry(struct flow_list *fl, const struct nf_conntrack *ct) { struct flow_entry *n; n = flow_list_find_id(fl, nfct_get_attr_u32(ct, ATTR_ID)); - if (n) { - if (n->proc) { - cds_list_del_rcu(&n->proc_head); - n->proc->flows_count--; - } - - cds_list_del_rcu(&n->entry); - call_rcu(&n->rcu, flow_entry_xfree_rcu); - } + if (n) + __flow_list_del_entry(fl, n); return NFCT_CB_CONTINUE; } @@ -492,10 +496,8 @@ static void flow_list_destroy(struct flow_list *fl) { struct flow_entry *n, *tmp; - cds_list_for_each_entry_safe(n, tmp, &fl->head, entry) { - cds_list_del_rcu(&n->entry); - call_rcu(&n->rcu, flow_entry_xfree_rcu); - } + cds_list_for_each_entry_safe(n, tmp, &fl->head, entry) + __flow_list_del_entry(fl, n); } static void proc_list_init(struct proc_list *proc_list) @@ -562,7 +564,7 @@ static void flow_entry_find_process(struct flow_entry *n) p->stat.bytes_dst += n->stat.bytes_dst; p->flows_count++; - cds_list_add(&n->proc_head, &p->flows); + cds_list_add_rcu(&n->proc_head, &p->flows); n->proc = p; } |