Hello,
On Sun, 5 Jul 2015, Alex Gartrell wrote:
> It is possible that we bind against a local socket in early_demux when we
> are actually going to want to forward it. In this case, the socket serves
> no purpose and only serves to confuse things (particularly functions which
> implicitly expect sk_fullsock to be true, like ip_local_out).
> Additionally, skb_set_owner_w is totally broken for non full-socks.
>
> Signed-off-by: Alex Gartrell <agartrell@xxxxxx>
Thanks for fixing this problem!
Acked-by: Julian Anastasov <ja@xxxxxx>
May be the patch fixes crashes? If yes, Simon
should apply it for ipvs/net tree, otherwise after
the merge window...
> ---
> net/netfilter/ipvs/ip_vs_xmit.c | 27 +++++++++++++++++++++++++++
> 1 file changed, 27 insertions(+)
>
> diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
> index bf66a86..99d4a41 100644
> --- a/net/netfilter/ipvs/ip_vs_xmit.c
> +++ b/net/netfilter/ipvs/ip_vs_xmit.c
> @@ -527,6 +527,21 @@ static inline int ip_vs_tunnel_xmit_prepare(struct
> sk_buff *skb,
> return ret;
> }
>
> +/* In the event of a remote destination, it's possible that we would have
> + * matches against an old socket (particularly a TIME-WAIT socket). This
> + * causes havoc down the line (ip_local_out et. al. expect regular sockets
> + * and invalid memory accesses will happen) so simply drop the association
> + * in this case.
> +*/
> +static inline void ip_vs_drop_early_demux_sk(struct sk_buff *skb)
> +{
> + /* If dev is set, the packet came from the LOCAL_IN callback and
> + * not from a local TCP socket.
> + */
> + if (skb->dev)
> + skb_orphan(skb);
> +}
> +
> /* return NF_STOLEN (sent) or NF_ACCEPT if local=1 (not sent) */
> static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb,
> struct ip_vs_conn *cp, int local)
> @@ -538,12 +553,21 @@ static inline int ip_vs_nat_send_or_cont(int pf, struct
> sk_buff *skb,
> ip_vs_notrack(skb);
> else
> ip_vs_update_conntrack(skb, cp, 1);
> +
> + /* Remove the early_demux association unless it's bound for the
> + * exact same port and address on this host after translation.
> + */
> + if (!local || cp->vport != cp->dport ||
> + !ip_vs_addr_equal(cp->af, &cp->vaddr, &cp->daddr))
> + ip_vs_drop_early_demux_sk(skb);
> +
> if (!local) {
> skb_forward_csum(skb);
> NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb,
> NULL, skb_dst(skb)->dev, dst_output_sk);
> } else
> ret = NF_ACCEPT;
> +
> return ret;
> }
>
> @@ -557,6 +581,7 @@ static inline int ip_vs_send_or_cont(int pf, struct
> sk_buff *skb,
> if (likely(!(cp->flags & IP_VS_CONN_F_NFCT)))
> ip_vs_notrack(skb);
> if (!local) {
> + ip_vs_drop_early_demux_sk(skb);
> skb_forward_csum(skb);
> NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb,
> NULL, skb_dst(skb)->dev, dst_output_sk);
> @@ -845,6 +870,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int
> skb_af,
> struct ipv6hdr *old_ipv6h = NULL;
> #endif
>
> + ip_vs_drop_early_demux_sk(skb);
> +
> if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) {
> new_skb = skb_realloc_headroom(skb, max_headroom);
> if (!new_skb)
> --
> Alex Gartrell <agartrell@xxxxxx>
Regards
--
Julian Anastasov <ja@xxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe lvs-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
|