diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 50 |
1 files changed, 10 insertions, 40 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4f2c0df7956..0f661745df0 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1654,7 +1654,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, skb->data = skb_head; skb->len = skb_len; } - kfree_skb(skb); + consume_skb(skb); skb = nskb; } @@ -1764,7 +1764,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, macoff = netoff = TPACKET_ALIGN(po->tp_hdrlen) + 16 + po->tp_reserve; } else { - unsigned maclen = skb_network_offset(skb); + unsigned int maclen = skb_network_offset(skb); netoff = TPACKET_ALIGN(po->tp_hdrlen + (maclen < 16 ? 16 : maclen)) + po->tp_reserve; @@ -3224,10 +3224,10 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { int len; - int val; + int val, lv = sizeof(val); struct sock *sk = sock->sk; struct packet_sock *po = pkt_sk(sk); - void *data; + void *data = &val; struct tpacket_stats st; union tpacket_stats_u st_u; @@ -3242,21 +3242,17 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, switch (optname) { case PACKET_STATISTICS: - if (po->tp_version == TPACKET_V3) { - len = sizeof(struct tpacket_stats_v3); - } else { - if (len > sizeof(struct tpacket_stats)) - len = sizeof(struct tpacket_stats); - } spin_lock_bh(&sk->sk_receive_queue.lock); if (po->tp_version == TPACKET_V3) { + lv = sizeof(struct tpacket_stats_v3); memcpy(&st_u.stats3, &po->stats, - sizeof(struct tpacket_stats)); + sizeof(struct tpacket_stats)); st_u.stats3.tp_freeze_q_cnt = - po->stats_u.stats3.tp_freeze_q_cnt; + po->stats_u.stats3.tp_freeze_q_cnt; st_u.stats3.tp_packets += po->stats.tp_drops; data = &st_u.stats3; } else { + lv = sizeof(struct tpacket_stats); st = po->stats; st.tp_packets += st.tp_drops; data = &st; @@ -3265,31 +3261,16 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, spin_unlock_bh(&sk->sk_receive_queue.lock); break; case PACKET_AUXDATA: - if (len > sizeof(int)) - len = sizeof(int); val = po->auxdata; - - data = &val; break; case PACKET_ORIGDEV: - if (len > sizeof(int)) - len = sizeof(int); val = po->origdev; - - data = &val; break; case PACKET_VNET_HDR: - if (len > sizeof(int)) - len = sizeof(int); val = po->has_vnet_hdr; - - data = &val; break; case PACKET_VERSION: - if (len > sizeof(int)) - len = sizeof(int); val = po->tp_version; - data = &val; break; case PACKET_HDRLEN: if (len > sizeof(int)) @@ -3309,39 +3290,28 @@ static int packet_getsockopt(struct socket *sock, int level, int optname, default: return -EINVAL; } - data = &val; break; case PACKET_RESERVE: - if (len > sizeof(unsigned int)) - len = sizeof(unsigned int); val = po->tp_reserve; - data = &val; break; case PACKET_LOSS: - if (len > sizeof(unsigned int)) - len = sizeof(unsigned int); val = po->tp_loss; - data = &val; break; case PACKET_TIMESTAMP: - if (len > sizeof(int)) - len = sizeof(int); val = po->tp_tstamp; - data = &val; break; case PACKET_FANOUT: - if (len > sizeof(int)) - len = sizeof(int); val = (po->fanout ? ((u32)po->fanout->id | ((u32)po->fanout->type << 16)) : 0); - data = &val; break; default: return -ENOPROTOOPT; } + if (len > lv) + len = lv; if (put_user(len, optlen)) return -EFAULT; if (copy_to_user(optval, data, len)) |