ip_vs_conn_out_get() does not filter templates. A template with cport 0 is matched by a packet sent to client port 0 that traverses the out hook, and handle_response() then runs ip_vs_set_state() and the timeout update on a connection that must never see packets. A backup server receives such templates over the unauthenticated sync protocol. An ordinary connection scheduled for a client that uses source port 0 has cport 0 as well and is matched the same way. Apply the rule used by __ip_vs_conn_in_get(): a lookup for client port 0 matches only connections flagged IP_VS_CONN_F_NO_CPORT, which still wait for their cport, and a lookup for a nonzero client port matches only connections without this flag. Test p->vport, which was already compared with cp->cport, instead of reading cp->cport again. ip_vs_ftp_out() relies on the first case: it looks up the data connection with client port 0 to find the IP_VS_CONN_F_NO_CPORT entry created for an earlier PASV or EPSV reply. That lookup keeps working. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Suggested-by: Julian Anastasov Signed-off-by: Axel Mierczuk --- net/netfilter/ipvs/ip_vs_conn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 94f25fb7d87e..29cbe797bb86 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -579,6 +579,8 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p) ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) && ip_vs_addr_equal(p->af, p->caddr, saddr) && + (!p->vport ^ + (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) && p->protocol == cp->protocol) { if (__ip_vs_conn_get(cp)) goto out; -- 2.50.1 (Apple Git-155)