diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index da73e8a8c18d..594c078c5ebc 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -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; |