Skip to content

Commit

Permalink
[AF_PACKET]: Fix BPF handling.
Browse files Browse the repository at this point in the history
This fixes a bug introduced by:

commit fda9ef5
Author: Dmitry Mishin <dim@openvz.org>
Date:   Thu Aug 31 15:28:39 2006 -0700

    [NET]: Fix sk->sk_filter field access

sk_run_filter() returns either 0 or an unsigned 32-bit
length which says how much of the packet to retain.
If that 32-bit unsigned integer is larger than the packet,
this is fine we just leave the packet unchanged.

The above commit caused all filter return values which
were negative when interpreted as a signed integer to
indicate a packet drop, which is wrong.

Based upon a report and initial patch by Raivis Bucis.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 24, 2007
1 parent 6640e69 commit dbcb585
Showing 1 changed file with 15 additions and 15 deletions.
30 changes: 15 additions & 15 deletions net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,24 +428,18 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
}
#endif

static inline int run_filter(struct sk_buff *skb, struct sock *sk,
unsigned *snaplen)
static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
unsigned int res)
{
struct sk_filter *filter;
int err = 0;

rcu_read_lock_bh();
filter = rcu_dereference(sk->sk_filter);
if (filter != NULL) {
err = sk_run_filter(skb, filter->insns, filter->len);
if (!err)
err = -EPERM;
else if (*snaplen > err)
*snaplen = err;
}
if (filter != NULL)
res = sk_run_filter(skb, filter->insns, filter->len);
rcu_read_unlock_bh();

return err;
return res;
}

/*
Expand All @@ -467,7 +461,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
struct packet_sock *po;
u8 * skb_head = skb->data;
int skb_len = skb->len;
unsigned snaplen;
unsigned int snaplen, res;

if (skb->pkt_type == PACKET_LOOPBACK)
goto drop;
Expand Down Expand Up @@ -495,8 +489,11 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet

snaplen = skb->len;

if (run_filter(skb, sk, &snaplen) < 0)
res = run_filter(skb, sk, snaplen);
if (!res)
goto drop_n_restore;
if (snaplen > res)
snaplen = res;

if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
(unsigned)sk->sk_rcvbuf)
Expand Down Expand Up @@ -568,7 +565,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
struct tpacket_hdr *h;
u8 * skb_head = skb->data;
int skb_len = skb->len;
unsigned snaplen;
unsigned int snaplen, res;
unsigned long status = TP_STATUS_LOSING|TP_STATUS_USER;
unsigned short macoff, netoff;
struct sk_buff *copy_skb = NULL;
Expand All @@ -592,8 +589,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe

snaplen = skb->len;

if (run_filter(skb, sk, &snaplen) < 0)
res = run_filter(skb, sk, snaplen);
if (!res)
goto drop_n_restore;
if (snaplen > res)
snaplen = res;

if (sk->sk_type == SOCK_DGRAM) {
macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16;
Expand Down

0 comments on commit dbcb585

Please sign in to comment.