Commit 77a92189 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: nf_tables: report EEXIST on overlaps

Replace EBUSY by EEXIST in the following cases:

- If the user adds a chain with a different configuration such as different
  type, hook and priority.

- If the user adds a non-base chain that clashes with an existing basechain.

- If the user adds a { key : value } mapping element and the key exists
  but the value differs.

- If the device already belongs to an existing flowtable.

User describe that this error reporting is confusing:

- https://bugzilla.netfilter.org/show_bug.cgi?id=1176
- https://bugzilla.netfilter.org/show_bug.cgi?id=1413Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 83d9dcba
...@@ -2097,7 +2097,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, ...@@ -2097,7 +2097,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
if (nla[NFTA_CHAIN_HOOK]) { if (nla[NFTA_CHAIN_HOOK]) {
if (!nft_is_base_chain(chain)) if (!nft_is_base_chain(chain))
return -EBUSY; return -EEXIST;
err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family, err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family,
false); false);
...@@ -2107,21 +2107,21 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, ...@@ -2107,21 +2107,21 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
basechain = nft_base_chain(chain); basechain = nft_base_chain(chain);
if (basechain->type != hook.type) { if (basechain->type != hook.type) {
nft_chain_release_hook(&hook); nft_chain_release_hook(&hook);
return -EBUSY; return -EEXIST;
} }
if (ctx->family == NFPROTO_NETDEV) { if (ctx->family == NFPROTO_NETDEV) {
if (!nft_hook_list_equal(&basechain->hook_list, if (!nft_hook_list_equal(&basechain->hook_list,
&hook.list)) { &hook.list)) {
nft_chain_release_hook(&hook); nft_chain_release_hook(&hook);
return -EBUSY; return -EEXIST;
} }
} else { } else {
ops = &basechain->ops; ops = &basechain->ops;
if (ops->hooknum != hook.num || if (ops->hooknum != hook.num ||
ops->priority != hook.priority) { ops->priority != hook.priority) {
nft_chain_release_hook(&hook); nft_chain_release_hook(&hook);
return -EBUSY; return -EEXIST;
} }
} }
nft_chain_release_hook(&hook); nft_chain_release_hook(&hook);
...@@ -5262,10 +5262,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, ...@@ -5262,10 +5262,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^ if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^
nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) || nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) ||
nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^ nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^
nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF)) { nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF))
err = -EBUSY;
goto err_element_clash; goto err_element_clash;
}
if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) && if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) && nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
memcmp(nft_set_ext_data(ext), memcmp(nft_set_ext_data(ext),
...@@ -5273,7 +5271,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, ...@@ -5273,7 +5271,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
(nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) && (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF) && nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF) &&
*nft_set_ext_obj(ext) != *nft_set_ext_obj(ext2))) *nft_set_ext_obj(ext) != *nft_set_ext_obj(ext2)))
err = -EBUSY; goto err_element_clash;
else if (!(nlmsg_flags & NLM_F_EXCL)) else if (!(nlmsg_flags & NLM_F_EXCL))
err = 0; err = 0;
} else if (err == -ENOTEMPTY) { } else if (err == -ENOTEMPTY) {
...@@ -6423,7 +6421,7 @@ static int nft_register_flowtable_net_hooks(struct net *net, ...@@ -6423,7 +6421,7 @@ static int nft_register_flowtable_net_hooks(struct net *net,
list_for_each_entry(hook2, &ft->hook_list, list) { list_for_each_entry(hook2, &ft->hook_list, list) {
if (hook->ops.dev == hook2->ops.dev && if (hook->ops.dev == hook2->ops.dev &&
hook->ops.pf == hook2->ops.pf) { hook->ops.pf == hook2->ops.pf) {
err = -EBUSY; err = -EEXIST;
goto err_unregister_net_hooks; goto err_unregister_net_hooks;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment