Skip to content

Commit 84bef5b

Browse files
Guillaume Naultdavem330
authored andcommitted
pptp: Fix fib lookup calls.
PPTP uses pppox sockets (struct pppox_sock). These sockets don't embed an inet_sock structure, so it's invalid to call inet_sk() on them. Therefore, the ip_route_output_ports() call in pptp_connect() has two problems: * The tos variable is set with RT_CONN_FLAGS(sk), which calls inet_sk() on the pppox socket. * ip_route_output_ports() tries to retrieve routing flags using inet_sk_flowi_flags(), which is also going to call inet_sk() on the pppox socket. While PPTP doesn't use inet sockets, it's actually really layered on top of IP and therefore needs a proper way to do fib lookups. So let's define pptp_route_output() to get a struct rtable from a pptp socket. Let's also replace the ip_route_output_ports() call of pptp_xmit() for consistency. In practice, this means that: * pptp_connect() sets ->flowi4_tos and ->flowi4_flags to zero instead of using bits of unrelated struct pppox_sock fields. * pptp_xmit() now respects ->sk_mark and ->sk_uid. * pptp_xmit() now calls the security_sk_classify_flow() security hook, thus allowing to set ->flowic_secid. * pptp_xmit() now passes the pppox socket to xfrm_lookup_route(). Found by code inspection. Fixes: 00959ad ("PPTP: PPP over IPv4 (Point-to-Point Tunneling Protocol)") Signed-off-by: Guillaume Nault <gnault@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 90a8007 commit 84bef5b

1 file changed

Lines changed: 20 additions & 11 deletions

File tree

drivers/net/ppp/pptp.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/in.h>
2525
#include <linux/ip.h>
2626
#include <linux/rcupdate.h>
27+
#include <linux/security.h>
2728
#include <linux/spinlock.h>
2829

2930
#include <net/sock.h>
@@ -128,6 +129,23 @@ static void del_chan(struct pppox_sock *sock)
128129
spin_unlock(&chan_lock);
129130
}
130131

132+
static struct rtable *pptp_route_output(struct pppox_sock *po,
133+
struct flowi4 *fl4)
134+
{
135+
struct sock *sk = &po->sk;
136+
struct net *net;
137+
138+
net = sock_net(sk);
139+
flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, 0,
140+
RT_SCOPE_UNIVERSE, IPPROTO_GRE, 0,
141+
po->proto.pptp.dst_addr.sin_addr.s_addr,
142+
po->proto.pptp.src_addr.sin_addr.s_addr,
143+
0, 0, sock_net_uid(net, sk));
144+
security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
145+
146+
return ip_route_output_flow(net, fl4, sk);
147+
}
148+
131149
static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
132150
{
133151
struct sock *sk = (struct sock *) chan->private;
@@ -151,11 +169,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
151169
if (sk_pppox(po)->sk_state & PPPOX_DEAD)
152170
goto tx_error;
153171

154-
rt = ip_route_output_ports(net, &fl4, NULL,
155-
opt->dst_addr.sin_addr.s_addr,
156-
opt->src_addr.sin_addr.s_addr,
157-
0, 0, IPPROTO_GRE,
158-
RT_TOS(0), sk->sk_bound_dev_if);
172+
rt = pptp_route_output(po, &fl4);
159173
if (IS_ERR(rt))
160174
goto tx_error;
161175

@@ -438,12 +452,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
438452
po->chan.private = sk;
439453
po->chan.ops = &pptp_chan_ops;
440454

441-
rt = ip_route_output_ports(sock_net(sk), &fl4, sk,
442-
opt->dst_addr.sin_addr.s_addr,
443-
opt->src_addr.sin_addr.s_addr,
444-
0, 0,
445-
IPPROTO_GRE, RT_CONN_FLAGS(sk),
446-
sk->sk_bound_dev_if);
455+
rt = pptp_route_output(po, &fl4);
447456
if (IS_ERR(rt)) {
448457
error = -EHOSTUNREACH;
449458
goto end;

0 commit comments

Comments
 (0)