diff options
Diffstat (limited to 'target/linux/generic/backport-4.19/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch')
-rw-r--r-- | target/linux/generic/backport-4.19/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/target/linux/generic/backport-4.19/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch b/target/linux/generic/backport-4.19/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch new file mode 100644 index 0000000000..0db6262fd9 --- /dev/null +++ b/target/linux/generic/backport-4.19/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch @@ -0,0 +1,390 @@ +From: Pablo Neira Ayuso <pablo@netfilter.org> +Date: Sat, 9 Dec 2017 15:40:25 +0100 +Subject: [PATCH] netfilter: nf_tables: remove multihook chains and families + +Since NFPROTO_INET is handled from the core, we don't need to maintain +extra infrastructure in nf_tables to handle the double hook +registration, one for IPv4 and another for IPv6. + +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +--- + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -897,8 +897,6 @@ struct nft_stats { + struct u64_stats_sync syncp; + }; + +-#define NFT_HOOK_OPS_MAX 2 +- + /** + * struct nft_base_chain - nf_tables base chain + * +@@ -910,7 +908,7 @@ struct nft_stats { + * @dev_name: device name that this base chain is attached to (if any) + */ + struct nft_base_chain { +- struct nf_hook_ops ops[NFT_HOOK_OPS_MAX]; ++ struct nf_hook_ops ops; + const struct nf_chain_type *type; + u8 policy; + u8 flags; +@@ -971,8 +969,6 @@ enum nft_af_flags { + * @owner: module owner + * @tables: used internally + * @flags: family flags +- * @nops: number of hook ops in this family +- * @hook_ops_init: initialization function for chain hook ops + * @hooks: hookfn overrides for packet validation + */ + struct nft_af_info { +@@ -982,9 +978,6 @@ struct nft_af_info { + struct module *owner; + struct list_head tables; + u32 flags; +- unsigned int nops; +- void (*hook_ops_init)(struct nf_hook_ops *, +- unsigned int); + nf_hookfn *hooks[NF_MAX_HOOKS]; + }; + +--- a/net/bridge/netfilter/nf_tables_bridge.c ++++ b/net/bridge/netfilter/nf_tables_bridge.c +@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_bridge + .family = NFPROTO_BRIDGE, + .nhooks = NF_BR_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, + [NF_BR_LOCAL_IN] = nft_do_chain_bridge, +--- a/net/ipv4/netfilter/nf_tables_arp.c ++++ b/net/ipv4/netfilter/nf_tables_arp.c +@@ -31,7 +31,6 @@ static struct nft_af_info nft_af_arp __r + .family = NFPROTO_ARP, + .nhooks = NF_ARP_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_ARP_IN] = nft_do_chain_arp, + [NF_ARP_OUT] = nft_do_chain_arp, +--- a/net/ipv4/netfilter/nf_tables_ipv4.c ++++ b/net/ipv4/netfilter/nf_tables_ipv4.c +@@ -49,7 +49,6 @@ static struct nft_af_info nft_af_ipv4 __ + .family = NFPROTO_IPV4, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_ipv4, + [NF_INET_LOCAL_OUT] = nft_ipv4_output, +--- a/net/ipv6/netfilter/nf_tables_ipv6.c ++++ b/net/ipv6/netfilter/nf_tables_ipv6.c +@@ -46,7 +46,6 @@ static struct nft_af_info nft_af_ipv6 __ + .family = NFPROTO_IPV6, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_ipv6, + [NF_INET_LOCAL_OUT] = nft_ipv6_output, +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -139,29 +139,26 @@ static void nft_trans_destroy(struct nft + kfree(trans); + } + +-static int nf_tables_register_hooks(struct net *net, +- const struct nft_table *table, +- struct nft_chain *chain, +- unsigned int hook_nops) ++static int nf_tables_register_hook(struct net *net, ++ const struct nft_table *table, ++ struct nft_chain *chain) + { + if (table->flags & NFT_TABLE_F_DORMANT || + !nft_is_base_chain(chain)) + return 0; + +- return nf_register_net_hooks(net, nft_base_chain(chain)->ops, +- hook_nops); ++ return nf_register_net_hook(net, &nft_base_chain(chain)->ops); + } + +-static void nf_tables_unregister_hooks(struct net *net, +- const struct nft_table *table, +- struct nft_chain *chain, +- unsigned int hook_nops) ++static void nf_tables_unregister_hook(struct net *net, ++ const struct nft_table *table, ++ struct nft_chain *chain) + { + if (table->flags & NFT_TABLE_F_DORMANT || + !nft_is_base_chain(chain)) + return; + +- nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, hook_nops); ++ nf_unregister_net_hook(net, &nft_base_chain(chain)->ops); + } + + static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) +@@ -624,8 +621,7 @@ static void _nf_tables_table_disable(str + if (cnt && i++ == cnt) + break; + +- nf_unregister_net_hooks(net, nft_base_chain(chain)->ops, +- afi->nops); ++ nf_unregister_net_hook(net, &nft_base_chain(chain)->ops); + } + } + +@@ -642,8 +638,7 @@ static int nf_tables_table_enable(struct + if (!nft_is_base_chain(chain)) + continue; + +- err = nf_register_net_hooks(net, nft_base_chain(chain)->ops, +- afi->nops); ++ err = nf_register_net_hook(net, &nft_base_chain(chain)->ops); + if (err < 0) + goto err; + +@@ -1055,7 +1050,7 @@ static int nf_tables_fill_chain_info(str + + if (nft_is_base_chain(chain)) { + const struct nft_base_chain *basechain = nft_base_chain(chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + struct nlattr *nest; + + nest = nla_nest_start(skb, NFTA_CHAIN_HOOK); +@@ -1283,8 +1278,8 @@ static void nf_tables_chain_destroy(stru + free_percpu(basechain->stats); + if (basechain->stats) + static_branch_dec(&nft_counters_enabled); +- if (basechain->ops[0].dev != NULL) +- dev_put(basechain->ops[0].dev); ++ if (basechain->ops.dev != NULL) ++ dev_put(basechain->ops.dev); + kfree(chain->name); + kfree(basechain); + } else { +@@ -1380,7 +1375,6 @@ static int nf_tables_addchain(struct nft + struct nft_stats __percpu *stats; + struct net *net = ctx->net; + struct nft_chain *chain; +- unsigned int i; + int err; + + if (table->use == UINT_MAX) +@@ -1419,21 +1413,18 @@ static int nf_tables_addchain(struct nft + basechain->type = hook.type; + chain = &basechain->chain; + +- for (i = 0; i < afi->nops; i++) { +- ops = &basechain->ops[i]; +- ops->pf = family; +- ops->hooknum = hook.num; +- ops->priority = hook.priority; +- ops->priv = chain; +- ops->hook = afi->hooks[ops->hooknum]; +- ops->dev = hook.dev; +- if (hookfn) +- ops->hook = hookfn; +- if (afi->hook_ops_init) +- afi->hook_ops_init(ops, i); +- if (basechain->type->type == NFT_CHAIN_T_NAT) +- ops->nat_hook = true; +- } ++ ops = &basechain->ops; ++ ops->pf = family; ++ ops->hooknum = hook.num; ++ ops->priority = hook.priority; ++ ops->priv = chain; ++ ops->hook = afi->hooks[ops->hooknum]; ++ ops->dev = hook.dev; ++ if (hookfn) ++ ops->hook = hookfn; ++ ++ if (basechain->type->type == NFT_CHAIN_T_NAT) ++ ops->nat_hook = true; + + chain->flags |= NFT_BASE_CHAIN; + basechain->policy = policy; +@@ -1451,7 +1442,7 @@ static int nf_tables_addchain(struct nft + goto err1; + } + +- err = nf_tables_register_hooks(net, table, chain, afi->nops); ++ err = nf_tables_register_hook(net, table, chain); + if (err < 0) + goto err1; + +@@ -1465,7 +1456,7 @@ static int nf_tables_addchain(struct nft + + return 0; + err2: +- nf_tables_unregister_hooks(net, table, chain, afi->nops); ++ nf_tables_unregister_hook(net, table, chain); + err1: + nf_tables_chain_destroy(chain); + +@@ -1478,13 +1469,12 @@ static int nf_tables_updchain(struct nft + const struct nlattr * const *nla = ctx->nla; + struct nft_table *table = ctx->table; + struct nft_chain *chain = ctx->chain; +- struct nft_af_info *afi = ctx->afi; + struct nft_base_chain *basechain; + struct nft_stats *stats = NULL; + struct nft_chain_hook hook; + struct nf_hook_ops *ops; + struct nft_trans *trans; +- int err, i; ++ int err; + + if (nla[NFTA_CHAIN_HOOK]) { + if (!nft_is_base_chain(chain)) +@@ -1501,14 +1491,12 @@ static int nf_tables_updchain(struct nft + 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; +- } ++ ops = &basechain->ops; ++ 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); + } +@@ -5135,10 +5123,9 @@ static int nf_tables_commit(struct net * + case NFT_MSG_DELCHAIN: + list_del_rcu(&trans->ctx.chain->list); + nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN); +- nf_tables_unregister_hooks(trans->ctx.net, +- trans->ctx.table, +- trans->ctx.chain, +- trans->ctx.afi->nops); ++ nf_tables_unregister_hook(trans->ctx.net, ++ trans->ctx.table, ++ trans->ctx.chain); + break; + case NFT_MSG_NEWRULE: + nft_clear(trans->ctx.net, nft_trans_rule(trans)); +@@ -5275,10 +5262,9 @@ static int nf_tables_abort(struct net *n + } else { + trans->ctx.table->use--; + list_del_rcu(&trans->ctx.chain->list); +- nf_tables_unregister_hooks(trans->ctx.net, +- trans->ctx.table, +- trans->ctx.chain, +- trans->ctx.afi->nops); ++ nf_tables_unregister_hook(trans->ctx.net, ++ trans->ctx.table, ++ trans->ctx.chain); + } + break; + case NFT_MSG_DELCHAIN: +@@ -5381,7 +5367,7 @@ int nft_chain_validate_hooks(const struc + if (nft_is_base_chain(chain)) { + basechain = nft_base_chain(chain); + +- if ((1 << basechain->ops[0].hooknum) & hook_flags) ++ if ((1 << basechain->ops.hooknum) & hook_flags) + return 0; + + return -EOPNOTSUPP; +@@ -5863,8 +5849,7 @@ int __nft_release_basechain(struct nft_c + + BUG_ON(!nft_is_base_chain(ctx->chain)); + +- nf_tables_unregister_hooks(ctx->net, ctx->chain->table, ctx->chain, +- ctx->afi->nops); ++ nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain); + list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { + list_del(&rule->list); + ctx->chain->use--; +@@ -5893,8 +5878,7 @@ static void __nft_release_afinfo(struct + + list_for_each_entry_safe(table, nt, &afi->tables, list) { + list_for_each_entry(chain, &table->chains, list) +- nf_tables_unregister_hooks(net, table, chain, +- afi->nops); ++ nf_tables_unregister_hook(net, table, chain); + /* No packets are walking on these chains anymore. */ + ctx.table = table; + list_for_each_entry(chain, &table->chains, list) { +--- a/net/netfilter/nf_tables_inet.c ++++ b/net/netfilter/nf_tables_inet.c +@@ -74,7 +74,6 @@ static struct nft_af_info nft_af_inet __ + .family = NFPROTO_INET, + .nhooks = NF_INET_NUMHOOKS, + .owner = THIS_MODULE, +- .nops = 1, + .hooks = { + [NF_INET_LOCAL_IN] = nft_do_chain_inet, + [NF_INET_LOCAL_OUT] = nft_inet_output, +--- a/net/netfilter/nf_tables_netdev.c ++++ b/net/netfilter/nf_tables_netdev.c +@@ -43,7 +43,6 @@ static struct nft_af_info nft_af_netdev + .nhooks = NF_NETDEV_NUMHOOKS, + .owner = THIS_MODULE, + .flags = NFT_AF_NEEDS_DEV, +- .nops = 1, + .hooks = { + [NF_NETDEV_INGRESS] = nft_do_chain_netdev, + }, +@@ -98,7 +97,7 @@ static void nft_netdev_event(unsigned lo + __nft_release_basechain(ctx); + break; + case NETDEV_CHANGENAME: +- if (dev->ifindex != basechain->ops[0].dev->ifindex) ++ if (dev->ifindex != basechain->ops.dev->ifindex) + return; + + strncpy(basechain->dev_name, dev->name, IFNAMSIZ); +--- a/net/netfilter/nft_compat.c ++++ b/net/netfilter/nft_compat.c +@@ -186,7 +186,7 @@ nft_target_set_tgchk_param(struct xt_tgc + if (nft_is_base_chain(ctx->chain)) { + const struct nft_base_chain *basechain = + nft_base_chain(ctx->chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + + par->hook_mask = 1 << ops->hooknum; + } else { +@@ -317,7 +317,7 @@ static int nft_target_validate(const str + if (nft_is_base_chain(ctx->chain)) { + const struct nft_base_chain *basechain = + nft_base_chain(ctx->chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + + hook_mask = 1 << ops->hooknum; + if (target->hooks && !(hook_mask & target->hooks)) +@@ -414,7 +414,7 @@ nft_match_set_mtchk_param(struct xt_mtch + if (nft_is_base_chain(ctx->chain)) { + const struct nft_base_chain *basechain = + nft_base_chain(ctx->chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + + par->hook_mask = 1 << ops->hooknum; + } else { +@@ -564,7 +564,7 @@ static int nft_match_validate(const stru + if (nft_is_base_chain(ctx->chain)) { + const struct nft_base_chain *basechain = + nft_base_chain(ctx->chain); +- const struct nf_hook_ops *ops = &basechain->ops[0]; ++ const struct nf_hook_ops *ops = &basechain->ops; + + hook_mask = 1 << ops->hooknum; + if (match->hooks && !(hook_mask & match->hooks)) |