aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-05-13 20:28:47 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-13 20:28:47 -0400
commit4f6b15c3a604c0addf1607c5482c46a0a5123066 (patch)
tree4d47d8780be641a240e28cff56f702b40c384f91
parent91dfd02b23006e7cc557bcb3a40aeb740f66fb52 (diff)
parentf0dfd7a2b35b02030949100247d851b793cb275f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter/IPVS fixes for net The following patchset contains Netfilter/IPVS fixes for your net tree, they are: 1) Fix handling of simultaneous open TCP connection in conntrack, from Jozsef Kadlecsik. 2) Insufficient sanitify check of xtables extension names, from Florian Westphal. 3) Skip unnecessary synchronize_rcu() call when transaction log is already empty, from Florian Westphal. 4) Incorrect destination mac validation in ebt_stp, from Stephen Hemminger. 5) xtables module reference counter leak in nft_compat, from Florian Westphal. 6) Incorrect connection reference counting logic in IPVS one-packet scheduler, from Julian Anastasov. 7) Wrong stats for 32-bits CPU in IPVS, also from Julian. 8) Calm down sparse error in netfilter core, also from Florian. 9) Use nla_strlcpy to fix compilation warning in nfnetlink_acct and nfnetlink_cthelper, again from Florian. 10) Missing module alias in icmp and icmp6 xtables extensions, from Florian Westphal. 11) Base chain statistics in nf_tables may be unset/null, from Florian. 12) Fix handling of large matchinfo size in nft_compat, this includes one preparation for before this fix. From Florian. 13) Fix bogus EBUSY error when deleting chains due to incorrect reference counting from the preparation phase of the two-phase commit protocol. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/netfilter/nf_tables.h5
-rw-r--r--include/uapi/linux/netfilter/nf_conntrack_tcp.h3
-rw-r--r--net/bridge/netfilter/ebt_stp.c4
-rw-r--r--net/ipv4/netfilter/ip_tables.c1
-rw-r--r--net/ipv6/netfilter/ip6_tables.c1
-rw-r--r--net/netfilter/core.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c17
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c12
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c11
-rw-r--r--net/netfilter/nf_tables_api.c77
-rw-r--r--net/netfilter/nf_tables_core.c21
-rw-r--r--net/netfilter/nfnetlink_acct.c2
-rw-r--r--net/netfilter/nfnetlink_cthelper.c7
-rw-r--r--net/netfilter/nft_compat.c201
-rw-r--r--net/netfilter/nft_immediate.c15
-rw-r--r--net/netfilter/x_tables.c6
16 files changed, 299 insertions, 87 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index cd368d1b8cb8..a1e28dd5d0bf 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -170,6 +170,7 @@ struct nft_data_desc {
170int nft_data_init(const struct nft_ctx *ctx, 170int nft_data_init(const struct nft_ctx *ctx,
171 struct nft_data *data, unsigned int size, 171 struct nft_data *data, unsigned int size,
172 struct nft_data_desc *desc, const struct nlattr *nla); 172 struct nft_data_desc *desc, const struct nlattr *nla);
173void nft_data_hold(const struct nft_data *data, enum nft_data_types type);
173void nft_data_release(const struct nft_data *data, enum nft_data_types type); 174void nft_data_release(const struct nft_data *data, enum nft_data_types type);
174int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, 175int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
175 enum nft_data_types type, unsigned int len); 176 enum nft_data_types type, unsigned int len);
@@ -736,6 +737,10 @@ struct nft_expr_ops {
736 int (*init)(const struct nft_ctx *ctx, 737 int (*init)(const struct nft_ctx *ctx,
737 const struct nft_expr *expr, 738 const struct nft_expr *expr,
738 const struct nlattr * const tb[]); 739 const struct nlattr * const tb[]);
740 void (*activate)(const struct nft_ctx *ctx,
741 const struct nft_expr *expr);
742 void (*deactivate)(const struct nft_ctx *ctx,
743 const struct nft_expr *expr);
739 void (*destroy)(const struct nft_ctx *ctx, 744 void (*destroy)(const struct nft_ctx *ctx,
740 const struct nft_expr *expr); 745 const struct nft_expr *expr);
741 int (*dump)(struct sk_buff *skb, 746 int (*dump)(struct sk_buff *skb,
diff --git a/include/uapi/linux/netfilter/nf_conntrack_tcp.h b/include/uapi/linux/netfilter/nf_conntrack_tcp.h
index 74b91151d494..bcba72def817 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_tcp.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_tcp.h
@@ -46,6 +46,9 @@ enum tcp_conntrack {
46/* Marks possibility for expected RFC5961 challenge ACK */ 46/* Marks possibility for expected RFC5961 challenge ACK */
47#define IP_CT_EXP_CHALLENGE_ACK 0x40 47#define IP_CT_EXP_CHALLENGE_ACK 0x40
48 48
49/* Simultaneous open initialized */
50#define IP_CT_TCP_SIMULTANEOUS_OPEN 0x80
51
49struct nf_ct_tcp_flags { 52struct nf_ct_tcp_flags {
50 __u8 flags; 53 __u8 flags;
51 __u8 mask; 54 __u8 mask;
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index 47ba98db145d..46c1fe7637ea 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -161,8 +161,8 @@ static int ebt_stp_mt_check(const struct xt_mtchk_param *par)
161 /* Make sure the match only receives stp frames */ 161 /* Make sure the match only receives stp frames */
162 if (!par->nft_compat && 162 if (!par->nft_compat &&
163 (!ether_addr_equal(e->destmac, eth_stp_addr) || 163 (!ether_addr_equal(e->destmac, eth_stp_addr) ||
164 !is_broadcast_ether_addr(e->destmsk) || 164 !(e->bitmask & EBT_DESTMAC) ||
165 !(e->bitmask & EBT_DESTMAC))) 165 !is_broadcast_ether_addr(e->destmsk)))
166 return -EINVAL; 166 return -EINVAL;
167 167
168 return 0; 168 return 0;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 44b308d93ec2..e85f35b89c49 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -34,6 +34,7 @@
34MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
35MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 35MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
36MODULE_DESCRIPTION("IPv4 packet filter"); 36MODULE_DESCRIPTION("IPv4 packet filter");
37MODULE_ALIAS("ipt_icmp");
37 38
38void *ipt_alloc_initial_table(const struct xt_table *info) 39void *ipt_alloc_initial_table(const struct xt_table *info)
39{ 40{
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 65c9e1a58305..97f79dc943d7 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -38,6 +38,7 @@
38MODULE_LICENSE("GPL"); 38MODULE_LICENSE("GPL");
39MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 39MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
40MODULE_DESCRIPTION("IPv6 packet filter"); 40MODULE_DESCRIPTION("IPv6 packet filter");
41MODULE_ALIAS("ip6t_icmp6");
41 42
42void *ip6t_alloc_initial_table(const struct xt_table *info) 43void *ip6t_alloc_initial_table(const struct xt_table *info)
43{ 44{
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 0f6b8172fb9a..206fb2c4c319 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -585,7 +585,8 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
585EXPORT_SYMBOL(nf_nat_decode_session_hook); 585EXPORT_SYMBOL(nf_nat_decode_session_hook);
586#endif 586#endif
587 587
588static void __net_init __netfilter_net_init(struct nf_hook_entries **e, int max) 588static void __net_init
589__netfilter_net_init(struct nf_hook_entries __rcu **e, int max)
589{ 590{
590 int h; 591 int h;
591 592
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 370abbf6f421..75de46576f51 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -232,7 +232,10 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
232static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp) 232static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
233{ 233{
234 unsigned int hash; 234 unsigned int hash;
235 bool ret; 235 bool ret = false;
236
237 if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
238 return refcount_dec_if_one(&cp->refcnt);
236 239
237 hash = ip_vs_conn_hashkey_conn(cp); 240 hash = ip_vs_conn_hashkey_conn(cp);
238 241
@@ -240,15 +243,13 @@ static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
240 spin_lock(&cp->lock); 243 spin_lock(&cp->lock);
241 244
242 if (cp->flags & IP_VS_CONN_F_HASHED) { 245 if (cp->flags & IP_VS_CONN_F_HASHED) {
243 ret = false;
244 /* Decrease refcnt and unlink conn only if we are last user */ 246 /* Decrease refcnt and unlink conn only if we are last user */
245 if (refcount_dec_if_one(&cp->refcnt)) { 247 if (refcount_dec_if_one(&cp->refcnt)) {
246 hlist_del_rcu(&cp->c_list); 248 hlist_del_rcu(&cp->c_list);
247 cp->flags &= ~IP_VS_CONN_F_HASHED; 249 cp->flags &= ~IP_VS_CONN_F_HASHED;
248 ret = true; 250 ret = true;
249 } 251 }
250 } else 252 }
251 ret = refcount_read(&cp->refcnt) ? false : true;
252 253
253 spin_unlock(&cp->lock); 254 spin_unlock(&cp->lock);
254 ct_write_unlock_bh(hash); 255 ct_write_unlock_bh(hash);
@@ -454,12 +455,6 @@ ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af,
454} 455}
455EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto); 456EXPORT_SYMBOL_GPL(ip_vs_conn_out_get_proto);
456 457
457static void __ip_vs_conn_put_notimer(struct ip_vs_conn *cp)
458{
459 __ip_vs_conn_put(cp);
460 ip_vs_conn_expire(&cp->timer);
461}
462
463/* 458/*
464 * Put back the conn and restart its timer with its timeout 459 * Put back the conn and restart its timer with its timeout
465 */ 460 */
@@ -478,7 +473,7 @@ void ip_vs_conn_put(struct ip_vs_conn *cp)
478 (refcount_read(&cp->refcnt) == 1) && 473 (refcount_read(&cp->refcnt) == 1) &&
479 !timer_pending(&cp->timer)) 474 !timer_pending(&cp->timer))
480 /* expire connection immediately */ 475 /* expire connection immediately */
481 __ip_vs_conn_put_notimer(cp); 476 ip_vs_conn_expire(&cp->timer);
482 else 477 else
483 __ip_vs_conn_put_timer(cp); 478 __ip_vs_conn_put_timer(cp);
484} 479}
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 5f6f73cf2174..0679dd101e72 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -119,6 +119,8 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
119 struct ip_vs_cpu_stats *s; 119 struct ip_vs_cpu_stats *s;
120 struct ip_vs_service *svc; 120 struct ip_vs_service *svc;
121 121
122 local_bh_disable();
123
122 s = this_cpu_ptr(dest->stats.cpustats); 124 s = this_cpu_ptr(dest->stats.cpustats);
123 u64_stats_update_begin(&s->syncp); 125 u64_stats_update_begin(&s->syncp);
124 s->cnt.inpkts++; 126 s->cnt.inpkts++;
@@ -137,6 +139,8 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
137 s->cnt.inpkts++; 139 s->cnt.inpkts++;
138 s->cnt.inbytes += skb->len; 140 s->cnt.inbytes += skb->len;
139 u64_stats_update_end(&s->syncp); 141 u64_stats_update_end(&s->syncp);
142
143 local_bh_enable();
140 } 144 }
141} 145}
142 146
@@ -151,6 +155,8 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
151 struct ip_vs_cpu_stats *s; 155 struct ip_vs_cpu_stats *s;
152 struct ip_vs_service *svc; 156 struct ip_vs_service *svc;
153 157
158 local_bh_disable();
159
154 s = this_cpu_ptr(dest->stats.cpustats); 160 s = this_cpu_ptr(dest->stats.cpustats);
155 u64_stats_update_begin(&s->syncp); 161 u64_stats_update_begin(&s->syncp);
156 s->cnt.outpkts++; 162 s->cnt.outpkts++;
@@ -169,6 +175,8 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
169 s->cnt.outpkts++; 175 s->cnt.outpkts++;
170 s->cnt.outbytes += skb->len; 176 s->cnt.outbytes += skb->len;
171 u64_stats_update_end(&s->syncp); 177 u64_stats_update_end(&s->syncp);
178
179 local_bh_enable();
172 } 180 }
173} 181}
174 182
@@ -179,6 +187,8 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
179 struct netns_ipvs *ipvs = svc->ipvs; 187 struct netns_ipvs *ipvs = svc->ipvs;
180 struct ip_vs_cpu_stats *s; 188 struct ip_vs_cpu_stats *s;
181 189
190 local_bh_disable();
191
182 s = this_cpu_ptr(cp->dest->stats.cpustats); 192 s = this_cpu_ptr(cp->dest->stats.cpustats);
183 u64_stats_update_begin(&s->syncp); 193 u64_stats_update_begin(&s->syncp);
184 s->cnt.conns++; 194 s->cnt.conns++;
@@ -193,6 +203,8 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
193 u64_stats_update_begin(&s->syncp); 203 u64_stats_update_begin(&s->syncp);
194 s->cnt.conns++; 204 s->cnt.conns++;
195 u64_stats_update_end(&s->syncp); 205 u64_stats_update_end(&s->syncp);
206
207 local_bh_enable();
196} 208}
197 209
198 210
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index e97cdc1cf98c..8e67910185a0 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -981,6 +981,17 @@ static int tcp_packet(struct nf_conn *ct,
981 return NF_ACCEPT; /* Don't change state */ 981 return NF_ACCEPT; /* Don't change state */
982 } 982 }
983 break; 983 break;
984 case TCP_CONNTRACK_SYN_SENT2:
985 /* tcp_conntracks table is not smart enough to handle
986 * simultaneous open.
987 */
988 ct->proto.tcp.last_flags |= IP_CT_TCP_SIMULTANEOUS_OPEN;
989 break;
990 case TCP_CONNTRACK_SYN_RECV:
991 if (dir == IP_CT_DIR_REPLY && index == TCP_ACK_SET &&
992 ct->proto.tcp.last_flags & IP_CT_TCP_SIMULTANEOUS_OPEN)
993 new_state = TCP_CONNTRACK_ESTABLISHED;
994 break;
984 case TCP_CONNTRACK_CLOSE: 995 case TCP_CONNTRACK_CLOSE:
985 if (index == TCP_RST_SET 996 if (index == TCP_RST_SET
986 && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET) 997 && (ct->proto.tcp.seen[!dir].flags & IP_CT_TCP_FLAG_MAXACK_SET)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 04d4e3772584..91e80aa852d6 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -214,6 +214,34 @@ static int nft_delchain(struct nft_ctx *ctx)
214 return err; 214 return err;
215} 215}
216 216
217static void nft_rule_expr_activate(const struct nft_ctx *ctx,
218 struct nft_rule *rule)
219{
220 struct nft_expr *expr;
221
222 expr = nft_expr_first(rule);
223 while (expr != nft_expr_last(rule) && expr->ops) {
224 if (expr->ops->activate)
225 expr->ops->activate(ctx, expr);
226
227 expr = nft_expr_next(expr);
228 }
229}
230
231static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
232 struct nft_rule *rule)
233{
234 struct nft_expr *expr;
235
236 expr = nft_expr_first(rule);
237 while (expr != nft_expr_last(rule) && expr->ops) {
238 if (expr->ops->deactivate)
239 expr->ops->deactivate(ctx, expr);
240
241 expr = nft_expr_next(expr);
242 }
243}
244
217static int 245static int
218nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule) 246nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
219{ 247{
@@ -259,6 +287,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
259 nft_trans_destroy(trans); 287 nft_trans_destroy(trans);
260 return err; 288 return err;
261 } 289 }
290 nft_rule_expr_deactivate(ctx, rule);
262 291
263 return 0; 292 return 0;
264} 293}
@@ -2238,6 +2267,13 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
2238 kfree(rule); 2267 kfree(rule);
2239} 2268}
2240 2269
2270static void nf_tables_rule_release(const struct nft_ctx *ctx,
2271 struct nft_rule *rule)
2272{
2273 nft_rule_expr_deactivate(ctx, rule);
2274 nf_tables_rule_destroy(ctx, rule);
2275}
2276
2241#define NFT_RULE_MAXEXPRS 128 2277#define NFT_RULE_MAXEXPRS 128
2242 2278
2243static struct nft_expr_info *info; 2279static struct nft_expr_info *info;
@@ -2402,7 +2438,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2402 return 0; 2438 return 0;
2403 2439
2404err2: 2440err2:
2405 nf_tables_rule_destroy(&ctx, rule); 2441 nf_tables_rule_release(&ctx, rule);
2406err1: 2442err1:
2407 for (i = 0; i < n; i++) { 2443 for (i = 0; i < n; i++) {
2408 if (info[i].ops != NULL) 2444 if (info[i].ops != NULL)
@@ -4044,8 +4080,10 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
4044 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^ 4080 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^
4045 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) || 4081 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) ||
4046 nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^ 4082 nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^
4047 nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF)) 4083 nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF)) {
4048 return -EBUSY; 4084 err = -EBUSY;
4085 goto err5;
4086 }
4049 if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) && 4087 if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
4050 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) && 4088 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
4051 memcmp(nft_set_ext_data(ext), 4089 memcmp(nft_set_ext_data(ext),
@@ -4130,7 +4168,7 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
4130 * NFT_GOTO verdicts. This function must be called on active data objects 4168 * NFT_GOTO verdicts. This function must be called on active data objects
4131 * from the second phase of the commit protocol. 4169 * from the second phase of the commit protocol.
4132 */ 4170 */
4133static void nft_data_hold(const struct nft_data *data, enum nft_data_types type) 4171void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
4134{ 4172{
4135 if (type == NFT_DATA_VERDICT) { 4173 if (type == NFT_DATA_VERDICT) {
4136 switch (data->verdict.code) { 4174 switch (data->verdict.code) {
@@ -5761,7 +5799,7 @@ static void nft_chain_commit_update(struct nft_trans *trans)
5761 } 5799 }
5762} 5800}
5763 5801
5764static void nf_tables_commit_release(struct nft_trans *trans) 5802static void nft_commit_release(struct nft_trans *trans)
5765{ 5803{
5766 switch (trans->msg_type) { 5804 switch (trans->msg_type) {
5767 case NFT_MSG_DELTABLE: 5805 case NFT_MSG_DELTABLE:
@@ -5790,6 +5828,21 @@ static void nf_tables_commit_release(struct nft_trans *trans)
5790 kfree(trans); 5828 kfree(trans);
5791} 5829}
5792 5830
5831static void nf_tables_commit_release(struct net *net)
5832{
5833 struct nft_trans *trans, *next;
5834
5835 if (list_empty(&net->nft.commit_list))
5836 return;
5837
5838 synchronize_rcu();
5839
5840 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
5841 list_del(&trans->list);
5842 nft_commit_release(trans);
5843 }
5844}
5845
5793static int nf_tables_commit(struct net *net, struct sk_buff *skb) 5846static int nf_tables_commit(struct net *net, struct sk_buff *skb)
5794{ 5847{
5795 struct nft_trans *trans, *next; 5848 struct nft_trans *trans, *next;
@@ -5920,13 +5973,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
5920 } 5973 }
5921 } 5974 }
5922 5975
5923 synchronize_rcu(); 5976 nf_tables_commit_release(net);
5924
5925 list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
5926 list_del(&trans->list);
5927 nf_tables_commit_release(trans);
5928 }
5929
5930 nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); 5977 nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
5931 5978
5932 return 0; 5979 return 0;
@@ -6006,10 +6053,12 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
6006 case NFT_MSG_NEWRULE: 6053 case NFT_MSG_NEWRULE:
6007 trans->ctx.chain->use--; 6054 trans->ctx.chain->use--;
6008 list_del_rcu(&nft_trans_rule(trans)->list); 6055 list_del_rcu(&nft_trans_rule(trans)->list);
6056 nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans));
6009 break; 6057 break;
6010 case NFT_MSG_DELRULE: 6058 case NFT_MSG_DELRULE:
6011 trans->ctx.chain->use++; 6059 trans->ctx.chain->use++;
6012 nft_clear(trans->ctx.net, nft_trans_rule(trans)); 6060 nft_clear(trans->ctx.net, nft_trans_rule(trans));
6061 nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
6013 nft_trans_destroy(trans); 6062 nft_trans_destroy(trans);
6014 break; 6063 break;
6015 case NFT_MSG_NEWSET: 6064 case NFT_MSG_NEWSET:
@@ -6585,7 +6634,7 @@ int __nft_release_basechain(struct nft_ctx *ctx)
6585 list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) { 6634 list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
6586 list_del(&rule->list); 6635 list_del(&rule->list);
6587 ctx->chain->use--; 6636 ctx->chain->use--;
6588 nf_tables_rule_destroy(ctx, rule); 6637 nf_tables_rule_release(ctx, rule);
6589 } 6638 }
6590 list_del(&ctx->chain->list); 6639 list_del(&ctx->chain->list);
6591 ctx->table->use--; 6640 ctx->table->use--;
@@ -6623,7 +6672,7 @@ static void __nft_release_tables(struct net *net)
6623 list_for_each_entry_safe(rule, nr, &chain->rules, list) { 6672 list_for_each_entry_safe(rule, nr, &chain->rules, list) {
6624 list_del(&rule->list); 6673 list_del(&rule->list);
6625 chain->use--; 6674 chain->use--;
6626 nf_tables_rule_destroy(&ctx, rule); 6675 nf_tables_rule_release(&ctx, rule);
6627 } 6676 }
6628 } 6677 }
6629 list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) { 6678 list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) {
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index dfd0bf3810d2..942702a2776f 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -119,15 +119,22 @@ DEFINE_STATIC_KEY_FALSE(nft_counters_enabled);
119static noinline void nft_update_chain_stats(const struct nft_chain *chain, 119static noinline void nft_update_chain_stats(const struct nft_chain *chain,
120 const struct nft_pktinfo *pkt) 120 const struct nft_pktinfo *pkt)
121{ 121{
122 struct nft_base_chain *base_chain;
122 struct nft_stats *stats; 123 struct nft_stats *stats;
123 124
124 local_bh_disable(); 125 base_chain = nft_base_chain(chain);
125 stats = this_cpu_ptr(rcu_dereference(nft_base_chain(chain)->stats)); 126 if (!base_chain->stats)
126 u64_stats_update_begin(&stats->syncp); 127 return;
127 stats->pkts++; 128
128 stats->bytes += pkt->skb->len; 129 stats = this_cpu_ptr(rcu_dereference(base_chain->stats));
129 u64_stats_update_end(&stats->syncp); 130 if (stats) {
130 local_bh_enable(); 131 local_bh_disable();
132 u64_stats_update_begin(&stats->syncp);
133 stats->pkts++;
134 stats->bytes += pkt->skb->len;
135 u64_stats_update_end(&stats->syncp);
136 local_bh_enable();
137 }
131} 138}
132 139
133struct nft_jumpstack { 140struct nft_jumpstack {
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index b9505bcd3827..6ddf89183e7b 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -115,7 +115,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
115 nfacct->flags = flags; 115 nfacct->flags = flags;
116 } 116 }
117 117
118 strncpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX); 118 nla_strlcpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX);
119 119
120 if (tb[NFACCT_BYTES]) { 120 if (tb[NFACCT_BYTES]) {
121 atomic64_set(&nfacct->bytes, 121 atomic64_set(&nfacct->bytes,
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
index 4a4b293fb2e5..fa026b269b36 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -149,8 +149,8 @@ nfnl_cthelper_expect_policy(struct nf_conntrack_expect_policy *expect_policy,
149 !tb[NFCTH_POLICY_EXPECT_TIMEOUT]) 149 !tb[NFCTH_POLICY_EXPECT_TIMEOUT])
150 return -EINVAL; 150 return -EINVAL;
151 151
152 strncpy(expect_policy->name, 152 nla_strlcpy(expect_policy->name,
153 nla_data(tb[NFCTH_POLICY_NAME]), NF_CT_HELPER_NAME_LEN); 153 nla_data(tb[NFCTH_POLICY_NAME]), NF_CT_HELPER_NAME_LEN);
154 expect_policy->max_expected = 154 expect_policy->max_expected =
155 ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX])); 155 ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
156 if (expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT) 156 if (expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
@@ -234,7 +234,8 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
234 if (ret < 0) 234 if (ret < 0)
235 goto err1; 235 goto err1;
236 236
237 strncpy(helper->name, nla_data(tb[NFCTH_NAME]), NF_CT_HELPER_NAME_LEN); 237 nla_strlcpy(helper->name,
238 nla_data(tb[NFCTH_NAME]), NF_CT_HELPER_NAME_LEN);
238 size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN])); 239 size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN]));
239 if (size > FIELD_SIZEOF(struct nf_conn_help, data)) { 240 if (size > FIELD_SIZEOF(struct nf_conn_help, data)) {
240 ret = -ENOMEM; 241 ret = -ENOMEM;
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 8e23726b9081..1d99a1efdafc 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -27,14 +27,31 @@ struct nft_xt {
27 struct list_head head; 27 struct list_head head;
28 struct nft_expr_ops ops; 28 struct nft_expr_ops ops;
29 unsigned int refcnt; 29 unsigned int refcnt;
30
31 /* Unlike other expressions, ops doesn't have static storage duration.
32 * nft core assumes they do. We use kfree_rcu so that nft core can
33 * can check expr->ops->size even after nft_compat->destroy() frees
34 * the nft_xt struct that holds the ops structure.
35 */
36 struct rcu_head rcu_head;
37};
38
39/* Used for matches where *info is larger than X byte */
40#define NFT_MATCH_LARGE_THRESH 192
41
42struct nft_xt_match_priv {
43 void *info;
30}; 44};
31 45
32static void nft_xt_put(struct nft_xt *xt) 46static bool nft_xt_put(struct nft_xt *xt)
33{ 47{
34 if (--xt->refcnt == 0) { 48 if (--xt->refcnt == 0) {
35 list_del(&xt->head); 49 list_del(&xt->head);
36 kfree(xt); 50 kfree_rcu(xt, rcu_head);
51 return true;
37 } 52 }
53
54 return false;
38} 55}
39 56
40static int nft_compat_chain_validate_dependency(const char *tablename, 57static int nft_compat_chain_validate_dependency(const char *tablename,
@@ -226,6 +243,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
226 struct xt_target *target = expr->ops->data; 243 struct xt_target *target = expr->ops->data;
227 struct xt_tgchk_param par; 244 struct xt_tgchk_param par;
228 size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO])); 245 size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO]));
246 struct nft_xt *nft_xt;
229 u16 proto = 0; 247 u16 proto = 0;
230 bool inv = false; 248 bool inv = false;
231 union nft_entry e = {}; 249 union nft_entry e = {};
@@ -236,25 +254,22 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
236 if (ctx->nla[NFTA_RULE_COMPAT]) { 254 if (ctx->nla[NFTA_RULE_COMPAT]) {
237 ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv); 255 ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
238 if (ret < 0) 256 if (ret < 0)
239 goto err; 257 return ret;
240 } 258 }
241 259
242 nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv); 260 nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
243 261
244 ret = xt_check_target(&par, size, proto, inv); 262 ret = xt_check_target(&par, size, proto, inv);
245 if (ret < 0) 263 if (ret < 0)
246 goto err; 264 return ret;
247 265
248 /* The standard target cannot be used */ 266 /* The standard target cannot be used */
249 if (target->target == NULL) { 267 if (!target->target)
250 ret = -EINVAL; 268 return -EINVAL;
251 goto err;
252 }
253 269
270 nft_xt = container_of(expr->ops, struct nft_xt, ops);
271 nft_xt->refcnt++;
254 return 0; 272 return 0;
255err:
256 module_put(target->me);
257 return ret;
258} 273}
259 274
260static void 275static void
@@ -271,8 +286,8 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
271 if (par.target->destroy != NULL) 286 if (par.target->destroy != NULL)
272 par.target->destroy(&par); 287 par.target->destroy(&par);
273 288
274 nft_xt_put(container_of(expr->ops, struct nft_xt, ops)); 289 if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
275 module_put(target->me); 290 module_put(target->me);
276} 291}
277 292
278static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr) 293static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -316,11 +331,11 @@ static int nft_target_validate(const struct nft_ctx *ctx,
316 return 0; 331 return 0;
317} 332}
318 333
319static void nft_match_eval(const struct nft_expr *expr, 334static void __nft_match_eval(const struct nft_expr *expr,
320 struct nft_regs *regs, 335 struct nft_regs *regs,
321 const struct nft_pktinfo *pkt) 336 const struct nft_pktinfo *pkt,
337 void *info)
322{ 338{
323 void *info = nft_expr_priv(expr);
324 struct xt_match *match = expr->ops->data; 339 struct xt_match *match = expr->ops->data;
325 struct sk_buff *skb = pkt->skb; 340 struct sk_buff *skb = pkt->skb;
326 bool ret; 341 bool ret;
@@ -344,6 +359,22 @@ static void nft_match_eval(const struct nft_expr *expr,
344 } 359 }
345} 360}
346 361
362static void nft_match_large_eval(const struct nft_expr *expr,
363 struct nft_regs *regs,
364 const struct nft_pktinfo *pkt)
365{
366 struct nft_xt_match_priv *priv = nft_expr_priv(expr);
367
368 __nft_match_eval(expr, regs, pkt, priv->info);
369}
370
371static void nft_match_eval(const struct nft_expr *expr,
372 struct nft_regs *regs,
373 const struct nft_pktinfo *pkt)
374{
375 __nft_match_eval(expr, regs, pkt, nft_expr_priv(expr));
376}
377
347static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = { 378static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = {
348 [NFTA_MATCH_NAME] = { .type = NLA_NUL_STRING }, 379 [NFTA_MATCH_NAME] = { .type = NLA_NUL_STRING },
349 [NFTA_MATCH_REV] = { .type = NLA_U32 }, 380 [NFTA_MATCH_REV] = { .type = NLA_U32 },
@@ -404,13 +435,14 @@ static void match_compat_from_user(struct xt_match *m, void *in, void *out)
404} 435}
405 436
406static int 437static int
407nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr, 438__nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
408 const struct nlattr * const tb[]) 439 const struct nlattr * const tb[],
440 void *info)
409{ 441{
410 void *info = nft_expr_priv(expr);
411 struct xt_match *match = expr->ops->data; 442 struct xt_match *match = expr->ops->data;
412 struct xt_mtchk_param par; 443 struct xt_mtchk_param par;
413 size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO])); 444 size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO]));
445 struct nft_xt *nft_xt;
414 u16 proto = 0; 446 u16 proto = 0;
415 bool inv = false; 447 bool inv = false;
416 union nft_entry e = {}; 448 union nft_entry e = {};
@@ -421,26 +453,50 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
421 if (ctx->nla[NFTA_RULE_COMPAT]) { 453 if (ctx->nla[NFTA_RULE_COMPAT]) {
422 ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv); 454 ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
423 if (ret < 0) 455 if (ret < 0)
424 goto err; 456 return ret;
425 } 457 }
426 458
427 nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv); 459 nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
428 460
429 ret = xt_check_match(&par, size, proto, inv); 461 ret = xt_check_match(&par, size, proto, inv);
430 if (ret < 0) 462 if (ret < 0)
431 goto err; 463 return ret;
432 464
465 nft_xt = container_of(expr->ops, struct nft_xt, ops);
466 nft_xt->refcnt++;
433 return 0; 467 return 0;
434err: 468}
435 module_put(match->me); 469
470static int
471nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
472 const struct nlattr * const tb[])
473{
474 return __nft_match_init(ctx, expr, tb, nft_expr_priv(expr));
475}
476
477static int
478nft_match_large_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
479 const struct nlattr * const tb[])
480{
481 struct nft_xt_match_priv *priv = nft_expr_priv(expr);
482 struct xt_match *m = expr->ops->data;
483 int ret;
484
485 priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL);
486 if (!priv->info)
487 return -ENOMEM;
488
489 ret = __nft_match_init(ctx, expr, tb, priv->info);
490 if (ret)
491 kfree(priv->info);
436 return ret; 492 return ret;
437} 493}
438 494
439static void 495static void
440nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) 496__nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr,
497 void *info)
441{ 498{
442 struct xt_match *match = expr->ops->data; 499 struct xt_match *match = expr->ops->data;
443 void *info = nft_expr_priv(expr);
444 struct xt_mtdtor_param par; 500 struct xt_mtdtor_param par;
445 501
446 par.net = ctx->net; 502 par.net = ctx->net;
@@ -450,13 +506,28 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
450 if (par.match->destroy != NULL) 506 if (par.match->destroy != NULL)
451 par.match->destroy(&par); 507 par.match->destroy(&par);
452 508
453 nft_xt_put(container_of(expr->ops, struct nft_xt, ops)); 509 if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
454 module_put(match->me); 510 module_put(match->me);
455} 511}
456 512
457static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr) 513static void
514nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
515{
516 __nft_match_destroy(ctx, expr, nft_expr_priv(expr));
517}
518
519static void
520nft_match_large_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
521{
522 struct nft_xt_match_priv *priv = nft_expr_priv(expr);
523
524 __nft_match_destroy(ctx, expr, priv->info);
525 kfree(priv->info);
526}
527
528static int __nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr,
529 void *info)
458{ 530{
459 void *info = nft_expr_priv(expr);
460 struct xt_match *match = expr->ops->data; 531 struct xt_match *match = expr->ops->data;
461 532
462 if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) || 533 if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) ||
@@ -470,6 +541,18 @@ nla_put_failure:
470 return -1; 541 return -1;
471} 542}
472 543
544static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
545{
546 return __nft_match_dump(skb, expr, nft_expr_priv(expr));
547}
548
549static int nft_match_large_dump(struct sk_buff *skb, const struct nft_expr *e)
550{
551 struct nft_xt_match_priv *priv = nft_expr_priv(e);
552
553 return __nft_match_dump(skb, e, priv->info);
554}
555
473static int nft_match_validate(const struct nft_ctx *ctx, 556static int nft_match_validate(const struct nft_ctx *ctx,
474 const struct nft_expr *expr, 557 const struct nft_expr *expr,
475 const struct nft_data **data) 558 const struct nft_data **data)
@@ -637,6 +720,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
637{ 720{
638 struct nft_xt *nft_match; 721 struct nft_xt *nft_match;
639 struct xt_match *match; 722 struct xt_match *match;
723 unsigned int matchsize;
640 char *mt_name; 724 char *mt_name;
641 u32 rev, family; 725 u32 rev, family;
642 int err; 726 int err;
@@ -654,13 +738,8 @@ nft_match_select_ops(const struct nft_ctx *ctx,
654 list_for_each_entry(nft_match, &nft_match_list, head) { 738 list_for_each_entry(nft_match, &nft_match_list, head) {
655 struct xt_match *match = nft_match->ops.data; 739 struct xt_match *match = nft_match->ops.data;
656 740
657 if (nft_match_cmp(match, mt_name, rev, family)) { 741 if (nft_match_cmp(match, mt_name, rev, family))
658 if (!try_module_get(match->me))
659 return ERR_PTR(-ENOENT);
660
661 nft_match->refcnt++;
662 return &nft_match->ops; 742 return &nft_match->ops;
663 }
664 } 743 }
665 744
666 match = xt_request_find_match(family, mt_name, rev); 745 match = xt_request_find_match(family, mt_name, rev);
@@ -679,9 +758,8 @@ nft_match_select_ops(const struct nft_ctx *ctx,
679 goto err; 758 goto err;
680 } 759 }
681 760
682 nft_match->refcnt = 1; 761 nft_match->refcnt = 0;
683 nft_match->ops.type = &nft_match_type; 762 nft_match->ops.type = &nft_match_type;
684 nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
685 nft_match->ops.eval = nft_match_eval; 763 nft_match->ops.eval = nft_match_eval;
686 nft_match->ops.init = nft_match_init; 764 nft_match->ops.init = nft_match_init;
687 nft_match->ops.destroy = nft_match_destroy; 765 nft_match->ops.destroy = nft_match_destroy;
@@ -689,6 +767,18 @@ nft_match_select_ops(const struct nft_ctx *ctx,
689 nft_match->ops.validate = nft_match_validate; 767 nft_match->ops.validate = nft_match_validate;
690 nft_match->ops.data = match; 768 nft_match->ops.data = match;
691 769
770 matchsize = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
771 if (matchsize > NFT_MATCH_LARGE_THRESH) {
772 matchsize = NFT_EXPR_SIZE(sizeof(struct nft_xt_match_priv));
773
774 nft_match->ops.eval = nft_match_large_eval;
775 nft_match->ops.init = nft_match_large_init;
776 nft_match->ops.destroy = nft_match_large_destroy;
777 nft_match->ops.dump = nft_match_large_dump;
778 }
779
780 nft_match->ops.size = matchsize;
781
692 list_add(&nft_match->head, &nft_match_list); 782 list_add(&nft_match->head, &nft_match_list);
693 783
694 return &nft_match->ops; 784 return &nft_match->ops;
@@ -739,13 +829,8 @@ nft_target_select_ops(const struct nft_ctx *ctx,
739 list_for_each_entry(nft_target, &nft_target_list, head) { 829 list_for_each_entry(nft_target, &nft_target_list, head) {
740 struct xt_target *target = nft_target->ops.data; 830 struct xt_target *target = nft_target->ops.data;
741 831
742 if (nft_target_cmp(target, tg_name, rev, family)) { 832 if (nft_target_cmp(target, tg_name, rev, family))
743 if (!try_module_get(target->me))
744 return ERR_PTR(-ENOENT);
745
746 nft_target->refcnt++;
747 return &nft_target->ops; 833 return &nft_target->ops;
748 }
749 } 834 }
750 835
751 target = xt_request_find_target(family, tg_name, rev); 836 target = xt_request_find_target(family, tg_name, rev);
@@ -764,7 +849,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
764 goto err; 849 goto err;
765 } 850 }
766 851
767 nft_target->refcnt = 1; 852 nft_target->refcnt = 0;
768 nft_target->ops.type = &nft_target_type; 853 nft_target->ops.type = &nft_target_type;
769 nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); 854 nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
770 nft_target->ops.init = nft_target_init; 855 nft_target->ops.init = nft_target_init;
@@ -823,6 +908,32 @@ err_match:
823 908
824static void __exit nft_compat_module_exit(void) 909static void __exit nft_compat_module_exit(void)
825{ 910{
911 struct nft_xt *xt, *next;
912
913 /* list should be empty here, it can be non-empty only in case there
914 * was an error that caused nft_xt expr to not be initialized fully
915 * and noone else requested the same expression later.
916 *
917 * In this case, the lists contain 0-refcount entries that still
918 * hold module reference.
919 */
920 list_for_each_entry_safe(xt, next, &nft_target_list, head) {
921 struct xt_target *target = xt->ops.data;
922
923 if (WARN_ON_ONCE(xt->refcnt))
924 continue;
925 module_put(target->me);
926 kfree(xt);
927 }
928
929 list_for_each_entry_safe(xt, next, &nft_match_list, head) {
930 struct xt_match *match = xt->ops.data;
931
932 if (WARN_ON_ONCE(xt->refcnt))
933 continue;
934 module_put(match->me);
935 kfree(xt);
936 }
826 nfnetlink_subsys_unregister(&nfnl_compat_subsys); 937 nfnetlink_subsys_unregister(&nfnl_compat_subsys);
827 nft_unregister_expr(&nft_target_type); 938 nft_unregister_expr(&nft_target_type);
828 nft_unregister_expr(&nft_match_type); 939 nft_unregister_expr(&nft_match_type);
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index 4717d7796927..aa87ff8beae8 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -69,8 +69,16 @@ err1:
69 return err; 69 return err;
70} 70}
71 71
72static void nft_immediate_destroy(const struct nft_ctx *ctx, 72static void nft_immediate_activate(const struct nft_ctx *ctx,
73 const struct nft_expr *expr) 73 const struct nft_expr *expr)
74{
75 const struct nft_immediate_expr *priv = nft_expr_priv(expr);
76
77 return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
78}
79
80static void nft_immediate_deactivate(const struct nft_ctx *ctx,
81 const struct nft_expr *expr)
74{ 82{
75 const struct nft_immediate_expr *priv = nft_expr_priv(expr); 83 const struct nft_immediate_expr *priv = nft_expr_priv(expr);
76 84
@@ -108,7 +116,8 @@ static const struct nft_expr_ops nft_imm_ops = {
108 .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)), 116 .size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),
109 .eval = nft_immediate_eval, 117 .eval = nft_immediate_eval,
110 .init = nft_immediate_init, 118 .init = nft_immediate_init,
111 .destroy = nft_immediate_destroy, 119 .activate = nft_immediate_activate,
120 .deactivate = nft_immediate_deactivate,
112 .dump = nft_immediate_dump, 121 .dump = nft_immediate_dump,
113 .validate = nft_immediate_validate, 122 .validate = nft_immediate_validate,
114}; 123};
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 71325fef647d..cb7cb300c3bc 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -183,6 +183,9 @@ struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
183 struct xt_match *m; 183 struct xt_match *m;
184 int err = -ENOENT; 184 int err = -ENOENT;
185 185
186 if (strnlen(name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN)
187 return ERR_PTR(-EINVAL);
188
186 mutex_lock(&xt[af].mutex); 189 mutex_lock(&xt[af].mutex);
187 list_for_each_entry(m, &xt[af].match, list) { 190 list_for_each_entry(m, &xt[af].match, list) {
188 if (strcmp(m->name, name) == 0) { 191 if (strcmp(m->name, name) == 0) {
@@ -229,6 +232,9 @@ struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
229 struct xt_target *t; 232 struct xt_target *t;
230 int err = -ENOENT; 233 int err = -ENOENT;
231 234
235 if (strnlen(name, XT_EXTENSION_MAXNAMELEN) == XT_EXTENSION_MAXNAMELEN)
236 return ERR_PTR(-EINVAL);
237
232 mutex_lock(&xt[af].mutex); 238 mutex_lock(&xt[af].mutex);
233 list_for_each_entry(t, &xt[af].target, list) { 239 list_for_each_entry(t, &xt[af].target, list) {
234 if (strcmp(t->name, name) == 0) { 240 if (strcmp(t->name, name) == 0) {