Commit d387eaf51f8c869a41d90474d3599d1e89826254
Merge tag 'ipvs-fixes-for-v4.5' of https://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs
Simon Horman says: ==================== please consider these IPVS fixes for v4.5 or if it is too late please consider them for v4.6. * Arnd Bergman has corrected an error whereby the SIP persistence engine may incorrectly access protocol fields * Julian Anastasov has corrected a problem reported by Jiri Bohac with the connection rescheduling mechanism added in 3.10 when new SYNs in connection to dead real server can be redirected to another real server. * Marco Angaroni resolved a problem in the SIP persistence engine whereby the Call-ID could not be found if it was at the beginning of a SIP message. ==================== Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Showing 4 changed files Side-by-side Diff
include/net/ip_vs.h
... | ... | @@ -1588,6 +1588,23 @@ |
1588 | 1588 | } |
1589 | 1589 | #endif /* CONFIG_IP_VS_NFCT */ |
1590 | 1590 | |
1591 | +/* Really using conntrack? */ | |
1592 | +static inline bool ip_vs_conn_uses_conntrack(struct ip_vs_conn *cp, | |
1593 | + struct sk_buff *skb) | |
1594 | +{ | |
1595 | +#ifdef CONFIG_IP_VS_NFCT | |
1596 | + enum ip_conntrack_info ctinfo; | |
1597 | + struct nf_conn *ct; | |
1598 | + | |
1599 | + if (!(cp->flags & IP_VS_CONN_F_NFCT)) | |
1600 | + return false; | |
1601 | + ct = nf_ct_get(skb, &ctinfo); | |
1602 | + if (ct && !nf_ct_is_untracked(ct)) | |
1603 | + return true; | |
1604 | +#endif | |
1605 | + return false; | |
1606 | +} | |
1607 | + | |
1591 | 1608 | static inline int |
1592 | 1609 | ip_vs_dest_conn_overhead(struct ip_vs_dest *dest) |
1593 | 1610 | { |
net/netfilter/ipvs/ip_vs_core.c
... | ... | @@ -1089,6 +1089,7 @@ |
1089 | 1089 | switch (cp->protocol) { |
1090 | 1090 | case IPPROTO_TCP: |
1091 | 1091 | return (cp->state == IP_VS_TCP_S_TIME_WAIT) || |
1092 | + (cp->state == IP_VS_TCP_S_CLOSE) || | |
1092 | 1093 | ((conn_reuse_mode & 2) && |
1093 | 1094 | (cp->state == IP_VS_TCP_S_FIN_WAIT) && |
1094 | 1095 | (cp->flags & IP_VS_CONN_F_NOOUTPUT)); |
... | ... | @@ -1757,15 +1758,34 @@ |
1757 | 1758 | cp = pp->conn_in_get(ipvs, af, skb, &iph); |
1758 | 1759 | |
1759 | 1760 | conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); |
1760 | - if (conn_reuse_mode && !iph.fragoffs && | |
1761 | - is_new_conn(skb, &iph) && cp && | |
1762 | - ((unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && | |
1763 | - unlikely(!atomic_read(&cp->dest->weight))) || | |
1764 | - unlikely(is_new_conn_expected(cp, conn_reuse_mode)))) { | |
1765 | - if (!atomic_read(&cp->n_control)) | |
1766 | - ip_vs_conn_expire_now(cp); | |
1767 | - __ip_vs_conn_put(cp); | |
1768 | - cp = NULL; | |
1761 | + if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) { | |
1762 | + bool uses_ct = false, resched = false; | |
1763 | + | |
1764 | + if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && | |
1765 | + unlikely(!atomic_read(&cp->dest->weight))) { | |
1766 | + resched = true; | |
1767 | + uses_ct = ip_vs_conn_uses_conntrack(cp, skb); | |
1768 | + } else if (is_new_conn_expected(cp, conn_reuse_mode)) { | |
1769 | + uses_ct = ip_vs_conn_uses_conntrack(cp, skb); | |
1770 | + if (!atomic_read(&cp->n_control)) { | |
1771 | + resched = true; | |
1772 | + } else { | |
1773 | + /* Do not reschedule controlling connection | |
1774 | + * that uses conntrack while it is still | |
1775 | + * referenced by controlled connection(s). | |
1776 | + */ | |
1777 | + resched = !uses_ct; | |
1778 | + } | |
1779 | + } | |
1780 | + | |
1781 | + if (resched) { | |
1782 | + if (!atomic_read(&cp->n_control)) | |
1783 | + ip_vs_conn_expire_now(cp); | |
1784 | + __ip_vs_conn_put(cp); | |
1785 | + if (uses_ct) | |
1786 | + return NF_DROP; | |
1787 | + cp = NULL; | |
1788 | + } | |
1769 | 1789 | } |
1770 | 1790 | |
1771 | 1791 | if (unlikely(!cp)) { |
net/netfilter/ipvs/ip_vs_pe_sip.c
... | ... | @@ -70,10 +70,10 @@ |
70 | 70 | const char *dptr; |
71 | 71 | int retc; |
72 | 72 | |
73 | - ip_vs_fill_iph_skb(p->af, skb, false, &iph); | |
73 | + retc = ip_vs_fill_iph_skb(p->af, skb, false, &iph); | |
74 | 74 | |
75 | 75 | /* Only useful with UDP */ |
76 | - if (iph.protocol != IPPROTO_UDP) | |
76 | + if (!retc || iph.protocol != IPPROTO_UDP) | |
77 | 77 | return -EINVAL; |
78 | 78 | /* todo: IPv6 fragments: |
79 | 79 | * I think this only should be done for the first fragment. /HS |
... | ... | @@ -88,7 +88,7 @@ |
88 | 88 | dptr = skb->data + dataoff; |
89 | 89 | datalen = skb->len - dataoff; |
90 | 90 | |
91 | - if (get_callid(dptr, dataoff, datalen, &matchoff, &matchlen)) | |
91 | + if (get_callid(dptr, 0, datalen, &matchoff, &matchlen)) | |
92 | 92 | return -EINVAL; |
93 | 93 | |
94 | 94 | /* N.B: pe_data is only set on success, |
net/netfilter/nfnetlink_acct.c
... | ... | @@ -242,6 +242,9 @@ |
242 | 242 | if (err < 0) |
243 | 243 | return ERR_PTR(err); |
244 | 244 | |
245 | + if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE]) | |
246 | + return ERR_PTR(-EINVAL); | |
247 | + | |
245 | 248 | filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL); |
246 | 249 | if (!filter) |
247 | 250 | return ERR_PTR(-ENOMEM); |