diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2016-08-01 22:30:38 (GMT) |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2016-08-23 15:44:23 (GMT) |
commit | 6133740d6e80d969ff7d41098a9db1091d0f9c94 (patch) | |
tree | ca5b27f8da06607c240090d936f66822e4c4c6c8 | |
parent | 508f8ccdab0ef530dbc0ef8bb526ee11acc409ed (diff) | |
download | linux-6133740d6e80d969ff7d41098a9db1091d0f9c94.tar.xz |
netfilter: nf_tables: reject hook configuration updates on existing chains
Currently, if you add a base chain whose name clashes with an existing
non-base chain, nf_tables doesn't complain about this. Similarly, if you
update the chain type, the hook number and priority.
With this patch, nf_tables bails out in case any of this unsupported
operations occur by returning EBUSY.
# nft add table x
# nft add chain x y
# nft add chain x y { type nat hook input priority 0\; }
<cmdline>:1:1-49: Error: Could not process rule: Device or resource busy
add chain x y { type nat hook input priority 0; }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | net/netfilter/nf_tables_api.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 463fcad..221d27f 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -1348,6 +1348,37 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk, if (nlh->nlmsg_flags & NLM_F_REPLACE) return -EOPNOTSUPP; + if (nla[NFTA_CHAIN_HOOK]) { + struct nft_base_chain *basechain; + struct nft_chain_hook hook; + struct nf_hook_ops *ops; + + if (!(chain->flags & NFT_BASE_CHAIN)) + return -EBUSY; + + err = nft_chain_parse_hook(net, nla, afi, &hook, + create); + if (err < 0) + return err; + + basechain = nft_base_chain(chain); + if (basechain->type != hook.type) { + nft_chain_release_hook(&hook); + return -EBUSY; + } + + for (i = 0; i < afi->nops; i++) { + ops = &basechain->ops[i]; + if (ops->hooknum != hook.num || + ops->priority != hook.priority || + ops->dev != hook.dev) { + nft_chain_release_hook(&hook); + return -EBUSY; + } + } + nft_chain_release_hook(&hook); + } + if (nla[NFTA_CHAIN_HANDLE] && name) { struct nft_chain *chain2; |