diff options
author | David S. Miller <davem@davemloft.net> | 2012-06-21 17:58:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-06-21 17:58:10 -0400 |
commit | fd62e09b946522ec3578412826a81bead06fadf7 (patch) | |
tree | f105f85146261f7647928bd6e0b74c7f6398401f /net/ipv4/tcp_ipv4.c | |
parent | 3e428fe0382fca48795b5cf9d4f03a89cda5d84d (diff) |
tcp: Validate route interface in early demux.
Otherwise we might violate reverse path filtering.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 13857df1dae1..21e22a00481a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1676,6 +1676,7 @@ int tcp_v4_early_demux(struct sk_buff *skb) | |||
1676 | struct net *net = dev_net(skb->dev); | 1676 | struct net *net = dev_net(skb->dev); |
1677 | const struct iphdr *iph; | 1677 | const struct iphdr *iph; |
1678 | const struct tcphdr *th; | 1678 | const struct tcphdr *th; |
1679 | struct net_device *dev; | ||
1679 | struct sock *sk; | 1680 | struct sock *sk; |
1680 | int err; | 1681 | int err; |
1681 | 1682 | ||
@@ -1695,10 +1696,11 @@ int tcp_v4_early_demux(struct sk_buff *skb) | |||
1695 | if (!pskb_may_pull(skb, ip_hdrlen(skb) + th->doff * 4)) | 1696 | if (!pskb_may_pull(skb, ip_hdrlen(skb) + th->doff * 4)) |
1696 | goto out_err; | 1697 | goto out_err; |
1697 | 1698 | ||
1699 | dev = skb->dev; | ||
1698 | sk = __inet_lookup_established(net, &tcp_hashinfo, | 1700 | sk = __inet_lookup_established(net, &tcp_hashinfo, |
1699 | iph->saddr, th->source, | 1701 | iph->saddr, th->source, |
1700 | iph->daddr, th->dest, | 1702 | iph->daddr, th->dest, |
1701 | skb->dev->ifindex); | 1703 | dev->ifindex); |
1702 | if (sk) { | 1704 | if (sk) { |
1703 | skb->sk = sk; | 1705 | skb->sk = sk; |
1704 | skb->destructor = sock_edemux; | 1706 | skb->destructor = sock_edemux; |
@@ -1707,8 +1709,12 @@ int tcp_v4_early_demux(struct sk_buff *skb) | |||
1707 | if (dst) | 1709 | if (dst) |
1708 | dst = dst_check(dst, 0); | 1710 | dst = dst_check(dst, 0); |
1709 | if (dst) { | 1711 | if (dst) { |
1710 | skb_dst_set_noref(skb, dst); | 1712 | struct rtable *rt = (struct rtable *) dst; |
1711 | err = 0; | 1713 | |
1714 | if (rt->rt_iif == dev->ifindex) { | ||
1715 | skb_dst_set_noref(skb, dst); | ||
1716 | err = 0; | ||
1717 | } | ||
1712 | } | 1718 | } |
1713 | } | 1719 | } |
1714 | } | 1720 | } |