lkml.org 
[lkml]   [2020]   [Jan]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 064/103] netfilter: nf_tables: fix flowtable list del corruption
    Date
    From: Florian Westphal <fw@strlen.de>

    commit 335178d5429c4cee61b58f4ac80688f556630818 upstream.

    syzbot reported following crash:

    list_del corruption, ffff88808c9bb000->prev is LIST_POISON2 (dead000000000122)
    [..]
    Call Trace:
    __list_del_entry include/linux/list.h:131 [inline]
    list_del_rcu include/linux/rculist.h:148 [inline]
    nf_tables_commit+0x1068/0x3b30 net/netfilter/nf_tables_api.c:7183
    [..]

    The commit transaction list has:

    NFT_MSG_NEWTABLE
    NFT_MSG_NEWFLOWTABLE
    NFT_MSG_DELFLOWTABLE
    NFT_MSG_DELTABLE

    A missing generation check during DELTABLE processing causes it to queue
    the DELFLOWTABLE operation a second time, so we corrupt the list here:

    case NFT_MSG_DELFLOWTABLE:
    list_del_rcu(&nft_trans_flowtable(trans)->list);
    nf_tables_flowtable_notify(&trans->ctx,

    because we have two different DELFLOWTABLE transactions for the same
    flowtable. We then call list_del_rcu() twice for the same flowtable->list.

    The object handling seems to suffer from the same bug so add a generation
    check too and only queue delete transactions for flowtables/objects that
    are still active in the next generation.

    Reported-by: syzbot+37a6804945a3a13b1572@syzkaller.appspotmail.com
    Fixes: 3b49e2e94e6eb ("netfilter: nf_tables: add flow table netlink frontend")
    Signed-off-by: Florian Westphal <fw@strlen.de>
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    net/netfilter/nf_tables_api.c | 6 ++++++
    1 file changed, 6 insertions(+)

    --- a/net/netfilter/nf_tables_api.c
    +++ b/net/netfilter/nf_tables_api.c
    @@ -936,12 +936,18 @@ static int nft_flush_table(struct nft_ct
    }

    list_for_each_entry_safe(flowtable, nft, &ctx->table->flowtables, list) {
    + if (!nft_is_active_next(ctx->net, flowtable))
    + continue;
    +
    err = nft_delflowtable(ctx, flowtable);
    if (err < 0)
    goto out;
    }

    list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) {
    + if (!nft_is_active_next(ctx->net, obj))
    + continue;
    +
    err = nft_delobj(ctx, obj);
    if (err < 0)
    goto out;

    \
     
     \ /
      Last update: 2020-01-22 10:46    [W:2.404 / U:0.104 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site