lkml.org 
[lkml]   [2018]   [Dec]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.19 019/123] netfilter: nf_conncount: fix unexpected permanent node of list.
    Date
    From: Taehee Yoo <ap420073@gmail.com>

    [ Upstream commit 3c5cdb17c3be76714dfd0d03e384f70579545614 ]

    When list->count is 0, the list is deleted by GC. But list->count is
    never reached 0 because initial count value is 1 and it is increased
    when node is inserted. So that initial value of list->count should be 0.

    Originally GC always finds zero count list through deleting node and
    decreasing count. However, list may be left empty since node insertion
    may fail eg. allocaton problem. In order to solve this problem, GC
    routine also finds zero count list without deleting node.

    Fixes: cb2b36f5a97d ("netfilter: nf_conncount: Switch to plain list")
    Signed-off-by: Taehee Yoo <ap420073@gmail.com>
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/netfilter/nf_conncount.c | 18 +++++++++++++++---
    1 file changed, 15 insertions(+), 3 deletions(-)

    diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
    index cb33709138df..8acae4a3e4c0 100644
    --- a/net/netfilter/nf_conncount.c
    +++ b/net/netfilter/nf_conncount.c
    @@ -144,8 +144,10 @@ static bool conn_free(struct nf_conncount_list *list,
    list->count--;
    conn->dead = true;
    list_del_rcu(&conn->node);
    - if (list->count == 0)
    + if (list->count == 0) {
    + list->dead = true;
    free_entry = true;
    + }

    spin_unlock_bh(&list->list_lock);
    call_rcu(&conn->rcu_head, __conn_free);
    @@ -248,7 +250,7 @@ void nf_conncount_list_init(struct nf_conncount_list *list)
    {
    spin_lock_init(&list->list_lock);
    INIT_LIST_HEAD(&list->head);
    - list->count = 1;
    + list->count = 0;
    list->dead = false;
    }
    EXPORT_SYMBOL_GPL(nf_conncount_list_init);
    @@ -262,6 +264,7 @@ bool nf_conncount_gc_list(struct net *net,
    struct nf_conn *found_ct;
    unsigned int collected = 0;
    bool free_entry = false;
    + bool ret = false;

    list_for_each_entry_safe(conn, conn_n, &list->head, node) {
    found = find_or_evict(net, list, conn, &free_entry);
    @@ -291,7 +294,15 @@ bool nf_conncount_gc_list(struct net *net,
    if (collected > CONNCOUNT_GC_MAX_NODES)
    return false;
    }
    - return false;
    +
    + spin_lock_bh(&list->list_lock);
    + if (!list->count) {
    + list->dead = true;
    + ret = true;
    + }
    + spin_unlock_bh(&list->list_lock);
    +
    + return ret;
    }
    EXPORT_SYMBOL_GPL(nf_conncount_gc_list);

    @@ -417,6 +428,7 @@ insert_tree(struct net *net,
    nf_conncount_list_init(&rbconn->list);
    list_add(&conn->node, &rbconn->list.head);
    count = 1;
    + rbconn->list.count = count;

    rb_link_node(&rbconn->node, parent, rbnode);
    rb_insert_color(&rbconn->node, root);
    --
    2.17.1
    \
     
     \ /
      Last update: 2018-12-05 11:14    [W:4.070 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site