diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index da73e8a8c18d..6dc01bdeb76b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -359,6 +359,10 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, | |||
359 | if (dev == NULL) | 359 | if (dev == NULL) |
360 | goto out_unlock; | 360 | goto out_unlock; |
361 | 361 | ||
362 | err = -ENETDOWN; | ||
363 | if (!(dev->flags & IFF_UP)) | ||
364 | goto out_unlock; | ||
365 | |||
362 | /* | 366 | /* |
363 | * You may not queue a frame bigger than the mtu. This is the lowest level | 367 | * You may not queue a frame bigger than the mtu. This is the lowest level |
364 | * raw protocol and you must do your own fragmentation at this level. | 368 | * raw protocol and you must do your own fragmentation at this level. |
@@ -407,10 +411,6 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, | |||
407 | if (err) | 411 | if (err) |
408 | goto out_free; | 412 | goto out_free; |
409 | 413 | ||
410 | err = -ENETDOWN; | ||
411 | if (!(dev->flags & IFF_UP)) | ||
412 | goto out_free; | ||
413 | |||
414 | /* | 414 | /* |
415 | * Now send it | 415 | * Now send it |
416 | */ | 416 | */ |
@@ -428,24 +428,18 @@ out_unlock: | |||
428 | } | 428 | } |
429 | #endif | 429 | #endif |
430 | 430 | ||
431 | static inline int run_filter(struct sk_buff *skb, struct sock *sk, | 431 | static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk, |
432 | unsigned *snaplen) | 432 | unsigned int res) |
433 | { | 433 | { |
434 | struct sk_filter *filter; | 434 | struct sk_filter *filter; |
435 | int err = 0; | ||
436 | 435 | ||
437 | rcu_read_lock_bh(); | 436 | rcu_read_lock_bh(); |
438 | filter = rcu_dereference(sk->sk_filter); | 437 | filter = rcu_dereference(sk->sk_filter); |
439 | if (filter != NULL) { | 438 | if (filter != NULL) |
440 | err = sk_run_filter(skb, filter->insns, filter->len); | 439 | res = sk_run_filter(skb, filter->insns, filter->len); |
441 | if (!err) | ||
442 | err = -EPERM; | ||
443 | else if (*snaplen > err) | ||
444 | *snaplen = err; | ||
445 | } | ||
446 | rcu_read_unlock_bh(); | 440 | rcu_read_unlock_bh(); |
447 | 441 | ||
448 | return err; | 442 | return res; |
449 | } | 443 | } |
450 | 444 | ||
451 | /* | 445 | /* |
@@ -467,7 +461,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet | |||
467 | struct packet_sock *po; | 461 | struct packet_sock *po; |
468 | u8 * skb_head = skb->data; | 462 | u8 * skb_head = skb->data; |
469 | int skb_len = skb->len; | 463 | int skb_len = skb->len; |
470 | unsigned snaplen; | 464 | unsigned int snaplen, res; |
471 | 465 | ||
472 | if (skb->pkt_type == PACKET_LOOPBACK) | 466 | if (skb->pkt_type == PACKET_LOOPBACK) |
473 | goto drop; | 467 | goto drop; |
@@ -495,8 +489,11 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet | |||
495 | 489 | ||
496 | snaplen = skb->len; | 490 | snaplen = skb->len; |
497 | 491 | ||
498 | if (run_filter(skb, sk, &snaplen) < 0) | 492 | res = run_filter(skb, sk, snaplen); |
493 | if (!res) | ||
499 | goto drop_n_restore; | 494 | goto drop_n_restore; |
495 | if (snaplen > res) | ||
496 | snaplen = res; | ||
500 | 497 | ||
501 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | 498 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
502 | (unsigned)sk->sk_rcvbuf) | 499 | (unsigned)sk->sk_rcvbuf) |
@@ -568,7 +565,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe | |||
568 | struct tpacket_hdr *h; | 565 | struct tpacket_hdr *h; |
569 | u8 * skb_head = skb->data; | 566 | u8 * skb_head = skb->data; |
570 | int skb_len = skb->len; | 567 | int skb_len = skb->len; |
571 | unsigned snaplen; | 568 | unsigned int snaplen, res; |
572 | unsigned long status = TP_STATUS_LOSING|TP_STATUS_USER; | 569 | unsigned long status = TP_STATUS_LOSING|TP_STATUS_USER; |
573 | unsigned short macoff, netoff; | 570 | unsigned short macoff, netoff; |
574 | struct sk_buff *copy_skb = NULL; | 571 | struct sk_buff *copy_skb = NULL; |
@@ -592,8 +589,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe | |||
592 | 589 | ||
593 | snaplen = skb->len; | 590 | snaplen = skb->len; |
594 | 591 | ||
595 | if (run_filter(skb, sk, &snaplen) < 0) | 592 | res = run_filter(skb, sk, snaplen); |
593 | if (!res) | ||
596 | goto drop_n_restore; | 594 | goto drop_n_restore; |
595 | if (snaplen > res) | ||
596 | snaplen = res; | ||
597 | 597 | ||
598 | if (sk->sk_type == SOCK_DGRAM) { | 598 | if (sk->sk_type == SOCK_DGRAM) { |
599 | macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16; | 599 | macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16; |
@@ -738,6 +738,10 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
738 | if (sock->type == SOCK_RAW) | 738 | if (sock->type == SOCK_RAW) |
739 | reserve = dev->hard_header_len; | 739 | reserve = dev->hard_header_len; |
740 | 740 | ||
741 | err = -ENETDOWN; | ||
742 | if (!(dev->flags & IFF_UP)) | ||
743 | goto out_unlock; | ||
744 | |||
741 | err = -EMSGSIZE; | 745 | err = -EMSGSIZE; |
742 | if (len > dev->mtu+reserve) | 746 | if (len > dev->mtu+reserve) |
743 | goto out_unlock; | 747 | goto out_unlock; |
@@ -770,10 +774,6 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
770 | skb->dev = dev; | 774 | skb->dev = dev; |
771 | skb->priority = sk->sk_priority; | 775 | skb->priority = sk->sk_priority; |
772 | 776 | ||
773 | err = -ENETDOWN; | ||
774 | if (!(dev->flags & IFF_UP)) | ||
775 | goto out_free; | ||
776 | |||
777 | /* | 777 | /* |
778 | * Now send it | 778 | * Now send it |
779 | */ | 779 | */ |