Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+99 -36
+14 -6
include/linux/netfilter/ipset/ip_set_timeout.h
··· 23 23 /* Set is defined with timeout support: timeout value may be 0 */ 24 24 #define IPSET_NO_TIMEOUT UINT_MAX 25 25 26 + /* Max timeout value, see msecs_to_jiffies() in jiffies.h */ 27 + #define IPSET_MAX_TIMEOUT (UINT_MAX >> 1)/MSEC_PER_SEC 28 + 26 29 #define ip_set_adt_opt_timeout(opt, set) \ 27 30 ((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout) 28 31 ··· 35 32 unsigned int timeout = ip_set_get_h32(tb); 36 33 37 34 /* Normalize to fit into jiffies */ 38 - if (timeout > UINT_MAX/MSEC_PER_SEC) 39 - timeout = UINT_MAX/MSEC_PER_SEC; 35 + if (timeout > IPSET_MAX_TIMEOUT) 36 + timeout = IPSET_MAX_TIMEOUT; 40 37 41 - /* Userspace supplied TIMEOUT parameter: adjust crazy size */ 42 - return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout; 38 + return timeout; 43 39 } 44 40 45 41 static inline bool ··· 67 65 static inline u32 68 66 ip_set_timeout_get(const unsigned long *timeout) 69 67 { 70 - return *timeout == IPSET_ELEM_PERMANENT ? 0 : 71 - jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; 68 + u32 t; 69 + 70 + if (*timeout == IPSET_ELEM_PERMANENT) 71 + return 0; 72 + 73 + t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC; 74 + /* Zero value in userspace means no timeout */ 75 + return t == 0 ? 1 : t; 72 76 } 73 77 74 78 #endif /* __KERNEL__ */
+30
include/net/ip_vs.h
··· 631 631 632 632 /* alternate persistence engine */ 633 633 struct ip_vs_pe __rcu *pe; 634 + int conntrack_afmask; 634 635 635 636 struct rcu_head rcu_head; 636 637 }; ··· 1610 1609 return true; 1611 1610 #endif 1612 1611 return false; 1612 + } 1613 + 1614 + static inline int ip_vs_register_conntrack(struct ip_vs_service *svc) 1615 + { 1616 + #if IS_ENABLED(CONFIG_NF_CONNTRACK) 1617 + int afmask = (svc->af == AF_INET6) ? 2 : 1; 1618 + int ret = 0; 1619 + 1620 + if (!(svc->conntrack_afmask & afmask)) { 1621 + ret = nf_ct_netns_get(svc->ipvs->net, svc->af); 1622 + if (ret >= 0) 1623 + svc->conntrack_afmask |= afmask; 1624 + } 1625 + return ret; 1626 + #else 1627 + return 0; 1628 + #endif 1629 + } 1630 + 1631 + static inline void ip_vs_unregister_conntrack(struct ip_vs_service *svc) 1632 + { 1633 + #if IS_ENABLED(CONFIG_NF_CONNTRACK) 1634 + int afmask = (svc->af == AF_INET6) ? 2 : 1; 1635 + 1636 + if (svc->conntrack_afmask & afmask) { 1637 + nf_ct_netns_put(svc->ipvs->net, svc->af); 1638 + svc->conntrack_afmask &= ~afmask; 1639 + } 1640 + #endif 1613 1641 } 1614 1642 1615 1643 static inline int
-10
include/net/netfilter/nft_dup.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _NFT_DUP_H_ 3 - #define _NFT_DUP_H_ 4 - 5 - struct nft_dup_inet { 6 - enum nft_registers sreg_addr:8; 7 - enum nft_registers sreg_dev:8; 8 - }; 9 - 10 - #endif /* _NFT_DUP_H_ */
+1 -1
include/uapi/linux/netfilter/nf_conntrack_common.h
··· 112 112 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | 113 113 IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD), 114 114 115 - __IPS_MAX_BIT = 14, 115 + __IPS_MAX_BIT = 15, 116 116 }; 117 117 118 118 /* Connection tracking event types */
+20 -5
net/bridge/netfilter/ebtables.c
··· 411 411 watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0); 412 412 if (IS_ERR(watcher)) 413 413 return PTR_ERR(watcher); 414 + 415 + if (watcher->family != NFPROTO_BRIDGE) { 416 + module_put(watcher->me); 417 + return -ENOENT; 418 + } 419 + 414 420 w->u.watcher = watcher; 415 421 416 422 par->target = watcher; ··· 715 709 } 716 710 i = 0; 717 711 712 + memset(&mtpar, 0, sizeof(mtpar)); 713 + memset(&tgpar, 0, sizeof(tgpar)); 718 714 mtpar.net = tgpar.net = net; 719 715 mtpar.table = tgpar.table = name; 720 716 mtpar.entryinfo = tgpar.entryinfo = e; ··· 735 727 target = xt_request_find_target(NFPROTO_BRIDGE, t->u.name, 0); 736 728 if (IS_ERR(target)) { 737 729 ret = PTR_ERR(target); 730 + goto cleanup_watchers; 731 + } 732 + 733 + /* Reject UNSPEC, xtables verdicts/return values are incompatible */ 734 + if (target->family != NFPROTO_BRIDGE) { 735 + module_put(target->me); 736 + ret = -ENOENT; 738 737 goto cleanup_watchers; 739 738 } 740 739 ··· 1620 1605 compat_uptr_t ptr; 1621 1606 } u; 1622 1607 compat_uint_t match_size; 1623 - compat_uint_t data[0]; 1608 + compat_uint_t data[0] __attribute__ ((aligned (__alignof__(struct compat_ebt_replace)))); 1624 1609 }; 1625 1610 1626 1611 /* account for possible padding between match_size and ->data */ 1627 1612 static int ebt_compat_entry_padsize(void) 1628 1613 { 1629 - BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) < 1630 - COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt))); 1631 - return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) - 1632 - COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)); 1614 + BUILD_BUG_ON(sizeof(struct ebt_entry_match) < 1615 + sizeof(struct compat_ebt_entry_mwt)); 1616 + return (int) sizeof(struct ebt_entry_match) - 1617 + sizeof(struct compat_ebt_entry_mwt); 1633 1618 } 1634 1619 1635 1620 static int ebt_compat_match_offset(const struct xt_match *match,
+1 -1
net/bridge/netfilter/nft_reject_bridge.c
··· 261 261 if (!reject6_br_csum_ok(oldskb, hook)) 262 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 265 LL_MAX_HEADER + len, GFP_ATOMIC); 266 266 if (!nskb) 267 267 return;
+1
net/ipv4/netfilter/ip_tables.c
··· 531 531 return -ENOMEM; 532 532 533 533 j = 0; 534 + memset(&mtpar, 0, sizeof(mtpar)); 534 535 mtpar.net = net; 535 536 mtpar.table = name; 536 537 mtpar.entryinfo = &e->ip;
+1
net/ipv6/netfilter/ip6_tables.c
··· 550 550 return -ENOMEM; 551 551 552 552 j = 0; 553 + memset(&mtpar, 0, sizeof(mtpar)); 553 554 mtpar.net = net; 554 555 mtpar.table = name; 555 556 mtpar.entryinfo = &e->ipv6;
+4 -1
net/netfilter/ipset/ip_set_hash_gen.h
··· 1234 1234 pr_debug("Create set %s with family %s\n", 1235 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 1241 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) 1239 1242 return -IPSET_ERR_INVALID_FAMILY; 1240 1243 #endif
+4
net/netfilter/ipvs/ip_vs_ctl.c
··· 839 839 * For now only for NAT! 840 840 */ 841 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 846 atomic_set(&dest->conn_flags, conn_flags); 844 847 ··· 1465 1462 */ 1466 1463 static void ip_vs_unlink_service(struct ip_vs_service *svc, bool cleanup) 1467 1464 { 1465 + ip_vs_unregister_conntrack(svc); 1468 1466 /* Hold svc to avoid double release from dest_trash */ 1469 1467 atomic_inc(&svc->refcnt); 1470 1468 /*
+1 -1
net/netfilter/ipvs/ip_vs_xmit.c
··· 168 168 bool new_rt_is_local) 169 169 { 170 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 172 bool rt_mode_allow_redirect = !!(rt_mode & IP_VS_RT_MODE_RDR); 173 173 bool source_is_loopback; 174 174 bool old_rt_is_local;
+6 -5
net/netfilter/nf_tables_api.c
··· 2890 2890 u32 id = ntohl(nla_get_be32(nla)); 2891 2891 2892 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 - id == nft_trans_set_id(trans) && 2897 - nft_active_genmask(set, genmask)) 2898 - return set; 2896 + if (id == nft_trans_set_id(trans) && 2897 + nft_active_genmask(set, genmask)) 2898 + return set; 2899 + } 2899 2900 } 2900 2901 return ERR_PTR(-ENOENT); 2901 2902 }
+1 -1
net/netfilter/nft_set_rbtree.c
··· 66 66 parent = rcu_dereference_raw(parent->rb_left); 67 67 if (interval && 68 68 nft_rbtree_equal(set, this, interval) && 69 - nft_rbtree_interval_end(this) && 69 + nft_rbtree_interval_end(rbe) && 70 70 !nft_rbtree_interval_end(interval)) 71 71 continue; 72 72 interval = rbe;
+10
net/netfilter/xt_CT.c
··· 245 245 } 246 246 247 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 253 ret = xt_ct_set_helper(ct, info->helper, par); 249 254 if (ret < 0) 250 255 goto err3; 251 256 } 252 257 253 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 264 ret = xt_ct_set_timeout(ct, par, info->timeout); 255 265 if (ret < 0) 256 266 goto err4;
+5 -5
net/netfilter/xt_set.c
··· 372 372 373 373 /* Normalize to fit into jiffies */ 374 374 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT && 375 - add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC) 376 - add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC; 375 + add_opt.ext.timeout > IPSET_MAX_TIMEOUT) 376 + add_opt.ext.timeout = IPSET_MAX_TIMEOUT; 377 377 if (info->add_set.index != IPSET_INVALID_ID) 378 378 ip_set_add(info->add_set.index, skb, par, &add_opt); 379 379 if (info->del_set.index != IPSET_INVALID_ID) ··· 407 407 408 408 /* Normalize to fit into jiffies */ 409 409 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT && 410 - add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC) 411 - add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC; 410 + add_opt.ext.timeout > IPSET_MAX_TIMEOUT) 411 + add_opt.ext.timeout = IPSET_MAX_TIMEOUT; 412 412 if (info->add_set.index != IPSET_INVALID_ID) 413 413 ip_set_add(info->add_set.index, skb, par, &add_opt); 414 414 if (info->del_set.index != IPSET_INVALID_ID) ··· 470 470 } 471 471 if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) | 472 472 (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) && 473 - !(par->hook_mask & (1 << NF_INET_FORWARD | 473 + (par->hook_mask & ~(1 << NF_INET_FORWARD | 474 474 1 << NF_INET_LOCAL_OUT | 475 475 1 << NF_INET_POST_ROUTING))) { 476 476 pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");