aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-4.19/303-v4.16-netfilter-nf_tables-remove-multihook-chains-and-fami.patch
diff options
context:
space:
mode:
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.patch390
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))