netfilter: ipt_CLUSTERIP: fix out-of-bounds accesses in clusterip_tg_check()
[pandora-kernel.git] / net / can / af_can.c
index 0ce2ad0..57c4364 100644 (file)
@@ -244,6 +244,9 @@ int can_send(struct sk_buff *skb, int loop)
        }
 
        skb->protocol = htons(ETH_P_CAN);
+       skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+       skb_reset_mac_header(skb);
        skb_reset_network_header(skb);
        skb_reset_transport_header(skb);
 
@@ -400,6 +403,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
  * @func: callback function on filter match
  * @data: returned parameter for callback function
  * @ident: string for calling module indentification
+ * @sk: socket pointer (might be NULL)
  *
  * Description:
  *  Invokes the callback function with the received sk_buff and the given
@@ -423,7 +427,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask,
  */
 int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
                    void (*func)(struct sk_buff *, void *), void *data,
-                   char *ident)
+                   char *ident, struct sock *sk)
 {
        struct receiver *r;
        struct hlist_head *rl;
@@ -451,6 +455,7 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
                r->func    = func;
                r->data    = data;
                r->ident   = ident;
+               r->sk      = sk;
 
                hlist_add_head_rcu(&r->list, rl);
                d->entries++;
@@ -475,8 +480,11 @@ EXPORT_SYMBOL(can_rx_register);
 static void can_rx_delete_receiver(struct rcu_head *rp)
 {
        struct receiver *r = container_of(rp, struct receiver, rcu);
+       struct sock *sk = r->sk;
 
        kmem_cache_free(rcv_cache, r);
+       if (sk)
+               sock_put(sk);
 }
 
 /**
@@ -555,8 +563,11 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
        spin_unlock(&can_rcvlists_lock);
 
        /* schedule the receiver item for deletion */
-       if (r)
+       if (r) {
+               if (r->sk)
+                       sock_hold(r->sk);
                call_rcu(&r->rcu, can_rx_delete_receiver);
+       }
 }
 EXPORT_SYMBOL(can_rx_unregister);
 
@@ -642,13 +653,13 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
        if (!net_eq(dev_net(dev), &init_net))
                goto drop;
 
-       if (WARN_ONCE(dev->type != ARPHRD_CAN ||
-                     skb->len != sizeof(struct can_frame) ||
-                     cf->can_dlc > 8,
-                     "PF_CAN: dropped non conform skbuf: "
-                     "dev type %d, len %d, can_dlc %d\n",
-                     dev->type, skb->len, cf->can_dlc))
+       if (unlikely(dev->type != ARPHRD_CAN ||
+                    skb->len != sizeof(struct can_frame) ||
+                    cf->can_dlc > 8)) {
+               pr_warn_once("PF_CAN: dropped non conform CAN skbuf: dev type %d, len %d, can_dlc %d\n",
+                            dev->type, skb->len, cf->can_dlc);
                goto drop;
+       }
 
        /* update statistics */
        can_stats.rx_frames++;