diff options
Diffstat (limited to 'drivers/net/pppoe.c')
| -rw-r--r-- | drivers/net/pppoe.c | 37 |
1 files changed, 20 insertions, 17 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 58a26a47af..bafb69b6f7 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c | |||
| @@ -341,12 +341,6 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) | |||
| 341 | struct pppox_sock *relay_po; | 341 | struct pppox_sock *relay_po; |
| 342 | 342 | ||
| 343 | if (sk->sk_state & PPPOX_BOUND) { | 343 | if (sk->sk_state & PPPOX_BOUND) { |
| 344 | struct pppoe_hdr *ph = pppoe_hdr(skb); | ||
| 345 | int len = ntohs(ph->length); | ||
| 346 | skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); | ||
| 347 | if (pskb_trim_rcsum(skb, len)) | ||
| 348 | goto abort_kfree; | ||
| 349 | |||
| 350 | ppp_input(&po->chan, skb); | 344 | ppp_input(&po->chan, skb); |
| 351 | } else if (sk->sk_state & PPPOX_RELAY) { | 345 | } else if (sk->sk_state & PPPOX_RELAY) { |
| 352 | relay_po = get_item_by_addr(&po->pppoe_relay); | 346 | relay_po = get_item_by_addr(&po->pppoe_relay); |
| @@ -357,7 +351,6 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) | |||
| 357 | if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0) | 351 | if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0) |
| 358 | goto abort_put; | 352 | goto abort_put; |
| 359 | 353 | ||
| 360 | skb_pull(skb, sizeof(struct pppoe_hdr)); | ||
| 361 | if (!__pppoe_xmit(sk_pppox(relay_po), skb)) | 354 | if (!__pppoe_xmit(sk_pppox(relay_po), skb)) |
| 362 | goto abort_put; | 355 | goto abort_put; |
| 363 | } else { | 356 | } else { |
| @@ -388,6 +381,7 @@ static int pppoe_rcv(struct sk_buff *skb, | |||
| 388 | { | 381 | { |
| 389 | struct pppoe_hdr *ph; | 382 | struct pppoe_hdr *ph; |
| 390 | struct pppox_sock *po; | 383 | struct pppox_sock *po; |
| 384 | int len; | ||
| 391 | 385 | ||
| 392 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) | 386 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) |
| 393 | goto out; | 387 | goto out; |
| @@ -399,10 +393,21 @@ static int pppoe_rcv(struct sk_buff *skb, | |||
| 399 | goto drop; | 393 | goto drop; |
| 400 | 394 | ||
| 401 | ph = pppoe_hdr(skb); | 395 | ph = pppoe_hdr(skb); |
| 396 | len = ntohs(ph->length); | ||
| 397 | |||
| 398 | skb_pull_rcsum(skb, sizeof(*ph)); | ||
| 399 | if (skb->len < len) | ||
| 400 | goto drop; | ||
| 402 | 401 | ||
| 403 | po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); | 402 | po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); |
| 404 | if (po != NULL) | 403 | if (!po) |
| 405 | return sk_receive_skb(sk_pppox(po), skb, 0); | 404 | goto drop; |
| 405 | |||
| 406 | if (pskb_trim_rcsum(skb, len)) | ||
| 407 | goto drop; | ||
| 408 | |||
| 409 | return sk_receive_skb(sk_pppox(po), skb, 0); | ||
| 410 | |||
| 406 | drop: | 411 | drop: |
| 407 | kfree_skb(skb); | 412 | kfree_skb(skb); |
| 408 | out: | 413 | out: |
| @@ -427,12 +432,12 @@ static int pppoe_disc_rcv(struct sk_buff *skb, | |||
| 427 | if (dev_net(dev) != &init_net) | 432 | if (dev_net(dev) != &init_net) |
| 428 | goto abort; | 433 | goto abort; |
| 429 | 434 | ||
| 430 | if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) | ||
| 431 | goto abort; | ||
| 432 | |||
| 433 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) | 435 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) |
| 434 | goto out; | 436 | goto out; |
| 435 | 437 | ||
| 438 | if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) | ||
| 439 | goto abort; | ||
| 440 | |||
| 436 | ph = pppoe_hdr(skb); | 441 | ph = pppoe_hdr(skb); |
| 437 | if (ph->code != PADT_CODE) | 442 | if (ph->code != PADT_CODE) |
| 438 | goto abort; | 443 | goto abort; |
| @@ -937,12 +942,10 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 937 | m->msg_namelen = 0; | 942 | m->msg_namelen = 0; |
| 938 | 943 | ||
| 939 | if (skb) { | 944 | if (skb) { |
| 940 | struct pppoe_hdr *ph = pppoe_hdr(skb); | 945 | total_len = min(total_len, skb->len); |
| 941 | const int len = ntohs(ph->length); | 946 | error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); |
| 942 | |||
| 943 | error = memcpy_toiovec(m->msg_iov, (unsigned char *) &ph->tag[0], len); | ||
| 944 | if (error == 0) | 947 | if (error == 0) |
| 945 | error = len; | 948 | error = total_len; |
| 946 | } | 949 | } |
| 947 | 950 | ||
| 948 | kfree_skb(skb); | 951 | kfree_skb(skb); |
