aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-09-16 19:22:13 -0400
committerDavid S. Miller <davem@davemloft.net>2007-09-16 19:22:13 -0400
commit2a38b775b77f99308a4e571c13d908df78ac5e57 (patch)
tree10f7bbe1d1a35c7383b7aa7fa865119a8bc0ae65 /drivers
parent7b797d5b150775d717cb03b5ada28b8bad99afab (diff)
[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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ppp_generic.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 7e21342becb..4b49d0e8c7e 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1525,7 +1525,7 @@ ppp_input_error(struct ppp_channel *chan, int code)
1525static void 1525static void
1526ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) 1526ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
1527{ 1527{
1528 if (skb->len >= 2) { 1528 if (pskb_may_pull(skb, 2)) {
1529#ifdef CONFIG_PPP_MULTILINK 1529#ifdef CONFIG_PPP_MULTILINK
1530 /* XXX do channel-level decompression here */ 1530 /* XXX do channel-level decompression here */
1531 if (PPP_PROTO(skb) == PPP_MP) 1531 if (PPP_PROTO(skb) == PPP_MP)
@@ -1577,7 +1577,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
1577 if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) 1577 if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP))
1578 goto err; 1578 goto err;
1579 1579
1580 if (skb_tailroom(skb) < 124) { 1580 if (skb_tailroom(skb) < 124 || skb_cloned(skb)) {
1581 /* copy to a new sk_buff with more tailroom */ 1581 /* copy to a new sk_buff with more tailroom */
1582 ns = dev_alloc_skb(skb->len + 128); 1582 ns = dev_alloc_skb(skb->len + 128);
1583 if (ns == 0) { 1583 if (ns == 0) {
@@ -1648,23 +1648,29 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
1648 /* check if the packet passes the pass and active filters */ 1648 /* check if the packet passes the pass and active filters */
1649 /* the filter instructions are constructed assuming 1649 /* the filter instructions are constructed assuming
1650 a four-byte PPP header on each packet */ 1650 a four-byte PPP header on each packet */
1651 *skb_push(skb, 2) = 0; 1651 if (ppp->pass_filter || ppp->active_filter) {
1652 if (ppp->pass_filter 1652 if (skb_cloned(skb) &&
1653 && sk_run_filter(skb, ppp->pass_filter, 1653 pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
1654 ppp->pass_len) == 0) { 1654 goto err;
1655 if (ppp->debug & 1) 1655
1656 printk(KERN_DEBUG "PPP: inbound frame not passed\n"); 1656 *skb_push(skb, 2) = 0;
1657 kfree_skb(skb); 1657 if (ppp->pass_filter
1658 return; 1658 && sk_run_filter(skb, ppp->pass_filter,
1659 } 1659 ppp->pass_len) == 0) {
1660 if (!(ppp->active_filter 1660 if (ppp->debug & 1)
1661 && sk_run_filter(skb, ppp->active_filter, 1661 printk(KERN_DEBUG "PPP: inbound frame "
1662 ppp->active_len) == 0)) 1662 "not passed\n");
1663 ppp->last_recv = jiffies; 1663 kfree_skb(skb);
1664 skb_pull(skb, 2); 1664 return;
1665#else 1665 }
1666 ppp->last_recv = jiffies; 1666 if (!(ppp->active_filter
1667 && sk_run_filter(skb, ppp->active_filter,
1668 ppp->active_len) == 0))
1669 ppp->last_recv = jiffies;
1670 __skb_pull(skb, 2);
1671 } else
1667#endif /* CONFIG_PPP_FILTER */ 1672#endif /* CONFIG_PPP_FILTER */
1673 ppp->last_recv = jiffies;
1668 1674
1669 if ((ppp->dev->flags & IFF_UP) == 0 1675 if ((ppp->dev->flags & IFF_UP) == 0
1670 || ppp->npmode[npi] != NPMODE_PASS) { 1676 || ppp->npmode[npi] != NPMODE_PASS) {
@@ -1762,7 +1768,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
1762 struct channel *ch; 1768 struct channel *ch;
1763 int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; 1769 int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
1764 1770
1765 if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0) 1771 if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
1766 goto err; /* no good, throw it away */ 1772 goto err; /* no good, throw it away */
1767 1773
1768 /* Decode sequence number and begin/end bits */ 1774 /* Decode sequence number and begin/end bits */