[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: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
7b797d5b15
commit
2a38b775b7
@@ -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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
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 */
|
||||||
|
Reference in New Issue
Block a user