diff options
Diffstat (limited to 'drivers/net/ppp/pptp.c')
| -rw-r--r-- | drivers/net/ppp/pptp.c | 22 | 
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index eae542a7e98..89f829f5f72 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -285,8 +285,10 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)  	ip_send_check(iph);  	ip_local_out(skb); +	return 1;  tx_error: +	kfree_skb(skb);  	return 1;  } @@ -305,11 +307,18 @@ static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb)  	}  	header = (struct pptp_gre_header *)(skb->data); +	headersize  = sizeof(*header);  	/* test if acknowledgement present */  	if (PPTP_GRE_IS_A(header->ver)) { -		__u32 ack = (PPTP_GRE_IS_S(header->flags)) ? -				header->ack : header->seq; /* ack in different place if S = 0 */ +		__u32 ack; + +		if (!pskb_may_pull(skb, headersize)) +			goto drop; +		header = (struct pptp_gre_header *)(skb->data); + +		/* ack in different place if S = 0 */ +		ack = PPTP_GRE_IS_S(header->flags) ? header->ack : header->seq;  		ack = ntohl(ack); @@ -318,21 +327,18 @@ static int pptp_rcv_core(struct sock *sk, struct sk_buff *skb)  		/* also handle sequence number wrap-around  */  		if (WRAPPED(ack, opt->ack_recv))  			opt->ack_recv = ack; +	} else { +		headersize -= sizeof(header->ack);  	} -  	/* test if payload present */  	if (!PPTP_GRE_IS_S(header->flags))  		goto drop; -	headersize  = sizeof(*header);  	payload_len = ntohs(header->payload_len);  	seq         = ntohl(header->seq); -	/* no ack present? */ -	if (!PPTP_GRE_IS_A(header->ver)) -		headersize -= sizeof(header->ack);  	/* check for incomplete packet (length smaller than expected) */ -	if (skb->len - headersize < payload_len) +	if (!pskb_may_pull(skb, headersize + payload_len))  		goto drop;  	payload = skb->data + headersize;  |