Commit 2a38b775 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[PPP] generic: Fix receive path data clobbering & non-linear handling

This patch adds missing pskb_may_pull calls to deal with non-linear
packets that may arrive from pppoe or pppol2tp.

It also copies cloned packets before writing over them.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7b797d5b
...@@ -1525,7 +1525,7 @@ ppp_input_error(struct ppp_channel *chan, int code) ...@@ -1525,7 +1525,7 @@ ppp_input_error(struct ppp_channel *chan, int code)
static void static void
ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{ {
if (skb->len >= 2) { if (pskb_may_pull(skb, 2)) {
#ifdef CONFIG_PPP_MULTILINK #ifdef CONFIG_PPP_MULTILINK
/* XXX do channel-level decompression here */ /* XXX do channel-level decompression here */
if (PPP_PROTO(skb) == PPP_MP) if (PPP_PROTO(skb) == PPP_MP)
...@@ -1577,7 +1577,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) ...@@ -1577,7 +1577,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
goto err; goto err;
if (skb_tailroom(skb) < 124) { if (skb_tailroom(skb) < 124 || skb_cloned(skb)) {
/* copy to a new sk_buff with more tailroom */ /* copy to a new sk_buff with more tailroom */
ns = dev_alloc_skb(skb->len + 128); ns = dev_alloc_skb(skb->len + 128);
if (ns == 0) { if (ns == 0) {
...@@ -1648,23 +1648,29 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) ...@@ -1648,23 +1648,29 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
/* check if the packet passes the pass and active filters */ /* check if the packet passes the pass and active filters */
/* the filter instructions are constructed assuming /* the filter instructions are constructed assuming
a four-byte PPP header on each packet */ a four-byte PPP header on each packet */
*skb_push(skb, 2) = 0; if (ppp->pass_filter || ppp->active_filter) {
if (ppp->pass_filter if (skb_cloned(skb) &&
&& sk_run_filter(skb, ppp->pass_filter, pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
ppp->pass_len) == 0) { goto err;
if (ppp->debug & 1)
printk(KERN_DEBUG "PPP: inbound frame not passed\n"); *skb_push(skb, 2) = 0;
kfree_skb(skb); if (ppp->pass_filter
return; && sk_run_filter(skb, ppp->pass_filter,
} ppp->pass_len) == 0) {
if (!(ppp->active_filter if (ppp->debug & 1)
&& sk_run_filter(skb, ppp->active_filter, printk(KERN_DEBUG "PPP: inbound frame "
ppp->active_len) == 0)) "not passed\n");
ppp->last_recv = jiffies; kfree_skb(skb);
skb_pull(skb, 2); return;
#else }
ppp->last_recv = jiffies; if (!(ppp->active_filter
&& sk_run_filter(skb, ppp->active_filter,
ppp->active_len) == 0))
ppp->last_recv = jiffies;
__skb_pull(skb, 2);
} else
#endif /* CONFIG_PPP_FILTER */ #endif /* CONFIG_PPP_FILTER */
ppp->last_recv = jiffies;
if ((ppp->dev->flags & IFF_UP) == 0 if ((ppp->dev->flags & IFF_UP) == 0
|| ppp->npmode[npi] != NPMODE_PASS) { || ppp->npmode[npi] != NPMODE_PASS) {
...@@ -1762,7 +1768,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) ...@@ -1762,7 +1768,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
struct channel *ch; struct channel *ch;
int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0) if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
goto err; /* no good, throw it away */ goto err; /* no good, throw it away */
/* Decode sequence number and begin/end bits */ /* Decode sequence number and begin/end bits */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment