Local templates have cport 0 and IP_VS_CONN_F_NO_CPORT clear, so ip_vs_conn_in_get() cannot match them. A template received over the unauthenticated sync protocol with a nonzero cport can reach the protocol state machine. Before template state validation, this could cause out-of-bounds reads, crashes and kernel data leaks. Ordinary records with cport 0 and IP_VS_CONN_F_NO_CPORT clear, or with a nonzero cport and IP_VS_CONN_F_NO_CPORT set, create connections that incoming lookups cannot match. The latter also keeps the cport-zero fallback in ip_vs_conn_in_get() enabled. Reject all three cases. Continue accepting ordinary connections with cport 0 and IP_VS_CONN_F_NO_CPORT. The companion patch "ipvs: filter some flags received in the backup server" rejects template records carrying IP_VS_CONN_F_NO_CPORT. Fixes: 87375ab47cd0 ("[IPVS]: ip_vs_ftp breaks connections using persistence") Cc: stable@vger.kernel.org Suggested-by: Julian Anastasov Signed-off-by: Axel Mierczuk Acked-by: Julian Anastasov --- net/netfilter/ipvs/ip_vs_sync.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 157f5c8361ab..a85dc95e29cc 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -853,6 +853,25 @@ static void ip_vs_proc_conn(struct netns_ipvs *ipvs, struct ip_vs_conn_param *pa struct ip_vs_dest *dest; struct ip_vs_conn *cp; + /* Templates require cport 0. Ordinary connections require + * NO_CPORT exactly when cport is 0. + */ + if (flags & IP_VS_CONN_F_TEMPLATE) { + if (param->cport) { + IP_VS_DBG(2, "BACKUP, template with cport dropped\n"); + kfree(param->pe_data); + return; + } + } else if (!param->cport && !(flags & IP_VS_CONN_F_NO_CPORT)) { + IP_VS_DBG(2, "BACKUP, conn without cport dropped\n"); + kfree(param->pe_data); + return; + } else if (param->cport && (flags & IP_VS_CONN_F_NO_CPORT)) { + IP_VS_DBG(2, "BACKUP, conn with cport and NO_CPORT dropped\n"); + kfree(param->pe_data); + return; + } + if (!(flags & IP_VS_CONN_F_TEMPLATE)) { cp = ip_vs_conn_in_get(param); if (cp && ((cp->dport != dport) || -- 2.50.1 (Apple Git-155)