diff options
author | David S. Miller <davem@davemloft.net> | 2018-06-11 17:24:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-06-11 17:24:32 -0400 |
commit | a08ce73ba0a89be9f1418cba45fe94b39f9b73af (patch) | |
tree | a16d762ecdec50145e8e11f4f11cae2490f919e6 /net | |
parent | 349b71d6f427ff8211adf50839dbbff3f27c1805 (diff) | |
parent | d8e87fc6d11c31525430a388317b52f4a98a5328 (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.c | 25 | ||||
-rw-r--r-- | net/bridge/netfilter/nft_reject_bridge.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 1 | ||||
-rw-r--r-- | net/netfilter/ipset/ip_set_hash_gen.h | 5 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 4 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_xmit.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 11 | ||||
-rw-r--r-- | net/netfilter/nft_set_rbtree.c | 2 | ||||
-rw-r--r-- | net/netfilter/xt_CT.c | 10 | ||||
-rw-r--r-- | net/netfilter/xt_set.c | 10 |
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 */ |
1612 | static int ebt_compat_entry_padsize(void) | 1627 | static 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 | ||
1620 | static int ebt_compat_match_offset(const struct xt_match *match, | 1635 | static 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 | */ |
1463 | static void ip_vs_unlink_service(struct ip_vs_service *svc, bool cleanup) | 1466 | static 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"); |