aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-05-21 13:00:02 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-21 13:00:02 -0400
commit23416e230416a9201561f1db553b1515e9959f6a (patch)
tree5a518f333f13b09e196790b8b2c3eb6df095ae04
parent8b4822de59d5d9919b9b045183a36c673ce20b73 (diff)
parent751a9c763849f5859cb69ea44b0430d00672f637 (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) When using IPVS in direct-routing mode, normal traffic from the LVS host to a back-end server is sometimes incorrectly NATed on the way back into the LVS host. Patch to fix this from Julian Anastasov. 2) Calm down clang compilation warning in ctnetlink due to type mismatch, from Matthias Kaehlcke. 3) Do not re-setup NAT for conntracks that are already confirmed, this is fixing a problem that was introduced in the previous nf-next batch. Patch from Liping Zhang. 4) Do not allow conntrack helper removal from userspace cthelper infrastructure if already in used. This comes with an initial patch to introduce nf_conntrack_helper_put() that is required by this fix. From Liping Zhang. 5) Zero the pad when copying data to userspace, otherwise iptables fails to remove rules. This is a follow up on the patchset that sorts out the internal match/target structure pointer leak to userspace. Patch from the same author, Willem de Bruijn. This also comes with a build failure when CONFIG_COMPAT is not on, coming in the last patch of this series. 6) SYNPROXY crashes with conntrack entries that are created via ctnetlink, more specifically via conntrackd state sync. Patch from Eric Leblond. 7) RCU safe iteration on set element dumping in nf_tables, from Liping Zhang. 8) Missing sanitization of immediate date for the bitwise and cmp expressions in nf_tables. 9) Refcounting logic for chain and objects from set elements does not integrate into the nf_tables 2-phase commit protocol. 10) Missing sanitization of target verdict in ebtables arpreply target, from Gao Feng. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter/x_tables.h2
-rw-r--r--include/linux/netfilter_bridge/ebtables.h5
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h4
-rw-r--r--include/net/netfilter/nf_tables.h2
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c3
-rw-r--r--net/bridge/netfilter/ebtables.c9
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c19
-rw-r--r--net/netfilter/nf_conntrack_helper.c12
-rw-r--r--net/netfilter/nf_conntrack_netlink.c11
-rw-r--r--net/netfilter/nf_nat_core.c4
-rw-r--r--net/netfilter/nf_tables_api.c160
-rw-r--r--net/netfilter/nfnetlink_cthelper.c17
-rw-r--r--net/netfilter/nft_bitwise.c19
-rw-r--r--net/netfilter/nft_cmp.c12
-rw-r--r--net/netfilter/nft_ct.c4
-rw-r--r--net/netfilter/nft_immediate.c5
-rw-r--r--net/netfilter/nft_range.c4
-rw-r--r--net/netfilter/nft_set_hash.c2
-rw-r--r--net/netfilter/x_tables.c24
-rw-r--r--net/netfilter/xt_CT.c6
-rw-r--r--net/openvswitch/conntrack.c4
21 files changed, 249 insertions, 79 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index be378cf47fcc..b3044c2c62cb 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -294,7 +294,7 @@ int xt_match_to_user(const struct xt_entry_match *m,
294int xt_target_to_user(const struct xt_entry_target *t, 294int xt_target_to_user(const struct xt_entry_target *t,
295 struct xt_entry_target __user *u); 295 struct xt_entry_target __user *u);
296int xt_data_to_user(void __user *dst, const void *src, 296int xt_data_to_user(void __user *dst, const void *src,
297 int usersize, int size); 297 int usersize, int size, int aligned_size);
298 298
299void *xt_copy_counters_from_user(const void __user *user, unsigned int len, 299void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
300 struct xt_counters_info *info, bool compat); 300 struct xt_counters_info *info, bool compat);
diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h
index a30efb437e6d..e0cbf17af780 100644
--- a/include/linux/netfilter_bridge/ebtables.h
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -125,4 +125,9 @@ extern unsigned int ebt_do_table(struct sk_buff *skb,
125/* True if the target is not a standard target */ 125/* True if the target is not a standard target */
126#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) 126#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0)
127 127
128static inline bool ebt_invalid_target(int target)
129{
130 return (target < -NUM_STANDARD_TARGETS || target >= 0);
131}
132
128#endif 133#endif
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index e04fa7691e5d..c519bb5b5bb8 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -9,6 +9,7 @@
9 9
10#ifndef _NF_CONNTRACK_HELPER_H 10#ifndef _NF_CONNTRACK_HELPER_H
11#define _NF_CONNTRACK_HELPER_H 11#define _NF_CONNTRACK_HELPER_H
12#include <linux/refcount.h>
12#include <net/netfilter/nf_conntrack.h> 13#include <net/netfilter/nf_conntrack.h>
13#include <net/netfilter/nf_conntrack_extend.h> 14#include <net/netfilter/nf_conntrack_extend.h>
14#include <net/netfilter/nf_conntrack_expect.h> 15#include <net/netfilter/nf_conntrack_expect.h>
@@ -26,6 +27,7 @@ struct nf_conntrack_helper {
26 struct hlist_node hnode; /* Internal use. */ 27 struct hlist_node hnode; /* Internal use. */
27 28
28 char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */ 29 char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */
30 refcount_t refcnt;
29 struct module *me; /* pointer to self */ 31 struct module *me; /* pointer to self */
30 const struct nf_conntrack_expect_policy *expect_policy; 32 const struct nf_conntrack_expect_policy *expect_policy;
31 33
@@ -79,6 +81,8 @@ struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
79struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name, 81struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
80 u16 l3num, 82 u16 l3num,
81 u8 protonum); 83 u8 protonum);
84void nf_conntrack_helper_put(struct nf_conntrack_helper *helper);
85
82void nf_ct_helper_init(struct nf_conntrack_helper *helper, 86void nf_ct_helper_init(struct nf_conntrack_helper *helper,
83 u16 l3num, u16 protonum, const char *name, 87 u16 l3num, u16 protonum, const char *name,
84 u16 default_port, u16 spec_port, u32 id, 88 u16 default_port, u16 spec_port, u32 id,
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 028faec8fc27..8a8bab8d7b15 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -176,7 +176,7 @@ struct nft_data_desc {
176int nft_data_init(const struct nft_ctx *ctx, 176int nft_data_init(const struct nft_ctx *ctx,
177 struct nft_data *data, unsigned int size, 177 struct nft_data *data, unsigned int size,
178 struct nft_data_desc *desc, const struct nlattr *nla); 178 struct nft_data_desc *desc, const struct nlattr *nla);
179void nft_data_uninit(const struct nft_data *data, enum nft_data_types type); 179void nft_data_release(const struct nft_data *data, enum nft_data_types type);
180int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, 180int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
181 enum nft_data_types type, unsigned int len); 181 enum nft_data_types type, unsigned int len);
182 182
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index 5929309beaa1..db85230e49c3 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -68,6 +68,9 @@ static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par)
68 if (e->ethproto != htons(ETH_P_ARP) || 68 if (e->ethproto != htons(ETH_P_ARP) ||
69 e->invflags & EBT_IPROTO) 69 e->invflags & EBT_IPROTO)
70 return -EINVAL; 70 return -EINVAL;
71 if (ebt_invalid_target(info->target))
72 return -EINVAL;
73
71 return 0; 74 return 0;
72} 75}
73 76
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 9ec0c9f908fa..9c6e619f452b 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1373,7 +1373,8 @@ static inline int ebt_obj_to_user(char __user *um, const char *_name,
1373 strlcpy(name, _name, sizeof(name)); 1373 strlcpy(name, _name, sizeof(name));
1374 if (copy_to_user(um, name, EBT_FUNCTION_MAXNAMELEN) || 1374 if (copy_to_user(um, name, EBT_FUNCTION_MAXNAMELEN) ||
1375 put_user(datasize, (int __user *)(um + EBT_FUNCTION_MAXNAMELEN)) || 1375 put_user(datasize, (int __user *)(um + EBT_FUNCTION_MAXNAMELEN)) ||
1376 xt_data_to_user(um + entrysize, data, usersize, datasize)) 1376 xt_data_to_user(um + entrysize, data, usersize, datasize,
1377 XT_ALIGN(datasize)))
1377 return -EFAULT; 1378 return -EFAULT;
1378 1379
1379 return 0; 1380 return 0;
@@ -1658,7 +1659,8 @@ static int compat_match_to_user(struct ebt_entry_match *m, void __user **dstptr,
1658 if (match->compat_to_user(cm->data, m->data)) 1659 if (match->compat_to_user(cm->data, m->data))
1659 return -EFAULT; 1660 return -EFAULT;
1660 } else { 1661 } else {
1661 if (xt_data_to_user(cm->data, m->data, match->usersize, msize)) 1662 if (xt_data_to_user(cm->data, m->data, match->usersize, msize,
1663 COMPAT_XT_ALIGN(msize)))
1662 return -EFAULT; 1664 return -EFAULT;
1663 } 1665 }
1664 1666
@@ -1687,7 +1689,8 @@ static int compat_target_to_user(struct ebt_entry_target *t,
1687 if (target->compat_to_user(cm->data, t->data)) 1689 if (target->compat_to_user(cm->data, t->data))
1688 return -EFAULT; 1690 return -EFAULT;
1689 } else { 1691 } else {
1690 if (xt_data_to_user(cm->data, t->data, target->usersize, tsize)) 1692 if (xt_data_to_user(cm->data, t->data, target->usersize, tsize,
1693 COMPAT_XT_ALIGN(tsize)))
1691 return -EFAULT; 1694 return -EFAULT;
1692 } 1695 }
1693 1696
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index d2d7bdf1d510..ad99c1ceea6f 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -849,10 +849,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
849{ 849{
850 unsigned int verdict = NF_DROP; 850 unsigned int verdict = NF_DROP;
851 851
852 if (IP_VS_FWD_METHOD(cp) != 0) { 852 if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
853 pr_err("shouldn't reach here, because the box is on the " 853 goto ignore_cp;
854 "half connection in the tun/dr module.\n");
855 }
856 854
857 /* Ensure the checksum is correct */ 855 /* Ensure the checksum is correct */
858 if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) { 856 if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
@@ -886,6 +884,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
886 ip_vs_notrack(skb); 884 ip_vs_notrack(skb);
887 else 885 else
888 ip_vs_update_conntrack(skb, cp, 0); 886 ip_vs_update_conntrack(skb, cp, 0);
887
888ignore_cp:
889 verdict = NF_ACCEPT; 889 verdict = NF_ACCEPT;
890 890
891out: 891out:
@@ -1385,8 +1385,11 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
1385 */ 1385 */
1386 cp = pp->conn_out_get(ipvs, af, skb, &iph); 1386 cp = pp->conn_out_get(ipvs, af, skb, &iph);
1387 1387
1388 if (likely(cp)) 1388 if (likely(cp)) {
1389 if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
1390 goto ignore_cp;
1389 return handle_response(af, skb, pd, cp, &iph, hooknum); 1391 return handle_response(af, skb, pd, cp, &iph, hooknum);
1392 }
1390 1393
1391 /* Check for real-server-started requests */ 1394 /* Check for real-server-started requests */
1392 if (atomic_read(&ipvs->conn_out_counter)) { 1395 if (atomic_read(&ipvs->conn_out_counter)) {
@@ -1444,9 +1447,15 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
1444 } 1447 }
1445 } 1448 }
1446 } 1449 }
1450
1451out:
1447 IP_VS_DBG_PKT(12, af, pp, skb, iph.off, 1452 IP_VS_DBG_PKT(12, af, pp, skb, iph.off,
1448 "ip_vs_out: packet continues traversal as normal"); 1453 "ip_vs_out: packet continues traversal as normal");
1449 return NF_ACCEPT; 1454 return NF_ACCEPT;
1455
1456ignore_cp:
1457 __ip_vs_conn_put(cp);
1458 goto out;
1450} 1459}
1451 1460
1452/* 1461/*
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 3a60efa7799b..7f6100ca63be 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -174,6 +174,10 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
174#endif 174#endif
175 if (h != NULL && !try_module_get(h->me)) 175 if (h != NULL && !try_module_get(h->me))
176 h = NULL; 176 h = NULL;
177 if (h != NULL && !refcount_inc_not_zero(&h->refcnt)) {
178 module_put(h->me);
179 h = NULL;
180 }
177 181
178 rcu_read_unlock(); 182 rcu_read_unlock();
179 183
@@ -181,6 +185,13 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
181} 185}
182EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get); 186EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
183 187
188void nf_conntrack_helper_put(struct nf_conntrack_helper *helper)
189{
190 refcount_dec(&helper->refcnt);
191 module_put(helper->me);
192}
193EXPORT_SYMBOL_GPL(nf_conntrack_helper_put);
194
184struct nf_conn_help * 195struct nf_conn_help *
185nf_ct_helper_ext_add(struct nf_conn *ct, 196nf_ct_helper_ext_add(struct nf_conn *ct,
186 struct nf_conntrack_helper *helper, gfp_t gfp) 197 struct nf_conntrack_helper *helper, gfp_t gfp)
@@ -417,6 +428,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
417 } 428 }
418 } 429 }
419 } 430 }
431 refcount_set(&me->refcnt, 1);
420 hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]); 432 hlist_add_head_rcu(&me->hnode, &nf_ct_helper_hash[h]);
421 nf_ct_helper_count++; 433 nf_ct_helper_count++;
422out: 434out:
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index dcf561b5c97a..9799a50bc604 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -45,6 +45,8 @@
45#include <net/netfilter/nf_conntrack_zones.h> 45#include <net/netfilter/nf_conntrack_zones.h>
46#include <net/netfilter/nf_conntrack_timestamp.h> 46#include <net/netfilter/nf_conntrack_timestamp.h>
47#include <net/netfilter/nf_conntrack_labels.h> 47#include <net/netfilter/nf_conntrack_labels.h>
48#include <net/netfilter/nf_conntrack_seqadj.h>
49#include <net/netfilter/nf_conntrack_synproxy.h>
48#ifdef CONFIG_NF_NAT_NEEDED 50#ifdef CONFIG_NF_NAT_NEEDED
49#include <net/netfilter/nf_nat_core.h> 51#include <net/netfilter/nf_nat_core.h>
50#include <net/netfilter/nf_nat_l4proto.h> 52#include <net/netfilter/nf_nat_l4proto.h>
@@ -1007,9 +1009,8 @@ static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = {
1007 1009
1008static int 1010static int
1009ctnetlink_parse_tuple(const struct nlattr * const cda[], 1011ctnetlink_parse_tuple(const struct nlattr * const cda[],
1010 struct nf_conntrack_tuple *tuple, 1012 struct nf_conntrack_tuple *tuple, u32 type,
1011 enum ctattr_type type, u_int8_t l3num, 1013 u_int8_t l3num, struct nf_conntrack_zone *zone)
1012 struct nf_conntrack_zone *zone)
1013{ 1014{
1014 struct nlattr *tb[CTA_TUPLE_MAX+1]; 1015 struct nlattr *tb[CTA_TUPLE_MAX+1];
1015 int err; 1016 int err;
@@ -1828,6 +1829,8 @@ ctnetlink_create_conntrack(struct net *net,
1828 nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); 1829 nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
1829 nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); 1830 nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
1830 nf_ct_labels_ext_add(ct); 1831 nf_ct_labels_ext_add(ct);
1832 nfct_seqadj_ext_add(ct);
1833 nfct_synproxy_ext_add(ct);
1831 1834
1832 /* we must add conntrack extensions before confirmation. */ 1835 /* we must add conntrack extensions before confirmation. */
1833 ct->status |= IPS_CONFIRMED; 1836 ct->status |= IPS_CONFIRMED;
@@ -2447,7 +2450,7 @@ static struct nfnl_ct_hook ctnetlink_glue_hook = {
2447 2450
2448static int ctnetlink_exp_dump_tuple(struct sk_buff *skb, 2451static int ctnetlink_exp_dump_tuple(struct sk_buff *skb,
2449 const struct nf_conntrack_tuple *tuple, 2452 const struct nf_conntrack_tuple *tuple,
2450 enum ctattr_expect type) 2453 u32 type)
2451{ 2454{
2452 struct nlattr *nest_parms; 2455 struct nlattr *nest_parms;
2453 2456
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index b48d6b5aae8a..ef0be325a0c6 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -409,6 +409,10 @@ nf_nat_setup_info(struct nf_conn *ct,
409{ 409{
410 struct nf_conntrack_tuple curr_tuple, new_tuple; 410 struct nf_conntrack_tuple curr_tuple, new_tuple;
411 411
412 /* Can't setup nat info for confirmed ct. */
413 if (nf_ct_is_confirmed(ct))
414 return NF_ACCEPT;
415
412 NF_CT_ASSERT(maniptype == NF_NAT_MANIP_SRC || 416 NF_CT_ASSERT(maniptype == NF_NAT_MANIP_SRC ||
413 maniptype == NF_NAT_MANIP_DST); 417 maniptype == NF_NAT_MANIP_DST);
414 BUG_ON(nf_nat_initialized(ct, maniptype)); 418 BUG_ON(nf_nat_initialized(ct, maniptype));
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 559225029740..da314be0c048 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3367,35 +3367,50 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
3367 return nf_tables_fill_setelem(args->skb, set, elem); 3367 return nf_tables_fill_setelem(args->skb, set, elem);
3368} 3368}
3369 3369
3370struct nft_set_dump_ctx {
3371 const struct nft_set *set;
3372 struct nft_ctx ctx;
3373};
3374
3370static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) 3375static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3371{ 3376{
3377 struct nft_set_dump_ctx *dump_ctx = cb->data;
3372 struct net *net = sock_net(skb->sk); 3378 struct net *net = sock_net(skb->sk);
3373 u8 genmask = nft_genmask_cur(net); 3379 struct nft_af_info *afi;
3380 struct nft_table *table;
3374 struct nft_set *set; 3381 struct nft_set *set;
3375 struct nft_set_dump_args args; 3382 struct nft_set_dump_args args;
3376 struct nft_ctx ctx; 3383 bool set_found = false;
3377 struct nlattr *nla[NFTA_SET_ELEM_LIST_MAX + 1];
3378 struct nfgenmsg *nfmsg; 3384 struct nfgenmsg *nfmsg;
3379 struct nlmsghdr *nlh; 3385 struct nlmsghdr *nlh;
3380 struct nlattr *nest; 3386 struct nlattr *nest;
3381 u32 portid, seq; 3387 u32 portid, seq;
3382 int event, err; 3388 int event;
3383 3389
3384 err = nlmsg_parse(cb->nlh, sizeof(struct nfgenmsg), nla, 3390 rcu_read_lock();
3385 NFTA_SET_ELEM_LIST_MAX, nft_set_elem_list_policy, 3391 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
3386 NULL); 3392 if (afi != dump_ctx->ctx.afi)
3387 if (err < 0) 3393 continue;
3388 return err;
3389 3394
3390 err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh, 3395 list_for_each_entry_rcu(table, &afi->tables, list) {
3391 (void *)nla, genmask); 3396 if (table != dump_ctx->ctx.table)
3392 if (err < 0) 3397 continue;
3393 return err;
3394 3398
3395 set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], 3399 list_for_each_entry_rcu(set, &table->sets, list) {
3396 genmask); 3400 if (set == dump_ctx->set) {
3397 if (IS_ERR(set)) 3401 set_found = true;
3398 return PTR_ERR(set); 3402 break;
3403 }
3404 }
3405 break;
3406 }
3407 break;
3408 }
3409
3410 if (!set_found) {
3411 rcu_read_unlock();
3412 return -ENOENT;
3413 }
3399 3414
3400 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWSETELEM); 3415 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWSETELEM);
3401 portid = NETLINK_CB(cb->skb).portid; 3416 portid = NETLINK_CB(cb->skb).portid;
@@ -3407,11 +3422,11 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3407 goto nla_put_failure; 3422 goto nla_put_failure;
3408 3423
3409 nfmsg = nlmsg_data(nlh); 3424 nfmsg = nlmsg_data(nlh);
3410 nfmsg->nfgen_family = ctx.afi->family; 3425 nfmsg->nfgen_family = afi->family;
3411 nfmsg->version = NFNETLINK_V0; 3426 nfmsg->version = NFNETLINK_V0;
3412 nfmsg->res_id = htons(ctx.net->nft.base_seq & 0xffff); 3427 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
3413 3428
3414 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, ctx.table->name)) 3429 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, table->name))
3415 goto nla_put_failure; 3430 goto nla_put_failure;
3416 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_SET, set->name)) 3431 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_SET, set->name))
3417 goto nla_put_failure; 3432 goto nla_put_failure;
@@ -3422,12 +3437,13 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3422 3437
3423 args.cb = cb; 3438 args.cb = cb;
3424 args.skb = skb; 3439 args.skb = skb;
3425 args.iter.genmask = nft_genmask_cur(ctx.net); 3440 args.iter.genmask = nft_genmask_cur(net);
3426 args.iter.skip = cb->args[0]; 3441 args.iter.skip = cb->args[0];
3427 args.iter.count = 0; 3442 args.iter.count = 0;
3428 args.iter.err = 0; 3443 args.iter.err = 0;
3429 args.iter.fn = nf_tables_dump_setelem; 3444 args.iter.fn = nf_tables_dump_setelem;
3430 set->ops->walk(&ctx, set, &args.iter); 3445 set->ops->walk(&dump_ctx->ctx, set, &args.iter);
3446 rcu_read_unlock();
3431 3447
3432 nla_nest_end(skb, nest); 3448 nla_nest_end(skb, nest);
3433 nlmsg_end(skb, nlh); 3449 nlmsg_end(skb, nlh);
@@ -3441,9 +3457,16 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
3441 return skb->len; 3457 return skb->len;
3442 3458
3443nla_put_failure: 3459nla_put_failure:
3460 rcu_read_unlock();
3444 return -ENOSPC; 3461 return -ENOSPC;
3445} 3462}
3446 3463
3464static int nf_tables_dump_set_done(struct netlink_callback *cb)
3465{
3466 kfree(cb->data);
3467 return 0;
3468}
3469
3447static int nf_tables_getsetelem(struct net *net, struct sock *nlsk, 3470static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
3448 struct sk_buff *skb, const struct nlmsghdr *nlh, 3471 struct sk_buff *skb, const struct nlmsghdr *nlh,
3449 const struct nlattr * const nla[]) 3472 const struct nlattr * const nla[])
@@ -3465,7 +3488,18 @@ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
3465 if (nlh->nlmsg_flags & NLM_F_DUMP) { 3488 if (nlh->nlmsg_flags & NLM_F_DUMP) {
3466 struct netlink_dump_control c = { 3489 struct netlink_dump_control c = {
3467 .dump = nf_tables_dump_set, 3490 .dump = nf_tables_dump_set,
3491 .done = nf_tables_dump_set_done,
3468 }; 3492 };
3493 struct nft_set_dump_ctx *dump_ctx;
3494
3495 dump_ctx = kmalloc(sizeof(*dump_ctx), GFP_KERNEL);
3496 if (!dump_ctx)
3497 return -ENOMEM;
3498
3499 dump_ctx->set = set;
3500 dump_ctx->ctx = ctx;
3501
3502 c.data = dump_ctx;
3469 return netlink_dump_start(nlsk, skb, nlh, &c); 3503 return netlink_dump_start(nlsk, skb, nlh, &c);
3470 } 3504 }
3471 return -EOPNOTSUPP; 3505 return -EOPNOTSUPP;
@@ -3593,9 +3627,9 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
3593{ 3627{
3594 struct nft_set_ext *ext = nft_set_elem_ext(set, elem); 3628 struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
3595 3629
3596 nft_data_uninit(nft_set_ext_key(ext), NFT_DATA_VALUE); 3630 nft_data_release(nft_set_ext_key(ext), NFT_DATA_VALUE);
3597 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) 3631 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
3598 nft_data_uninit(nft_set_ext_data(ext), set->dtype); 3632 nft_data_release(nft_set_ext_data(ext), set->dtype);
3599 if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) 3633 if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
3600 nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext)); 3634 nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
3601 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF)) 3635 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
@@ -3604,6 +3638,18 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
3604} 3638}
3605EXPORT_SYMBOL_GPL(nft_set_elem_destroy); 3639EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
3606 3640
3641/* Only called from commit path, nft_set_elem_deactivate() already deals with
3642 * the refcounting from the preparation phase.
3643 */
3644static void nf_tables_set_elem_destroy(const struct nft_set *set, void *elem)
3645{
3646 struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
3647
3648 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR))
3649 nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext));
3650 kfree(elem);
3651}
3652
3607static int nft_setelem_parse_flags(const struct nft_set *set, 3653static int nft_setelem_parse_flags(const struct nft_set *set,
3608 const struct nlattr *attr, u32 *flags) 3654 const struct nlattr *attr, u32 *flags)
3609{ 3655{
@@ -3815,9 +3861,9 @@ err4:
3815 kfree(elem.priv); 3861 kfree(elem.priv);
3816err3: 3862err3:
3817 if (nla[NFTA_SET_ELEM_DATA] != NULL) 3863 if (nla[NFTA_SET_ELEM_DATA] != NULL)
3818 nft_data_uninit(&data, d2.type); 3864 nft_data_release(&data, d2.type);
3819err2: 3865err2:
3820 nft_data_uninit(&elem.key.val, d1.type); 3866 nft_data_release(&elem.key.val, d1.type);
3821err1: 3867err1:
3822 return err; 3868 return err;
3823} 3869}
@@ -3862,6 +3908,53 @@ static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
3862 return err; 3908 return err;
3863} 3909}
3864 3910
3911/**
3912 * nft_data_hold - hold a nft_data item
3913 *
3914 * @data: struct nft_data to release
3915 * @type: type of data
3916 *
3917 * Hold a nft_data item. NFT_DATA_VALUE types can be silently discarded,
3918 * NFT_DATA_VERDICT bumps the reference to chains in case of NFT_JUMP and
3919 * NFT_GOTO verdicts. This function must be called on active data objects
3920 * from the second phase of the commit protocol.
3921 */
3922static void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
3923{
3924 if (type == NFT_DATA_VERDICT) {
3925 switch (data->verdict.code) {
3926 case NFT_JUMP:
3927 case NFT_GOTO:
3928 data->verdict.chain->use++;
3929 break;
3930 }
3931 }
3932}
3933
3934static void nft_set_elem_activate(const struct net *net,
3935 const struct nft_set *set,
3936 struct nft_set_elem *elem)
3937{
3938 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
3939
3940 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
3941 nft_data_hold(nft_set_ext_data(ext), set->dtype);
3942 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
3943 (*nft_set_ext_obj(ext))->use++;
3944}
3945
3946static void nft_set_elem_deactivate(const struct net *net,
3947 const struct nft_set *set,
3948 struct nft_set_elem *elem)
3949{
3950 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
3951
3952 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
3953 nft_data_release(nft_set_ext_data(ext), set->dtype);
3954 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
3955 (*nft_set_ext_obj(ext))->use--;
3956}
3957
3865static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, 3958static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
3866 const struct nlattr *attr) 3959 const struct nlattr *attr)
3867{ 3960{
@@ -3927,6 +4020,8 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
3927 kfree(elem.priv); 4020 kfree(elem.priv);
3928 elem.priv = priv; 4021 elem.priv = priv;
3929 4022
4023 nft_set_elem_deactivate(ctx->net, set, &elem);
4024
3930 nft_trans_elem(trans) = elem; 4025 nft_trans_elem(trans) = elem;
3931 list_add_tail(&trans->list, &ctx->net->nft.commit_list); 4026 list_add_tail(&trans->list, &ctx->net->nft.commit_list);
3932 return 0; 4027 return 0;
@@ -3936,7 +4031,7 @@ err4:
3936err3: 4031err3:
3937 kfree(elem.priv); 4032 kfree(elem.priv);
3938err2: 4033err2:
3939 nft_data_uninit(&elem.key.val, desc.type); 4034 nft_data_release(&elem.key.val, desc.type);
3940err1: 4035err1:
3941 return err; 4036 return err;
3942} 4037}
@@ -4743,8 +4838,8 @@ static void nf_tables_commit_release(struct nft_trans *trans)
4743 nft_set_destroy(nft_trans_set(trans)); 4838 nft_set_destroy(nft_trans_set(trans));
4744 break; 4839 break;
4745 case NFT_MSG_DELSETELEM: 4840 case NFT_MSG_DELSETELEM:
4746 nft_set_elem_destroy(nft_trans_elem_set(trans), 4841 nf_tables_set_elem_destroy(nft_trans_elem_set(trans),
4747 nft_trans_elem(trans).priv, true); 4842 nft_trans_elem(trans).priv);
4748 break; 4843 break;
4749 case NFT_MSG_DELOBJ: 4844 case NFT_MSG_DELOBJ:
4750 nft_obj_destroy(nft_trans_obj(trans)); 4845 nft_obj_destroy(nft_trans_obj(trans));
@@ -4979,6 +5074,7 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb)
4979 case NFT_MSG_DELSETELEM: 5074 case NFT_MSG_DELSETELEM:
4980 te = (struct nft_trans_elem *)trans->data; 5075 te = (struct nft_trans_elem *)trans->data;
4981 5076
5077 nft_set_elem_activate(net, te->set, &te->elem);
4982 te->set->ops->activate(net, te->set, &te->elem); 5078 te->set->ops->activate(net, te->set, &te->elem);
4983 te->set->ndeact--; 5079 te->set->ndeact--;
4984 5080
@@ -5464,7 +5560,7 @@ int nft_data_init(const struct nft_ctx *ctx,
5464EXPORT_SYMBOL_GPL(nft_data_init); 5560EXPORT_SYMBOL_GPL(nft_data_init);
5465 5561
5466/** 5562/**
5467 * nft_data_uninit - release a nft_data item 5563 * nft_data_release - release a nft_data item
5468 * 5564 *
5469 * @data: struct nft_data to release 5565 * @data: struct nft_data to release
5470 * @type: type of data 5566 * @type: type of data
@@ -5472,7 +5568,7 @@ EXPORT_SYMBOL_GPL(nft_data_init);
5472 * Release a nft_data item. NFT_DATA_VALUE types can be silently discarded, 5568 * Release a nft_data item. NFT_DATA_VALUE types can be silently discarded,
5473 * all others need to be released by calling this function. 5569 * all others need to be released by calling this function.
5474 */ 5570 */
5475void nft_data_uninit(const struct nft_data *data, enum nft_data_types type) 5571void nft_data_release(const struct nft_data *data, enum nft_data_types type)
5476{ 5572{
5477 if (type < NFT_DATA_VERDICT) 5573 if (type < NFT_DATA_VERDICT)
5478 return; 5574 return;
@@ -5483,7 +5579,7 @@ void nft_data_uninit(const struct nft_data *data, enum nft_data_types type)
5483 WARN_ON(1); 5579 WARN_ON(1);
5484 } 5580 }
5485} 5581}
5486EXPORT_SYMBOL_GPL(nft_data_uninit); 5582EXPORT_SYMBOL_GPL(nft_data_release);
5487 5583
5488int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data, 5584int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
5489 enum nft_data_types type, unsigned int len) 5585 enum nft_data_types type, unsigned int len)
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
index 950bf6eadc65..be678a323598 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -686,6 +686,7 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
686 tuple_set = true; 686 tuple_set = true;
687 } 687 }
688 688
689 ret = -ENOENT;
689 list_for_each_entry_safe(nlcth, n, &nfnl_cthelper_list, list) { 690 list_for_each_entry_safe(nlcth, n, &nfnl_cthelper_list, list) {
690 cur = &nlcth->helper; 691 cur = &nlcth->helper;
691 j++; 692 j++;
@@ -699,16 +700,20 @@ static int nfnl_cthelper_del(struct net *net, struct sock *nfnl,
699 tuple.dst.protonum != cur->tuple.dst.protonum)) 700 tuple.dst.protonum != cur->tuple.dst.protonum))
700 continue; 701 continue;
701 702
702 found = true; 703 if (refcount_dec_if_one(&cur->refcnt)) {
703 nf_conntrack_helper_unregister(cur); 704 found = true;
704 kfree(cur->expect_policy); 705 nf_conntrack_helper_unregister(cur);
706 kfree(cur->expect_policy);
705 707
706 list_del(&nlcth->list); 708 list_del(&nlcth->list);
707 kfree(nlcth); 709 kfree(nlcth);
710 } else {
711 ret = -EBUSY;
712 }
708 } 713 }
709 714
710 /* Make sure we return success if we flush and there is no helpers */ 715 /* Make sure we return success if we flush and there is no helpers */
711 return (found || j == 0) ? 0 : -ENOENT; 716 return (found || j == 0) ? 0 : ret;
712} 717}
713 718
714static const struct nla_policy nfnl_cthelper_policy[NFCTH_MAX+1] = { 719static const struct nla_policy nfnl_cthelper_policy[NFCTH_MAX+1] = {
diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
index 877d9acd91ef..fff8073e2a56 100644
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -83,17 +83,26 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
83 tb[NFTA_BITWISE_MASK]); 83 tb[NFTA_BITWISE_MASK]);
84 if (err < 0) 84 if (err < 0)
85 return err; 85 return err;
86 if (d1.len != priv->len) 86 if (d1.len != priv->len) {
87 return -EINVAL; 87 err = -EINVAL;
88 goto err1;
89 }
88 90
89 err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2, 91 err = nft_data_init(NULL, &priv->xor, sizeof(priv->xor), &d2,
90 tb[NFTA_BITWISE_XOR]); 92 tb[NFTA_BITWISE_XOR]);
91 if (err < 0) 93 if (err < 0)
92 return err; 94 goto err1;
93 if (d2.len != priv->len) 95 if (d2.len != priv->len) {
94 return -EINVAL; 96 err = -EINVAL;
97 goto err2;
98 }
95 99
96 return 0; 100 return 0;
101err2:
102 nft_data_release(&priv->xor, d2.type);
103err1:
104 nft_data_release(&priv->mask, d1.type);
105 return err;
97} 106}
98 107
99static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr) 108static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr)
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
index 2b96effeadc1..c2945eb3397c 100644
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -201,10 +201,18 @@ nft_cmp_select_ops(const struct nft_ctx *ctx, const struct nlattr * const tb[])
201 if (err < 0) 201 if (err < 0)
202 return ERR_PTR(err); 202 return ERR_PTR(err);
203 203
204 if (desc.type != NFT_DATA_VALUE) {
205 err = -EINVAL;
206 goto err1;
207 }
208
204 if (desc.len <= sizeof(u32) && op == NFT_CMP_EQ) 209 if (desc.len <= sizeof(u32) && op == NFT_CMP_EQ)
205 return &nft_cmp_fast_ops; 210 return &nft_cmp_fast_ops;
206 else 211
207 return &nft_cmp_ops; 212 return &nft_cmp_ops;
213err1:
214 nft_data_release(&data, desc.type);
215 return ERR_PTR(-EINVAL);
208} 216}
209 217
210struct nft_expr_type nft_cmp_type __read_mostly = { 218struct nft_expr_type nft_cmp_type __read_mostly = {
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index a34ceb38fc55..1678e9e75e8e 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -826,9 +826,9 @@ static void nft_ct_helper_obj_destroy(struct nft_object *obj)
826 struct nft_ct_helper_obj *priv = nft_obj_data(obj); 826 struct nft_ct_helper_obj *priv = nft_obj_data(obj);
827 827
828 if (priv->helper4) 828 if (priv->helper4)
829 module_put(priv->helper4->me); 829 nf_conntrack_helper_put(priv->helper4);
830 if (priv->helper6) 830 if (priv->helper6)
831 module_put(priv->helper6->me); 831 nf_conntrack_helper_put(priv->helper6);
832} 832}
833 833
834static void nft_ct_helper_obj_eval(struct nft_object *obj, 834static void nft_ct_helper_obj_eval(struct nft_object *obj,
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
index 728baf88295a..4717d7796927 100644
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -65,7 +65,7 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
65 return 0; 65 return 0;
66 66
67err1: 67err1:
68 nft_data_uninit(&priv->data, desc.type); 68 nft_data_release(&priv->data, desc.type);
69 return err; 69 return err;
70} 70}
71 71
@@ -73,7 +73,8 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
73 const struct nft_expr *expr) 73 const struct nft_expr *expr)
74{ 74{
75 const struct nft_immediate_expr *priv = nft_expr_priv(expr); 75 const struct nft_immediate_expr *priv = nft_expr_priv(expr);
76 return nft_data_uninit(&priv->data, nft_dreg_to_type(priv->dreg)); 76
77 return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
77} 78}
78 79
79static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr) 80static int nft_immediate_dump(struct sk_buff *skb, const struct nft_expr *expr)
diff --git a/net/netfilter/nft_range.c b/net/netfilter/nft_range.c
index 9edc74eedc10..cedb96c3619f 100644
--- a/net/netfilter/nft_range.c
+++ b/net/netfilter/nft_range.c
@@ -102,9 +102,9 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
102 priv->len = desc_from.len; 102 priv->len = desc_from.len;
103 return 0; 103 return 0;
104err2: 104err2:
105 nft_data_uninit(&priv->data_to, desc_to.type); 105 nft_data_release(&priv->data_to, desc_to.type);
106err1: 106err1:
107 nft_data_uninit(&priv->data_from, desc_from.type); 107 nft_data_release(&priv->data_from, desc_from.type);
108 return err; 108 return err;
109} 109}
110 110
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index 8ec086b6b56b..3d3a6df4ce70 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -222,7 +222,7 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
222 struct nft_set_elem elem; 222 struct nft_set_elem elem;
223 int err; 223 int err;
224 224
225 err = rhashtable_walk_init(&priv->ht, &hti, GFP_KERNEL); 225 err = rhashtable_walk_init(&priv->ht, &hti, GFP_ATOMIC);
226 iter->err = err; 226 iter->err = err;
227 if (err) 227 if (err)
228 return; 228 return;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8876b7da6884..1770c1d9b37f 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -283,28 +283,30 @@ static int xt_obj_to_user(u16 __user *psize, u16 size,
283 &U->u.user.revision, K->u.kernel.TYPE->revision) 283 &U->u.user.revision, K->u.kernel.TYPE->revision)
284 284
285int xt_data_to_user(void __user *dst, const void *src, 285int xt_data_to_user(void __user *dst, const void *src,
286 int usersize, int size) 286 int usersize, int size, int aligned_size)
287{ 287{
288 usersize = usersize ? : size; 288 usersize = usersize ? : size;
289 if (copy_to_user(dst, src, usersize)) 289 if (copy_to_user(dst, src, usersize))
290 return -EFAULT; 290 return -EFAULT;
291 if (usersize != size && clear_user(dst + usersize, size - usersize)) 291 if (usersize != aligned_size &&
292 clear_user(dst + usersize, aligned_size - usersize))
292 return -EFAULT; 293 return -EFAULT;
293 294
294 return 0; 295 return 0;
295} 296}
296EXPORT_SYMBOL_GPL(xt_data_to_user); 297EXPORT_SYMBOL_GPL(xt_data_to_user);
297 298
298#define XT_DATA_TO_USER(U, K, TYPE, C_SIZE) \ 299#define XT_DATA_TO_USER(U, K, TYPE) \
299 xt_data_to_user(U->data, K->data, \ 300 xt_data_to_user(U->data, K->data, \
300 K->u.kernel.TYPE->usersize, \ 301 K->u.kernel.TYPE->usersize, \
301 C_SIZE ? : K->u.kernel.TYPE->TYPE##size) 302 K->u.kernel.TYPE->TYPE##size, \
303 XT_ALIGN(K->u.kernel.TYPE->TYPE##size))
302 304
303int xt_match_to_user(const struct xt_entry_match *m, 305int xt_match_to_user(const struct xt_entry_match *m,
304 struct xt_entry_match __user *u) 306 struct xt_entry_match __user *u)
305{ 307{
306 return XT_OBJ_TO_USER(u, m, match, 0) || 308 return XT_OBJ_TO_USER(u, m, match, 0) ||
307 XT_DATA_TO_USER(u, m, match, 0); 309 XT_DATA_TO_USER(u, m, match);
308} 310}
309EXPORT_SYMBOL_GPL(xt_match_to_user); 311EXPORT_SYMBOL_GPL(xt_match_to_user);
310 312
@@ -312,7 +314,7 @@ int xt_target_to_user(const struct xt_entry_target *t,
312 struct xt_entry_target __user *u) 314 struct xt_entry_target __user *u)
313{ 315{
314 return XT_OBJ_TO_USER(u, t, target, 0) || 316 return XT_OBJ_TO_USER(u, t, target, 0) ||
315 XT_DATA_TO_USER(u, t, target, 0); 317 XT_DATA_TO_USER(u, t, target);
316} 318}
317EXPORT_SYMBOL_GPL(xt_target_to_user); 319EXPORT_SYMBOL_GPL(xt_target_to_user);
318 320
@@ -611,6 +613,12 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
611} 613}
612EXPORT_SYMBOL_GPL(xt_compat_match_from_user); 614EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
613 615
616#define COMPAT_XT_DATA_TO_USER(U, K, TYPE, C_SIZE) \
617 xt_data_to_user(U->data, K->data, \
618 K->u.kernel.TYPE->usersize, \
619 C_SIZE, \
620 COMPAT_XT_ALIGN(C_SIZE))
621
614int xt_compat_match_to_user(const struct xt_entry_match *m, 622int xt_compat_match_to_user(const struct xt_entry_match *m,
615 void __user **dstptr, unsigned int *size) 623 void __user **dstptr, unsigned int *size)
616{ 624{
@@ -626,7 +634,7 @@ int xt_compat_match_to_user(const struct xt_entry_match *m,
626 if (match->compat_to_user((void __user *)cm->data, m->data)) 634 if (match->compat_to_user((void __user *)cm->data, m->data))
627 return -EFAULT; 635 return -EFAULT;
628 } else { 636 } else {
629 if (XT_DATA_TO_USER(cm, m, match, msize - sizeof(*cm))) 637 if (COMPAT_XT_DATA_TO_USER(cm, m, match, msize - sizeof(*cm)))
630 return -EFAULT; 638 return -EFAULT;
631 } 639 }
632 640
@@ -972,7 +980,7 @@ int xt_compat_target_to_user(const struct xt_entry_target *t,
972 if (target->compat_to_user((void __user *)ct->data, t->data)) 980 if (target->compat_to_user((void __user *)ct->data, t->data))
973 return -EFAULT; 981 return -EFAULT;
974 } else { 982 } else {
975 if (XT_DATA_TO_USER(ct, t, target, tsize - sizeof(*ct))) 983 if (COMPAT_XT_DATA_TO_USER(ct, t, target, tsize - sizeof(*ct)))
976 return -EFAULT; 984 return -EFAULT;
977 } 985 }
978 986
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index bb7ad82dcd56..623ef37de886 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -96,7 +96,7 @@ xt_ct_set_helper(struct nf_conn *ct, const char *helper_name,
96 96
97 help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); 97 help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL);
98 if (help == NULL) { 98 if (help == NULL) {
99 module_put(helper->me); 99 nf_conntrack_helper_put(helper);
100 return -ENOMEM; 100 return -ENOMEM;
101 } 101 }
102 102
@@ -263,7 +263,7 @@ out:
263err4: 263err4:
264 help = nfct_help(ct); 264 help = nfct_help(ct);
265 if (help) 265 if (help)
266 module_put(help->helper->me); 266 nf_conntrack_helper_put(help->helper);
267err3: 267err3:
268 nf_ct_tmpl_free(ct); 268 nf_ct_tmpl_free(ct);
269err2: 269err2:
@@ -346,7 +346,7 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
346 if (ct) { 346 if (ct) {
347 help = nfct_help(ct); 347 help = nfct_help(ct);
348 if (help) 348 if (help)
349 module_put(help->helper->me); 349 nf_conntrack_helper_put(help->helper);
350 350
351 nf_ct_netns_put(par->net, par->family); 351 nf_ct_netns_put(par->net, par->family);
352 352
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
index bf602e33c40a..08679ebb3068 100644
--- a/net/openvswitch/conntrack.c
+++ b/net/openvswitch/conntrack.c
@@ -1123,7 +1123,7 @@ static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
1123 1123
1124 help = nf_ct_helper_ext_add(info->ct, helper, GFP_KERNEL); 1124 help = nf_ct_helper_ext_add(info->ct, helper, GFP_KERNEL);
1125 if (!help) { 1125 if (!help) {
1126 module_put(helper->me); 1126 nf_conntrack_helper_put(helper);
1127 return -ENOMEM; 1127 return -ENOMEM;
1128 } 1128 }
1129 1129
@@ -1584,7 +1584,7 @@ void ovs_ct_free_action(const struct nlattr *a)
1584static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info) 1584static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
1585{ 1585{
1586 if (ct_info->helper) 1586 if (ct_info->helper)
1587 module_put(ct_info->helper->me); 1587 nf_conntrack_helper_put(ct_info->helper);
1588 if (ct_info->ct) 1588 if (ct_info->ct)
1589 nf_ct_tmpl_free(ct_info->ct); 1589 nf_ct_tmpl_free(ct_info->ct);
1590} 1590}