diff options
Diffstat (limited to 'drivers/net/ppp_generic.c')
| -rw-r--r-- | drivers/net/ppp_generic.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6e281bc825e5..8518a2e58e53 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
| @@ -405,6 +405,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, | |||
| 405 | DECLARE_WAITQUEUE(wait, current); | 405 | DECLARE_WAITQUEUE(wait, current); |
| 406 | ssize_t ret; | 406 | ssize_t ret; |
| 407 | struct sk_buff *skb = NULL; | 407 | struct sk_buff *skb = NULL; |
| 408 | struct iovec iov; | ||
| 408 | 409 | ||
| 409 | ret = count; | 410 | ret = count; |
| 410 | 411 | ||
| @@ -448,7 +449,9 @@ static ssize_t ppp_read(struct file *file, char __user *buf, | |||
| 448 | if (skb->len > count) | 449 | if (skb->len > count) |
| 449 | goto outf; | 450 | goto outf; |
| 450 | ret = -EFAULT; | 451 | ret = -EFAULT; |
| 451 | if (copy_to_user(buf, skb->data, skb->len)) | 452 | iov.iov_base = buf; |
| 453 | iov.iov_len = count; | ||
| 454 | if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len)) | ||
| 452 | goto outf; | 455 | goto outf; |
| 453 | ret = skb->len; | 456 | ret = skb->len; |
| 454 | 457 | ||
| @@ -1567,13 +1570,22 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 1567 | struct channel *pch = chan->ppp; | 1570 | struct channel *pch = chan->ppp; |
| 1568 | int proto; | 1571 | int proto; |
| 1569 | 1572 | ||
| 1570 | if (!pch || skb->len == 0) { | 1573 | if (!pch) { |
| 1571 | kfree_skb(skb); | 1574 | kfree_skb(skb); |
| 1572 | return; | 1575 | return; |
| 1573 | } | 1576 | } |
| 1574 | 1577 | ||
| 1575 | proto = PPP_PROTO(skb); | ||
| 1576 | read_lock_bh(&pch->upl); | 1578 | read_lock_bh(&pch->upl); |
| 1579 | if (!pskb_may_pull(skb, 2)) { | ||
| 1580 | kfree_skb(skb); | ||
| 1581 | if (pch->ppp) { | ||
| 1582 | ++pch->ppp->dev->stats.rx_length_errors; | ||
| 1583 | ppp_receive_error(pch->ppp); | ||
| 1584 | } | ||
| 1585 | goto done; | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | proto = PPP_PROTO(skb); | ||
| 1577 | if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { | 1589 | if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { |
| 1578 | /* put it on the channel queue */ | 1590 | /* put it on the channel queue */ |
| 1579 | skb_queue_tail(&pch->file.rq, skb); | 1591 | skb_queue_tail(&pch->file.rq, skb); |
| @@ -1585,6 +1597,8 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 1585 | } else { | 1597 | } else { |
| 1586 | ppp_do_recv(pch->ppp, skb, pch); | 1598 | ppp_do_recv(pch->ppp, skb, pch); |
| 1587 | } | 1599 | } |
| 1600 | |||
| 1601 | done: | ||
| 1588 | read_unlock_bh(&pch->upl); | 1602 | read_unlock_bh(&pch->upl); |
| 1589 | } | 1603 | } |
| 1590 | 1604 | ||
| @@ -1617,7 +1631,8 @@ ppp_input_error(struct ppp_channel *chan, int code) | |||
| 1617 | static void | 1631 | static void |
| 1618 | ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) | 1632 | ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) |
| 1619 | { | 1633 | { |
| 1620 | if (pskb_may_pull(skb, 2)) { | 1634 | /* note: a 0-length skb is used as an error indication */ |
| 1635 | if (skb->len > 0) { | ||
| 1621 | #ifdef CONFIG_PPP_MULTILINK | 1636 | #ifdef CONFIG_PPP_MULTILINK |
| 1622 | /* XXX do channel-level decompression here */ | 1637 | /* XXX do channel-level decompression here */ |
| 1623 | if (PPP_PROTO(skb) == PPP_MP) | 1638 | if (PPP_PROTO(skb) == PPP_MP) |
| @@ -1625,15 +1640,10 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) | |||
| 1625 | else | 1640 | else |
| 1626 | #endif /* CONFIG_PPP_MULTILINK */ | 1641 | #endif /* CONFIG_PPP_MULTILINK */ |
| 1627 | ppp_receive_nonmp_frame(ppp, skb); | 1642 | ppp_receive_nonmp_frame(ppp, skb); |
| 1628 | return; | 1643 | } else { |
| 1644 | kfree_skb(skb); | ||
| 1645 | ppp_receive_error(ppp); | ||
| 1629 | } | 1646 | } |
| 1630 | |||
| 1631 | if (skb->len > 0) | ||
| 1632 | /* note: a 0-length skb is used as an error indication */ | ||
| 1633 | ++ppp->dev->stats.rx_length_errors; | ||
| 1634 | |||
| 1635 | kfree_skb(skb); | ||
| 1636 | ppp_receive_error(ppp); | ||
| 1637 | } | 1647 | } |
| 1638 | 1648 | ||
| 1639 | static void | 1649 | static void |
