--- /dev/null
+From 467697d289e7e6e1b15910d99096c0da08c56d5b Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Tue, 20 Mar 2018 15:25:37 +0100
+Subject: netfilter: nf_tables: add missing netlink attrs to policies
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 467697d289e7e6e1b15910d99096c0da08c56d5b upstream.
+
+Fixes: 8aeff920dcc9 ("netfilter: nf_tables: add stateful object reference to set elements")
+Fixes: f25ad2e907f1 ("netfilter: nf_tables: prepare for expressions associated to set elements")
+Fixes: 1a94e38d254b ("netfilter: nf_tables: add NFTA_RULE_ID attribute")
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nf_tables_api.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -1978,6 +1978,7 @@ static const struct nla_policy nft_rule_
+ [NFTA_RULE_POSITION] = { .type = NLA_U64 },
+ [NFTA_RULE_USERDATA] = { .type = NLA_BINARY,
+ .len = NFT_USERDATA_MAXLEN },
++ [NFTA_RULE_ID] = { .type = NLA_U32 },
+ };
+
+ static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
+@@ -3412,6 +3413,8 @@ static const struct nla_policy nft_set_e
+ [NFTA_SET_ELEM_TIMEOUT] = { .type = NLA_U64 },
+ [NFTA_SET_ELEM_USERDATA] = { .type = NLA_BINARY,
+ .len = NFT_USERDATA_MAXLEN },
++ [NFTA_SET_ELEM_EXPR] = { .type = NLA_NESTED },
++ [NFTA_SET_ELEM_OBJREF] = { .type = NLA_STRING },
+ };
+
+ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
--- /dev/null
+From bb7b40aecbf778c0c83a5bd62b0f03ca9f49a618 Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Tue, 8 May 2018 02:43:57 +0200
+Subject: netfilter: nf_tables: bogus EBUSY in chain deletions
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit bb7b40aecbf778c0c83a5bd62b0f03ca9f49a618 upstream.
+
+When removing a rule that jumps to chain and such chain in the same
+batch, this bogusly hits EBUSY. Add activate and deactivate operations
+to expression that can be called from the preparation and the
+commit/abort phases.
+
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/netfilter/nf_tables.h | 5 ++++
+ net/netfilter/nf_tables_api.c | 46 ++++++++++++++++++++++++++++++++++----
+ net/netfilter/nft_immediate.c | 15 +++++++++---
+ 3 files changed, 59 insertions(+), 7 deletions(-)
+
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -177,6 +177,7 @@ struct nft_data_desc {
+ int nft_data_init(const struct nft_ctx *ctx,
+ struct nft_data *data, unsigned int size,
+ struct nft_data_desc *desc, const struct nlattr *nla);
++void nft_data_hold(const struct nft_data *data, enum nft_data_types type);
+ void nft_data_release(const struct nft_data *data, enum nft_data_types type);
+ int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
+ enum nft_data_types type, unsigned int len);
+@@ -731,6 +732,10 @@ struct nft_expr_ops {
+ int (*init)(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[]);
++ void (*activate)(const struct nft_ctx *ctx,
++ const struct nft_expr *expr);
++ void (*deactivate)(const struct nft_ctx *ctx,
++ const struct nft_expr *expr);
+ void (*destroy)(const struct nft_ctx *ctx,
+ const struct nft_expr *expr);
+ int (*dump)(struct sk_buff *skb,
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -220,6 +220,34 @@ static int nft_delchain(struct nft_ctx *
+ return err;
+ }
+
++static void nft_rule_expr_activate(const struct nft_ctx *ctx,
++ struct nft_rule *rule)
++{
++ struct nft_expr *expr;
++
++ expr = nft_expr_first(rule);
++ while (expr != nft_expr_last(rule) && expr->ops) {
++ if (expr->ops->activate)
++ expr->ops->activate(ctx, expr);
++
++ expr = nft_expr_next(expr);
++ }
++}
++
++static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
++ struct nft_rule *rule)
++{
++ struct nft_expr *expr;
++
++ expr = nft_expr_first(rule);
++ while (expr != nft_expr_last(rule) && expr->ops) {
++ if (expr->ops->deactivate)
++ expr->ops->deactivate(ctx, expr);
++
++ expr = nft_expr_next(expr);
++ }
++}
++
+ static int
+ nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
+ {
+@@ -265,6 +293,7 @@ static int nft_delrule(struct nft_ctx *c
+ nft_trans_destroy(trans);
+ return err;
+ }
++ nft_rule_expr_deactivate(ctx, rule);
+
+ return 0;
+ }
+@@ -2218,6 +2247,13 @@ static void nf_tables_rule_destroy(const
+ kfree(rule);
+ }
+
++static void nf_tables_rule_release(const struct nft_ctx *ctx,
++ struct nft_rule *rule)
++{
++ nft_rule_expr_deactivate(ctx, rule);
++ nf_tables_rule_destroy(ctx, rule);
++}
++
+ #define NFT_RULE_MAXEXPRS 128
+
+ static struct nft_expr_info *info;
+@@ -2385,7 +2421,7 @@ static int nf_tables_newrule(struct net
+ return 0;
+
+ err2:
+- nf_tables_rule_destroy(&ctx, rule);
++ nf_tables_rule_release(&ctx, rule);
+ err1:
+ for (i = 0; i < n; i++) {
+ if (info[i].ops != NULL)
+@@ -4054,7 +4090,7 @@ static int nf_tables_newsetelem(struct n
+ * NFT_GOTO verdicts. This function must be called on active data objects
+ * from the second phase of the commit protocol.
+ */
+-static void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
++void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
+ {
+ if (type == NFT_DATA_VERDICT) {
+ switch (data->verdict.code) {
+@@ -5221,10 +5257,12 @@ static int nf_tables_abort(struct net *n
+ case NFT_MSG_NEWRULE:
+ trans->ctx.chain->use--;
+ list_del_rcu(&nft_trans_rule(trans)->list);
++ nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans));
+ break;
+ case NFT_MSG_DELRULE:
+ trans->ctx.chain->use++;
+ nft_clear(trans->ctx.net, nft_trans_rule(trans));
++ nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
+ nft_trans_destroy(trans);
+ break;
+ case NFT_MSG_NEWSET:
+@@ -5798,7 +5836,7 @@ int __nft_release_basechain(struct nft_c
+ list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
+ list_del(&rule->list);
+ ctx->chain->use--;
+- nf_tables_rule_destroy(ctx, rule);
++ nf_tables_rule_release(ctx, rule);
+ }
+ list_del(&ctx->chain->list);
+ ctx->table->use--;
+@@ -5832,7 +5870,7 @@ static void __nft_release_afinfo(struct
+ list_for_each_entry_safe(rule, nr, &chain->rules, list) {
+ list_del(&rule->list);
+ chain->use--;
+- nf_tables_rule_destroy(&ctx, rule);
++ nf_tables_rule_release(&ctx, rule);
+ }
+ }
+ list_for_each_entry_safe(set, ns, &table->sets, list) {
+--- a/net/netfilter/nft_immediate.c
++++ b/net/netfilter/nft_immediate.c
+@@ -69,8 +69,16 @@ err1:
+ return err;
+ }
+
+-static void nft_immediate_destroy(const struct nft_ctx *ctx,
+- const struct nft_expr *expr)
++static void nft_immediate_activate(const struct nft_ctx *ctx,
++ const struct nft_expr *expr)
++{
++ const struct nft_immediate_expr *priv = nft_expr_priv(expr);
++
++ return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
++}
++
++static void nft_immediate_deactivate(const struct nft_ctx *ctx,
++ const struct nft_expr *expr)
+ {
+ const struct nft_immediate_expr *priv = nft_expr_priv(expr);
+
+@@ -108,7 +116,8 @@ static const struct nft_expr_ops nft_imm
+ .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),
+ .eval = nft_immediate_eval,
+ .init = nft_immediate_init,
+- .destroy = nft_immediate_destroy,
++ .activate = nft_immediate_activate,
++ .deactivate = nft_immediate_deactivate,
+ .dump = nft_immediate_dump,
+ .validate = nft_immediate_validate,
+ };
--- /dev/null
+From ad9d9e85072b668731f356be0a3750a3ba22a607 Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Sun, 27 May 2018 21:08:13 +0200
+Subject: netfilter: nf_tables: disable preemption in nft_update_chain_stats()
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+commit ad9d9e85072b668731f356be0a3750a3ba22a607 upstream.
+
+This patch fixes the following splat.
+
+[118709.054937] BUG: using smp_processor_id() in preemptible [00000000] code: test/1571
+[118709.054970] caller is nft_update_chain_stats.isra.4+0x53/0x97 [nf_tables]
+[118709.054980] CPU: 2 PID: 1571 Comm: test Not tainted 4.17.0-rc6+ #335
+[...]
+[118709.054992] Call Trace:
+[118709.055011] dump_stack+0x5f/0x86
+[118709.055026] check_preemption_disabled+0xd4/0xe4
+
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nf_tables_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/netfilter/nf_tables_core.c
++++ b/net/netfilter/nf_tables_core.c
+@@ -126,15 +126,15 @@ static noinline void nft_update_chain_st
+ if (!base_chain->stats)
+ return;
+
++ local_bh_disable();
+ stats = this_cpu_ptr(rcu_dereference(base_chain->stats));
+ if (stats) {
+- local_bh_disable();
+ u64_stats_update_begin(&stats->syncp);
+ stats->pkts++;
+ stats->bytes += pkt->skb->len;
+ u64_stats_update_end(&stats->syncp);
+- local_bh_enable();
+ }
++ local_bh_enable();
+ }
+
+ struct nft_jumpstack {
--- /dev/null
+From 009240940e84c1c089af88b454f7e804a4c5bd1b Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Sun, 6 May 2018 00:47:20 +0200
+Subject: netfilter: nf_tables: don't assume chain stats are set when jumplabel is set
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 009240940e84c1c089af88b454f7e804a4c5bd1b upstream.
+
+nft_chain_stats_replace() and all other spots assume ->stats can be
+NULL, but nft_update_chain_stats does not. It must do this check,
+just because the jump label is set doesn't mean all basechains have stats
+assigned.
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nf_tables_core.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+--- a/net/netfilter/nf_tables_core.c
++++ b/net/netfilter/nf_tables_core.c
+@@ -119,15 +119,22 @@ DEFINE_STATIC_KEY_FALSE(nft_counters_ena
+ static noinline void nft_update_chain_stats(const struct nft_chain *chain,
+ const struct nft_pktinfo *pkt)
+ {
++ struct nft_base_chain *base_chain;
+ struct nft_stats *stats;
+
+- local_bh_disable();
+- stats = this_cpu_ptr(rcu_dereference(nft_base_chain(chain)->stats));
+- u64_stats_update_begin(&stats->syncp);
+- stats->pkts++;
+- stats->bytes += pkt->skb->len;
+- u64_stats_update_end(&stats->syncp);
+- local_bh_enable();
++ base_chain = nft_base_chain(chain);
++ if (!base_chain->stats)
++ return;
++
++ stats = this_cpu_ptr(rcu_dereference(base_chain->stats));
++ if (stats) {
++ local_bh_disable();
++ u64_stats_update_begin(&stats->syncp);
++ stats->pkts++;
++ stats->bytes += pkt->skb->len;
++ u64_stats_update_end(&stats->syncp);
++ local_bh_enable();
++ }
+ }
+
+ struct nft_jumpstack {
--- /dev/null
+From f0dfd7a2b35b02030949100247d851b793cb275f Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Wed, 9 May 2018 13:22:56 +0100
+Subject: netfilter: nf_tables: fix memory leak on error exit return
+
+From: Colin Ian King <colin.king@canonical.com>
+
+commit f0dfd7a2b35b02030949100247d851b793cb275f upstream.
+
+Currently the -EBUSY error return path is not free'ing resources
+allocated earlier, leaving a memory leak. Fix this by exiting via the
+error exit label err5 that performs the necessary resource clean
+up.
+
+Detected by CoverityScan, CID#1432975 ("Resource leak")
+
+Fixes: 9744a6fcefcb ("netfilter: nf_tables: check if same extensions are set when adding elements")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nf_tables_api.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -3999,8 +3999,10 @@ static int nft_add_set_elem(struct nft_c
+ if (nft_set_ext_exists(ext, 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(ext2, NFT_SET_EXT_OBJREF))
+- return -EBUSY;
++ nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF)) {
++ err = -EBUSY;
++ goto err5;
++ }
+ if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
+ nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
+ memcmp(nft_set_ext_data(ext),
--- /dev/null
+From bbb8c61f97e3a2dd91b30d3e57b7964a67569d11 Mon Sep 17 00:00:00 2001
+From: Taehee Yoo <ap420073@gmail.com>
+Date: Tue, 29 May 2018 01:14:12 +0900
+Subject: netfilter: nf_tables: increase nft_counters_enabled in nft_chain_stats_replace()
+
+From: Taehee Yoo <ap420073@gmail.com>
+
+commit bbb8c61f97e3a2dd91b30d3e57b7964a67569d11 upstream.
+
+When a chain is updated, a counter can be attached. if so,
+the nft_counters_enabled should be increased.
+
+test commands:
+
+ %nft add table ip filter
+ %nft add chain ip filter input { type filter hook input priority 4\; }
+ %iptables-compat -Z input
+ %nft delete chain ip filter input
+
+we can see below messages.
+
+[ 286.443720] jump label: negative count!
+[ 286.448278] WARNING: CPU: 0 PID: 1459 at kernel/jump_label.c:197 __static_key_slow_dec_cpuslocked+0x6f/0xf0
+[ 286.449144] Modules linked in: nf_tables nfnetlink ip_tables x_tables
+[ 286.449144] CPU: 0 PID: 1459 Comm: nft Tainted: G W 4.17.0-rc2+ #12
+[ 286.449144] RIP: 0010:__static_key_slow_dec_cpuslocked+0x6f/0xf0
+[ 286.449144] RSP: 0018:ffff88010e5176f0 EFLAGS: 00010286
+[ 286.449144] RAX: 000000000000001b RBX: ffffffffc0179500 RCX: ffffffffb8a82522
+[ 286.449144] RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffff88011b7e5eac
+[ 286.449144] RBP: 0000000000000000 R08: ffffed00236fce5c R09: ffffed00236fce5b
+[ 286.449144] R10: ffffffffc0179503 R11: ffffed00236fce5c R12: 0000000000000000
+[ 286.449144] R13: ffff88011a28e448 R14: ffff88011a28e470 R15: dffffc0000000000
+[ 286.449144] FS: 00007f0384328700(0000) GS:ffff88011b600000(0000) knlGS:0000000000000000
+[ 286.449144] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 286.449144] CR2: 00007f038394bf10 CR3: 0000000104a86000 CR4: 00000000001006f0
+[ 286.449144] Call Trace:
+[ 286.449144] static_key_slow_dec+0x6a/0x70
+[ 286.449144] nf_tables_chain_destroy+0x19d/0x210 [nf_tables]
+[ 286.449144] nf_tables_commit+0x1891/0x1c50 [nf_tables]
+[ 286.449144] nfnetlink_rcv+0x1148/0x13d0 [nfnetlink]
+[ ... ]
+
+Signed-off-by: Taehee Yoo <ap420073@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nf_tables_api.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -1266,8 +1266,10 @@ static void nft_chain_stats_replace(stru
+ rcu_assign_pointer(chain->stats, newstats);
+ synchronize_rcu();
+ free_percpu(oldstats);
+- } else
++ } else {
+ rcu_assign_pointer(chain->stats, newstats);
++ static_branch_inc(&nft_counters_enabled);
++ }
+ }
+
+ static void nf_tables_chain_destroy(struct nft_chain *chain)
--- /dev/null
+From b8e9dc1c75714ceb53615743e1036f76e00f5a17 Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Wed, 2 May 2018 14:07:42 +0200
+Subject: netfilter: nf_tables: nft_compat: fix refcount leak on xt module
+
+From: Florian Westphal <fw@strlen.de>
+
+commit b8e9dc1c75714ceb53615743e1036f76e00f5a17 upstream.
+
+Taehee Yoo reported following bug:
+ iptables-compat -I OUTPUT -m cpu --cpu 0
+ iptables-compat -F
+ lsmod |grep xt_cpu
+ xt_cpu 16384 1
+
+Quote:
+"When above command is given, a netlink message has two expressions that
+are the cpu compat and the nft_counter.
+The nft_expr_type_get() in the nf_tables_expr_parse() successes
+first expression then, calls select_ops callback.
+(allocates memory and holds module)
+But, second nft_expr_type_get() in the nf_tables_expr_parse()
+returns -EAGAIN because of request_module().
+In that point, by the 'goto err1',
+the 'module_put(info[i].ops->type->owner)' is called.
+There is no release routine."
+
+The core problem is that unlike all other expression,
+nft_compat select_ops has side effects.
+
+1. it allocates dynamic memory which holds an nft ops struct.
+ In all other expressions, ops has static storage duration.
+2. It grabs references to the xt module that it is supposed to
+ invoke.
+
+Depending on where things go wrong, error unwinding doesn't
+always do the right thing.
+
+In the above scenario, a new nft_compat_expr is created and
+xt_cpu module gets loaded with a refcount of 1.
+
+Due to to -EAGAIN, the netlink messages get re-parsed.
+When that happens, nft_compat finds that xt_cpu is already present
+and increments module refcount again.
+
+This fixes the problem by making select_ops to have no visible
+side effects and removes all extra module_get/put.
+
+When select_ops creates a new nft_compat expression, the new
+expression has a refcount of 0, and the xt module gets its refcount
+incremented.
+
+When error happens, the next call finds existing entry, but will no
+longer increase the reference count -- the presence of existing
+nft_xt means we already hold a module reference.
+
+Because nft_xt_put is only called from nft_compat destroy hook,
+it will never see the initial zero reference count.
+->destroy can only be called after ->init(), and that will increase the
+refcount.
+
+Lastly, we now free nft_xt struct with kfree_rcu.
+Else, we get use-after free in nf_tables_rule_destroy:
+
+ while (expr != nft_expr_last(rule) && expr->ops) {
+ nf_tables_expr_destroy(ctx, expr);
+ expr = nft_expr_next(expr); // here
+
+nft_expr_next() dereferences expr->ops. This is safe
+for all users, as ops have static storage duration.
+In nft_compat case however, its ->destroy callback can
+free the memory that hold the ops structure.
+
+Tested-by: Taehee Yoo <ap420073@gmail.com>
+Reported-by: Taehee Yoo <ap420073@gmail.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nft_compat.c | 92 ++++++++++++++++++++++++++++-----------------
+ 1 file changed, 58 insertions(+), 34 deletions(-)
+
+--- a/net/netfilter/nft_compat.c
++++ b/net/netfilter/nft_compat.c
+@@ -27,14 +27,24 @@ struct nft_xt {
+ struct list_head head;
+ struct nft_expr_ops ops;
+ unsigned int refcnt;
++
++ /* Unlike other expressions, ops doesn't have static storage duration.
++ * nft core assumes they do. We use kfree_rcu so that nft core can
++ * can check expr->ops->size even after nft_compat->destroy() frees
++ * the nft_xt struct that holds the ops structure.
++ */
++ struct rcu_head rcu_head;
+ };
+
+-static void nft_xt_put(struct nft_xt *xt)
++static bool nft_xt_put(struct nft_xt *xt)
+ {
+ if (--xt->refcnt == 0) {
+ list_del(&xt->head);
+- kfree(xt);
++ kfree_rcu(xt, rcu_head);
++ return true;
+ }
++
++ return false;
+ }
+
+ static int nft_compat_chain_validate_dependency(const char *tablename,
+@@ -226,6 +236,7 @@ nft_target_init(const struct nft_ctx *ct
+ struct xt_target *target = expr->ops->data;
+ struct xt_tgchk_param par;
+ size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO]));
++ struct nft_xt *nft_xt;
+ u16 proto = 0;
+ bool inv = false;
+ union nft_entry e = {};
+@@ -236,25 +247,22 @@ nft_target_init(const struct nft_ctx *ct
+ if (ctx->nla[NFTA_RULE_COMPAT]) {
+ ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
+ if (ret < 0)
+- goto err;
++ return ret;
+ }
+
+ nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
+
+ ret = xt_check_target(&par, size, proto, inv);
+ if (ret < 0)
+- goto err;
++ return ret;
+
+ /* The standard target cannot be used */
+- if (target->target == NULL) {
+- ret = -EINVAL;
+- goto err;
+- }
++ if (!target->target)
++ return -EINVAL;
+
++ nft_xt = container_of(expr->ops, struct nft_xt, ops);
++ nft_xt->refcnt++;
+ return 0;
+-err:
+- module_put(target->me);
+- return ret;
+ }
+
+ static void
+@@ -271,8 +279,8 @@ nft_target_destroy(const struct nft_ctx
+ if (par.target->destroy != NULL)
+ par.target->destroy(&par);
+
+- nft_xt_put(container_of(expr->ops, struct nft_xt, ops));
+- module_put(target->me);
++ if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
++ module_put(target->me);
+ }
+
+ static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
+@@ -411,6 +419,7 @@ nft_match_init(const struct nft_ctx *ctx
+ struct xt_match *match = expr->ops->data;
+ struct xt_mtchk_param par;
+ size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO]));
++ struct nft_xt *nft_xt;
+ u16 proto = 0;
+ bool inv = false;
+ union nft_entry e = {};
+@@ -421,19 +430,18 @@ nft_match_init(const struct nft_ctx *ctx
+ if (ctx->nla[NFTA_RULE_COMPAT]) {
+ ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
+ if (ret < 0)
+- goto err;
++ return ret;
+ }
+
+ nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
+
+ ret = xt_check_match(&par, size, proto, inv);
+ if (ret < 0)
+- goto err;
++ return ret;
+
++ nft_xt = container_of(expr->ops, struct nft_xt, ops);
++ nft_xt->refcnt++;
+ return 0;
+-err:
+- module_put(match->me);
+- return ret;
+ }
+
+ static void
+@@ -450,8 +458,8 @@ nft_match_destroy(const struct nft_ctx *
+ if (par.match->destroy != NULL)
+ par.match->destroy(&par);
+
+- nft_xt_put(container_of(expr->ops, struct nft_xt, ops));
+- module_put(match->me);
++ if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
++ module_put(match->me);
+ }
+
+ static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
+@@ -654,13 +662,8 @@ nft_match_select_ops(const struct nft_ct
+ list_for_each_entry(nft_match, &nft_match_list, head) {
+ struct xt_match *match = nft_match->ops.data;
+
+- if (nft_match_cmp(match, mt_name, rev, family)) {
+- if (!try_module_get(match->me))
+- return ERR_PTR(-ENOENT);
+-
+- nft_match->refcnt++;
++ if (nft_match_cmp(match, mt_name, rev, family))
+ return &nft_match->ops;
+- }
+ }
+
+ match = xt_request_find_match(family, mt_name, rev);
+@@ -679,7 +682,7 @@ nft_match_select_ops(const struct nft_ct
+ goto err;
+ }
+
+- nft_match->refcnt = 1;
++ nft_match->refcnt = 0;
+ nft_match->ops.type = &nft_match_type;
+ nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
+ nft_match->ops.eval = nft_match_eval;
+@@ -739,13 +742,8 @@ nft_target_select_ops(const struct nft_c
+ list_for_each_entry(nft_target, &nft_target_list, head) {
+ struct xt_target *target = nft_target->ops.data;
+
+- if (nft_target_cmp(target, tg_name, rev, family)) {
+- if (!try_module_get(target->me))
+- return ERR_PTR(-ENOENT);
+-
+- nft_target->refcnt++;
++ if (nft_target_cmp(target, tg_name, rev, family))
+ return &nft_target->ops;
+- }
+ }
+
+ target = xt_request_find_target(family, tg_name, rev);
+@@ -764,7 +762,7 @@ nft_target_select_ops(const struct nft_c
+ goto err;
+ }
+
+- nft_target->refcnt = 1;
++ nft_target->refcnt = 0;
+ nft_target->ops.type = &nft_target_type;
+ nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
+ nft_target->ops.init = nft_target_init;
+@@ -825,6 +823,32 @@ err_match:
+
+ static void __exit nft_compat_module_exit(void)
+ {
++ struct nft_xt *xt, *next;
++
++ /* list should be empty here, it can be non-empty only in case there
++ * was an error that caused nft_xt expr to not be initialized fully
++ * and noone else requested the same expression later.
++ *
++ * In this case, the lists contain 0-refcount entries that still
++ * hold module reference.
++ */
++ list_for_each_entry_safe(xt, next, &nft_target_list, head) {
++ struct xt_target *target = xt->ops.data;
++
++ if (WARN_ON_ONCE(xt->refcnt))
++ continue;
++ module_put(target->me);
++ kfree(xt);
++ }
++
++ list_for_each_entry_safe(xt, next, &nft_match_list, head) {
++ struct xt_match *match = xt->ops.data;
++
++ if (WARN_ON_ONCE(xt->refcnt))
++ continue;
++ module_put(match->me);
++ kfree(xt);
++ }
+ nfnetlink_subsys_unregister(&nfnl_compat_subsys);
+ nft_unregister_expr(&nft_target_type);
+ nft_unregister_expr(&nft_match_type);
--- /dev/null
+From 732a8049f365f514d0607e03938491bf6cb0d620 Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Mon, 7 May 2018 15:22:36 +0200
+Subject: netfilter: nft_compat: fix handling of large matchinfo size
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 732a8049f365f514d0607e03938491bf6cb0d620 upstream.
+
+currently matchinfo gets stored in the expression, but some xt matches
+are very large.
+
+To handle those we either need to switch nft core to kvmalloc and increase
+size limit, or allocate the info blob of large matches separately.
+
+This does the latter, this limits the scope of the changes to
+nft_compat.
+
+I picked a threshold of 192, this allows most matches to work as before and
+handle only few ones via separate alloation (cgroup, u32, sctp, rt).
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nft_compat.c | 64 ++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 63 insertions(+), 1 deletion(-)
+
+--- a/net/netfilter/nft_compat.c
++++ b/net/netfilter/nft_compat.c
+@@ -36,6 +36,13 @@ struct nft_xt {
+ struct rcu_head rcu_head;
+ };
+
++/* Used for matches where *info is larger than X byte */
++#define NFT_MATCH_LARGE_THRESH 192
++
++struct nft_xt_match_priv {
++ void *info;
++};
++
+ static bool nft_xt_put(struct nft_xt *xt)
+ {
+ if (--xt->refcnt == 0) {
+@@ -352,6 +359,15 @@ static void __nft_match_eval(const struc
+ }
+ }
+
++static void nft_match_large_eval(const struct nft_expr *expr,
++ struct nft_regs *regs,
++ const struct nft_pktinfo *pkt)
++{
++ struct nft_xt_match_priv *priv = nft_expr_priv(expr);
++
++ __nft_match_eval(expr, regs, pkt, priv->info);
++}
++
+ static void nft_match_eval(const struct nft_expr *expr,
+ struct nft_regs *regs,
+ const struct nft_pktinfo *pkt)
+@@ -458,6 +474,24 @@ nft_match_init(const struct nft_ctx *ctx
+ return __nft_match_init(ctx, expr, tb, nft_expr_priv(expr));
+ }
+
++static int
++nft_match_large_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
++ const struct nlattr * const tb[])
++{
++ struct nft_xt_match_priv *priv = nft_expr_priv(expr);
++ struct xt_match *m = expr->ops->data;
++ int ret;
++
++ priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL);
++ if (!priv->info)
++ return -ENOMEM;
++
++ ret = __nft_match_init(ctx, expr, tb, priv->info);
++ if (ret)
++ kfree(priv->info);
++ return ret;
++}
++
+ static void
+ __nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr,
+ void *info)
+@@ -482,6 +516,15 @@ nft_match_destroy(const struct nft_ctx *
+ __nft_match_destroy(ctx, expr, nft_expr_priv(expr));
+ }
+
++static void
++nft_match_large_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
++{
++ struct nft_xt_match_priv *priv = nft_expr_priv(expr);
++
++ __nft_match_destroy(ctx, expr, priv->info);
++ kfree(priv->info);
++}
++
+ static int __nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr,
+ void *info)
+ {
+@@ -503,6 +546,13 @@ static int nft_match_dump(struct sk_buff
+ return __nft_match_dump(skb, expr, nft_expr_priv(expr));
+ }
+
++static int nft_match_large_dump(struct sk_buff *skb, const struct nft_expr *e)
++{
++ struct nft_xt_match_priv *priv = nft_expr_priv(e);
++
++ return __nft_match_dump(skb, e, priv->info);
++}
++
+ static int nft_match_validate(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nft_data **data)
+@@ -670,6 +720,7 @@ nft_match_select_ops(const struct nft_ct
+ {
+ struct nft_xt *nft_match;
+ struct xt_match *match;
++ unsigned int matchsize;
+ char *mt_name;
+ u32 rev, family;
+ int err;
+@@ -709,7 +760,6 @@ nft_match_select_ops(const struct nft_ct
+
+ nft_match->refcnt = 0;
+ nft_match->ops.type = &nft_match_type;
+- nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
+ nft_match->ops.eval = nft_match_eval;
+ nft_match->ops.init = nft_match_init;
+ nft_match->ops.destroy = nft_match_destroy;
+@@ -717,6 +767,18 @@ nft_match_select_ops(const struct nft_ct
+ nft_match->ops.validate = nft_match_validate;
+ nft_match->ops.data = match;
+
++ matchsize = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
++ if (matchsize > NFT_MATCH_LARGE_THRESH) {
++ matchsize = NFT_EXPR_SIZE(sizeof(struct nft_xt_match_priv));
++
++ nft_match->ops.eval = nft_match_large_eval;
++ nft_match->ops.init = nft_match_large_init;
++ nft_match->ops.destroy = nft_match_large_destroy;
++ nft_match->ops.dump = nft_match_large_dump;
++ }
++
++ nft_match->ops.size = matchsize;
++
+ list_add(&nft_match->head, &nft_match_list);
+
+ return &nft_match->ops;
--- /dev/null
+From 8bdf164744b2c7f63561846c01cff3db597f282d Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Mon, 7 May 2018 15:22:35 +0200
+Subject: netfilter: nft_compat: prepare for indirect info storage
+
+From: Florian Westphal <fw@strlen.de>
+
+commit 8bdf164744b2c7f63561846c01cff3db597f282d upstream.
+
+Next patch will make it possible for *info to be stored in
+a separate allocation instead of the expr private area.
+
+This removes the 'expr priv area is info blob' assumption
+from the match init/destroy/eval functions.
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nft_compat.c | 47 ++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 36 insertions(+), 11 deletions(-)
+
+--- a/net/netfilter/nft_compat.c
++++ b/net/netfilter/nft_compat.c
+@@ -324,11 +324,11 @@ static int nft_target_validate(const str
+ return 0;
+ }
+
+-static void nft_match_eval(const struct nft_expr *expr,
+- struct nft_regs *regs,
+- const struct nft_pktinfo *pkt)
++static void __nft_match_eval(const struct nft_expr *expr,
++ struct nft_regs *regs,
++ const struct nft_pktinfo *pkt,
++ void *info)
+ {
+- void *info = nft_expr_priv(expr);
+ struct xt_match *match = expr->ops->data;
+ struct sk_buff *skb = pkt->skb;
+ bool ret;
+@@ -352,6 +352,13 @@ static void nft_match_eval(const struct
+ }
+ }
+
++static void nft_match_eval(const struct nft_expr *expr,
++ struct nft_regs *regs,
++ const struct nft_pktinfo *pkt)
++{
++ __nft_match_eval(expr, regs, pkt, nft_expr_priv(expr));
++}
++
+ static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = {
+ [NFTA_MATCH_NAME] = { .type = NLA_NUL_STRING },
+ [NFTA_MATCH_REV] = { .type = NLA_U32 },
+@@ -412,10 +419,10 @@ static void match_compat_from_user(struc
+ }
+
+ static int
+-nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
+- const struct nlattr * const tb[])
++__nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
++ const struct nlattr * const tb[],
++ void *info)
+ {
+- void *info = nft_expr_priv(expr);
+ struct xt_match *match = expr->ops->data;
+ struct xt_mtchk_param par;
+ size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO]));
+@@ -444,11 +451,18 @@ nft_match_init(const struct nft_ctx *ctx
+ return 0;
+ }
+
++static int
++nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
++ const struct nlattr * const tb[])
++{
++ return __nft_match_init(ctx, expr, tb, nft_expr_priv(expr));
++}
++
+ static void
+-nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
++__nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr,
++ void *info)
+ {
+ struct xt_match *match = expr->ops->data;
+- void *info = nft_expr_priv(expr);
+ struct xt_mtdtor_param par;
+
+ par.net = ctx->net;
+@@ -462,9 +476,15 @@ nft_match_destroy(const struct nft_ctx *
+ module_put(match->me);
+ }
+
+-static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
++static void
++nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
++{
++ __nft_match_destroy(ctx, expr, nft_expr_priv(expr));
++}
++
++static int __nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr,
++ void *info)
+ {
+- void *info = nft_expr_priv(expr);
+ struct xt_match *match = expr->ops->data;
+
+ if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) ||
+@@ -478,6 +498,11 @@ nla_put_failure:
+ return -1;
+ }
+
++static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
++{
++ return __nft_match_dump(skb, expr, nft_expr_priv(expr));
++}
++
+ static int nft_match_validate(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nft_data **data)
--- /dev/null
+From 97a0549b15a0b466c47f6a0143a490a082c64b4e Mon Sep 17 00:00:00 2001
+From: Taehee Yoo <ap420073@gmail.com>
+Date: Thu, 17 May 2018 22:49:49 +0900
+Subject: netfilter: nft_meta: fix wrong value dereference in nft_meta_set_eval
+
+From: Taehee Yoo <ap420073@gmail.com>
+
+commit 97a0549b15a0b466c47f6a0143a490a082c64b4e upstream.
+
+In the nft_meta_set_eval, nftrace value is dereferenced as u32 from sreg.
+But correct type is u8. so that sometimes incorrect value is dereferenced.
+
+Steps to reproduce:
+
+ %nft add table ip filter
+ %nft add chain ip filter input { type filter hook input priority 4\; }
+ %nft add rule ip filter input nftrace set 0
+ %nft monitor
+
+Sometimes, we can see trace messages.
+
+ trace id 16767227 ip filter input packet: iif "enp2s0"
+ ether saddr xx:xx:xx:xx:xx:xx ether daddr xx:xx:xx:xx:xx:xx
+ ip saddr 192.168.0.1 ip daddr 255.255.255.255 ip dscp cs0
+ ip ecn not-ect ip
+ trace id 16767227 ip filter input rule nftrace set 0 (verdict continue)
+ trace id 16767227 ip filter input verdict continue
+ trace id 16767227 ip filter input
+
+Signed-off-by: Taehee Yoo <ap420073@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nft_meta.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/net/netfilter/nft_meta.c
++++ b/net/netfilter/nft_meta.c
+@@ -229,7 +229,7 @@ void nft_meta_set_eval(const struct nft_
+ struct sk_buff *skb = pkt->skb;
+ u32 *sreg = ®s->data[meta->sreg];
+ u32 value = *sreg;
+- u8 pkt_type;
++ u8 value8;
+
+ switch (meta->key) {
+ case NFT_META_MARK:
+@@ -239,15 +239,17 @@ void nft_meta_set_eval(const struct nft_
+ skb->priority = value;
+ break;
+ case NFT_META_PKTTYPE:
+- pkt_type = nft_reg_load8(sreg);
++ value8 = nft_reg_load8(sreg);
+
+- if (skb->pkt_type != pkt_type &&
+- skb_pkt_type_ok(pkt_type) &&
++ if (skb->pkt_type != value8 &&
++ skb_pkt_type_ok(value8) &&
+ skb_pkt_type_ok(skb->pkt_type))
+- skb->pkt_type = pkt_type;
++ skb->pkt_type = value8;
+ break;
+ case NFT_META_NFTRACE:
+- skb->nf_trace = !!value;
++ value8 = nft_reg_load8(sreg);
++
++ skb->nf_trace = !!value8;
+ break;
+ default:
+ WARN_ON(1);
drm-amdgpu-refactor-amdgpu_vram_mgr_bo_invisible_size-helper.patch
drm-amdgpu-make-amdgpu_vram_mgr_bo_invisible_size-always-accurate.patch
drm-i915-enable-provoking-vertex-fix-on-gen9-systems.patch
+netfilter-nf_tables-nft_compat-fix-refcount-leak-on-xt-module.patch
+netfilter-nft_compat-prepare-for-indirect-info-storage.patch
+netfilter-nft_compat-fix-handling-of-large-matchinfo-size.patch
+netfilter-nf_tables-don-t-assume-chain-stats-are-set-when-jumplabel-is-set.patch
+netfilter-nf_tables-bogus-ebusy-in-chain-deletions.patch
+netfilter-nft_meta-fix-wrong-value-dereference-in-nft_meta_set_eval.patch
+netfilter-nf_tables-disable-preemption-in-nft_update_chain_stats.patch
+netfilter-nf_tables-increase-nft_counters_enabled-in-nft_chain_stats_replace.patch
+netfilter-nf_tables-fix-memory-leak-on-error-exit-return.patch
+netfilter-nf_tables-add-missing-netlink-attrs-to-policies.patch