summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-06-11 17:24:32 -0400
committerDavid S. Miller <davem@davemloft.net>2018-06-11 17:24:32 -0400
commita08ce73ba0a89be9f1418cba45fe94b39f9b73af (patch)
treea16d762ecdec50145e8e11f4f11cae2490f919e6 /net
parent349b71d6f427ff8211adf50839dbbff3f27c1805 (diff)
parentd8e87fc6d11c31525430a388317b52f4a98a5328 (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: 1) Reject non-null terminated helper names from xt_CT, from Gao Feng. 2) Fix KASAN splat due to out-of-bound access from commit phase, from Alexey Kodanev. 3) Missing conntrack hook registration on IPVS FTP helper, from Julian Anastasov. 4) Incorrect skbuff allocation size in bridge nft_reject, from Taehee Yoo. 5) Fix inverted check on packet xmit to non-local addresses, also from Julian. 6) Fix ebtables alignment compat problems, from Alin Nastac. 7) Hook mask checks are not correct in xt_set, from Serhey Popovych. 8) Fix timeout listing of element in ipsets, from Jozsef. 9) Cap maximum timeout value in ipset, also from Jozsef. 10) Don't allow family option for hash:mac sets, from Florent Fourcot. 11) Restrict ebtables to work with NFPROTO_BRIDGE targets only, this Florian. 12) Another bug reported by KASAN in the rbtree set backend, from Taehee Yoo. 13) Missing __IPS_MAX_BIT update doesn't include IPS_OFFLOAD_BIT. From Gao Feng. 14) Missing initialization of match/target in ebtables, from Florian Westphal. 15) Remove useless nft_dup.h file in include path, from C. Labbe. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/netfilter/ebtables.c25
-rw-r--r--net/bridge/netfilter/nft_reject_bridge.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c1
-rw-r--r--net/ipv6/netfilter/ip6_tables.c1
-rw-r--r--net/netfilter/ipset/ip_set_hash_gen.h5
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c2
-rw-r--r--net/netfilter/nf_tables_api.c11
-rw-r--r--net/netfilter/nft_set_rbtree.c2
-rw-r--r--net/netfilter/xt_CT.c10
-rw-r--r--net/netfilter/xt_set.c10
11 files changed, 54 insertions, 19 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 28f68a2ec911..bcec377b07e7 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -411,6 +411,12 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
411 watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0); 411 watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0);
412 if (IS_ERR(watcher)) 412 if (IS_ERR(watcher))
413 return PTR_ERR(watcher); 413 return PTR_ERR(watcher);
414
415 if (watcher->family != NFPROTO_BRIDGE) {
416 module_put(watcher->me);
417 return -ENOENT;
418 }
419
414 w->u.watcher = watcher; 420 w->u.watcher = watcher;
415 421
416 par->target = watcher; 422 par->target = watcher;
@@ -709,6 +715,8 @@ ebt_check_entry(struct ebt_entry *e, struct net *net,
709 } 715 }
710 i = 0; 716 i = 0;
711 717
718 memset(&mtpar, 0, sizeof(mtpar));
719 memset(&tgpar, 0, sizeof(tgpar));
712 mtpar.net = tgpar.net = net; 720 mtpar.net = tgpar.net = net;
713 mtpar.table = tgpar.table = name; 721 mtpar.table = tgpar.table = name;
714 mtpar.entryinfo = tgpar.entryinfo = e; 722 mtpar.entryinfo = tgpar.entryinfo = e;
@@ -730,6 +738,13 @@ ebt_check_entry(struct ebt_entry *e, struct net *net,
730 goto cleanup_watchers; 738 goto cleanup_watchers;
731 } 739 }
732 740
741 /* Reject UNSPEC, xtables verdicts/return values are incompatible */
742 if (target->family != NFPROTO_BRIDGE) {
743 module_put(target->me);
744 ret = -ENOENT;
745 goto cleanup_watchers;
746 }
747
733 t->u.target = target; 748 t->u.target = target;
734 if (t->u.target == &ebt_standard_target) { 749 if (t->u.target == &ebt_standard_target) {
735 if (gap < sizeof(struct ebt_standard_target)) { 750 if (gap < sizeof(struct ebt_standard_target)) {
@@ -1605,16 +1620,16 @@ struct compat_ebt_entry_mwt {
1605 compat_uptr_t ptr; 1620 compat_uptr_t ptr;
1606 } u; 1621 } u;
1607 compat_uint_t match_size; 1622 compat_uint_t match_size;
1608 compat_uint_t data[0]; 1623 compat_uint_t data[0] __attribute__ ((aligned (__alignof__(struct compat_ebt_replace))));
1609}; 1624};
1610 1625
1611/* account for possible padding between match_size and ->data */ 1626/* account for possible padding between match_size and ->data */
1612static int ebt_compat_entry_padsize(void) 1627static int ebt_compat_entry_padsize(void)
1613{ 1628{
1614 BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) < 1629 BUILD_BUG_ON(sizeof(struct ebt_entry_match) <
1615 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt))); 1630 sizeof(struct compat_ebt_entry_mwt));
1616 return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) - 1631 return (int) sizeof(struct ebt_entry_match) -
1617 COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)); 1632 sizeof(struct compat_ebt_entry_mwt);
1618} 1633}
1619 1634
1620static int ebt_compat_match_offset(const struct xt_match *match, 1635static int ebt_compat_match_offset(const struct xt_match *match,
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index eaf05de37f75..6de981270566 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -261,7 +261,7 @@ static void nft_reject_br_send_v6_unreach(struct net *net,
261 if (!reject6_br_csum_ok(oldskb, hook)) 261 if (!reject6_br_csum_ok(oldskb, hook))
262 return; 262 return;
263 263
264 nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmp6hdr) + 264 nskb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr) +
265 LL_MAX_HEADER + len, GFP_ATOMIC); 265 LL_MAX_HEADER + len, GFP_ATOMIC);
266 if (!nskb) 266 if (!nskb)
267 return; 267 return;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 38ab97b0a2ec..ca0dad90803a 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -531,6 +531,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
531 return -ENOMEM; 531 return -ENOMEM;
532 532
533 j = 0; 533 j = 0;
534 memset(&mtpar, 0, sizeof(mtpar));
534 mtpar.net = net; 535 mtpar.net = net;
535 mtpar.table = name; 536 mtpar.table = name;
536 mtpar.entryinfo = &e->ip; 537 mtpar.entryinfo = &e->ip;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 0758b5bcfb29..7eab959734bc 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -550,6 +550,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
550 return -ENOMEM; 550 return -ENOMEM;
551 551
552 j = 0; 552 j = 0;
553 memset(&mtpar, 0, sizeof(mtpar));
553 mtpar.net = net; 554 mtpar.net = net;
554 mtpar.table = name; 555 mtpar.table = name;
555 mtpar.entryinfo = &e->ipv6; 556 mtpar.entryinfo = &e->ipv6;
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index bbad940c0137..8a33dac4e805 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -1234,7 +1234,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
1234 pr_debug("Create set %s with family %s\n", 1234 pr_debug("Create set %s with family %s\n",
1235 set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6"); 1235 set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
1236 1236
1237#ifndef IP_SET_PROTO_UNDEF 1237#ifdef IP_SET_PROTO_UNDEF
1238 if (set->family != NFPROTO_UNSPEC)
1239 return -IPSET_ERR_INVALID_FAMILY;
1240#else
1238 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) 1241 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
1239 return -IPSET_ERR_INVALID_FAMILY; 1242 return -IPSET_ERR_INVALID_FAMILY;
1240#endif 1243#endif
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 0c03c0e16a96..dd21782e2f12 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -839,6 +839,9 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
839 * For now only for NAT! 839 * For now only for NAT!
840 */ 840 */
841 ip_vs_rs_hash(ipvs, dest); 841 ip_vs_rs_hash(ipvs, dest);
842 /* FTP-NAT requires conntrack for mangling */
843 if (svc->port == FTPPORT)
844 ip_vs_register_conntrack(svc);
842 } 845 }
843 atomic_set(&dest->conn_flags, conn_flags); 846 atomic_set(&dest->conn_flags, conn_flags);
844 847
@@ -1462,6 +1465,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
1462 */ 1465 */
1463static void ip_vs_unlink_service(struct ip_vs_service *svc, bool cleanup) 1466static void ip_vs_unlink_service(struct ip_vs_service *svc, bool cleanup)
1464{ 1467{
1468 ip_vs_unregister_conntrack(svc);
1465 /* Hold svc to avoid double release from dest_trash */ 1469 /* Hold svc to avoid double release from dest_trash */
1466 atomic_inc(&svc->refcnt); 1470 atomic_inc(&svc->refcnt);
1467 /* 1471 /*
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index ba0a0fd045c8..473cce2a5231 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -168,7 +168,7 @@ static inline bool crosses_local_route_boundary(int skb_af, struct sk_buff *skb,
168 bool new_rt_is_local) 168 bool new_rt_is_local)
169{ 169{
170 bool rt_mode_allow_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL); 170 bool rt_mode_allow_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL);
171 bool rt_mode_allow_non_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL); 171 bool rt_mode_allow_non_local = !!(rt_mode & IP_VS_RT_MODE_NON_LOCAL);
172 bool rt_mode_allow_redirect = !!(rt_mode & IP_VS_RT_MODE_RDR); 172 bool rt_mode_allow_redirect = !!(rt_mode & IP_VS_RT_MODE_RDR);
173 bool source_is_loopback; 173 bool source_is_loopback;
174 bool old_rt_is_local; 174 bool old_rt_is_local;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index ca4c4d994ddb..7979095b69b0 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2890,12 +2890,13 @@ static struct nft_set *nft_set_lookup_byid(const struct net *net,
2890 u32 id = ntohl(nla_get_be32(nla)); 2890 u32 id = ntohl(nla_get_be32(nla));
2891 2891
2892 list_for_each_entry(trans, &net->nft.commit_list, list) { 2892 list_for_each_entry(trans, &net->nft.commit_list, list) {
2893 struct nft_set *set = nft_trans_set(trans); 2893 if (trans->msg_type == NFT_MSG_NEWSET) {
2894 struct nft_set *set = nft_trans_set(trans);
2894 2895
2895 if (trans->msg_type == NFT_MSG_NEWSET && 2896 if (id == nft_trans_set_id(trans) &&
2896 id == nft_trans_set_id(trans) && 2897 nft_active_genmask(set, genmask))
2897 nft_active_genmask(set, genmask)) 2898 return set;
2898 return set; 2899 }
2899 } 2900 }
2900 return ERR_PTR(-ENOENT); 2901 return ERR_PTR(-ENOENT);
2901} 2902}
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index d260ce2d6671..7f3a9a211034 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -66,7 +66,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
66 parent = rcu_dereference_raw(parent->rb_left); 66 parent = rcu_dereference_raw(parent->rb_left);
67 if (interval && 67 if (interval &&
68 nft_rbtree_equal(set, this, interval) && 68 nft_rbtree_equal(set, this, interval) &&
69 nft_rbtree_interval_end(this) && 69 nft_rbtree_interval_end(rbe) &&
70 !nft_rbtree_interval_end(interval)) 70 !nft_rbtree_interval_end(interval))
71 continue; 71 continue;
72 interval = rbe; 72 interval = rbe;
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 8790190c6feb..03b9a50ec93b 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -245,12 +245,22 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
245 } 245 }
246 246
247 if (info->helper[0]) { 247 if (info->helper[0]) {
248 if (strnlen(info->helper, sizeof(info->helper)) == sizeof(info->helper)) {
249 ret = -ENAMETOOLONG;
250 goto err3;
251 }
252
248 ret = xt_ct_set_helper(ct, info->helper, par); 253 ret = xt_ct_set_helper(ct, info->helper, par);
249 if (ret < 0) 254 if (ret < 0)
250 goto err3; 255 goto err3;
251 } 256 }
252 257
253 if (info->timeout[0]) { 258 if (info->timeout[0]) {
259 if (strnlen(info->timeout, sizeof(info->timeout)) == sizeof(info->timeout)) {
260 ret = -ENAMETOOLONG;
261 goto err4;
262 }
263
254 ret = xt_ct_set_timeout(ct, par, info->timeout); 264 ret = xt_ct_set_timeout(ct, par, info->timeout);
255 if (ret < 0) 265 if (ret < 0)
256 goto err4; 266 goto err4;
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index 6f4c5217d835..bf2890b13212 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -372,8 +372,8 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
372 372
373 /* Normalize to fit into jiffies */ 373 /* Normalize to fit into jiffies */
374 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT && 374 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
375 add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC) 375 add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
376 add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC; 376 add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
377 if (info->add_set.index != IPSET_INVALID_ID) 377 if (info->add_set.index != IPSET_INVALID_ID)
378 ip_set_add(info->add_set.index, skb, par, &add_opt); 378 ip_set_add(info->add_set.index, skb, par, &add_opt);
379 if (info->del_set.index != IPSET_INVALID_ID) 379 if (info->del_set.index != IPSET_INVALID_ID)
@@ -407,8 +407,8 @@ set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
407 407
408 /* Normalize to fit into jiffies */ 408 /* Normalize to fit into jiffies */
409 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT && 409 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
410 add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC) 410 add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
411 add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC; 411 add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
412 if (info->add_set.index != IPSET_INVALID_ID) 412 if (info->add_set.index != IPSET_INVALID_ID)
413 ip_set_add(info->add_set.index, skb, par, &add_opt); 413 ip_set_add(info->add_set.index, skb, par, &add_opt);
414 if (info->del_set.index != IPSET_INVALID_ID) 414 if (info->del_set.index != IPSET_INVALID_ID)
@@ -470,7 +470,7 @@ set_target_v3_checkentry(const struct xt_tgchk_param *par)
470 } 470 }
471 if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) | 471 if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
472 (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) && 472 (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
473 !(par->hook_mask & (1 << NF_INET_FORWARD | 473 (par->hook_mask & ~(1 << NF_INET_FORWARD |
474 1 << NF_INET_LOCAL_OUT | 474 1 << NF_INET_LOCAL_OUT |
475 1 << NF_INET_POST_ROUTING))) { 475 1 << NF_INET_POST_ROUTING))) {
476 pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n"); 476 pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");