Skip to content
  • Florian Westphal's avatar
    netfilter: nf_tables: fix nat hook table deletion · 1e9451cb
    Florian Westphal authored
    
    
    sybot came up with following transaction:
     add table ip syz0
     add chain ip syz0 syz2 { type nat hook prerouting priority 0; policy accept; }
     add table ip syz0 { flags dormant; }
     delete chain ip syz0 syz2
     delete table ip syz0
    
    which yields:
    hook not found, pf 2 num 0
    WARNING: CPU: 0 PID: 6775 at net/netfilter/core.c:413 __nf_unregister_net_hook+0x3e6/0x4a0 net/netfilter/core.c:413
    [..]
     nft_unregister_basechain_hooks net/netfilter/nf_tables_api.c:206 [inline]
     nft_table_disable net/netfilter/nf_tables_api.c:835 [inline]
     nf_tables_table_disable net/netfilter/nf_tables_api.c:868 [inline]
     nf_tables_commit+0x32d3/0x4d70 net/netfilter/nf_tables_api.c:7550
     nfnetlink_rcv_batch net/netfilter/nfnetlink.c:486 [inline]
     nfnetlink_rcv_skb_batch net/netfilter/nfnetlink.c:544 [inline]
     nfnetlink_rcv+0x14a5/0x1e50 net/netfilter/nfnetlink.c:562
     netlink_unicast_kernel net/netlink/af_netlink.c:1303 [inline]
    
    Problem is that when I added ability to override base hook registration
    to make nat basechains register with the nat core instead of netfilter
    core, I forgot to update nft_table_disable() to use that instead of
    the 'raw' hook register interface.
    
    In syzbot transaction, the basechain is of 'nat' type. Its registered
    with the nat core.  The switch to 'dormant mode' attempts to delete from
    netfilter core instead.
    
    After updating nft_table_disable/enable to use the correct helper,
    nft_(un)register_basechain_hooks can be folded into the only remaining
    caller.
    
    Because nft_trans_table_enable() won't do anything when the DORMANT flag
    is set, remove the flag first, then re-add it in case re-enablement
    fails, else this patch breaks sequence:
    
    add table ip x { flags dormant; }
    /* add base chains */
    add table ip x
    
    The last 'add' will remove the dormant flags, but won't have any other
    effect -- base chains are not registered.
    Then, next 'set dormant flag' will create another 'hook not found'
    splat.
    
    Reported-by: default avatar <syzbot+2570f2c036e3da5db176@syzkaller.appspotmail.com>
    Fixes: 4e25ceb8
    
     ("netfilter: nf_tables: allow chain type to override hook register")
    Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
    Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
    1e9451cb