diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2014-01-30 04:11:28 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-30 19:25:49 -0500 |
commit | 0ae89beb283a0db5980d1d4781c7d7be2f2810d6 (patch) | |
tree | 70260be9219b03dbc8e96f852a8900db7845cbc9 /drivers/net/can | |
parent | 920a0fde5a32fd40b4d3c94ad72f7fc7039db8e3 (diff) |
can: add destructor for self generated skbs
Self generated skbuffs in net/can/bcm.c are setting a skb->sk reference but
no explicit destructor which is enforced since Linux 3.11 with commit
376c7311bdb6 (net: add a temporary sanity check in skb_orphan()).
This patch adds some helper functions to make sure that a destructor is
properly defined when a sock reference is assigned to a CAN related skb.
To create an unshared skb owned by the original sock a common helper function
has been introduced to replace open coded functions to create CAN echo skbs.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Tested-by: Andre Naujoks <nautsch2@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/dev.c | 15 | ||||
-rw-r--r-- | drivers/net/can/janz-ican3.c | 18 | ||||
-rw-r--r-- | drivers/net/can/vcan.c | 9 |
3 files changed, 11 insertions, 31 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 13a909822e25..fc59bc6f040b 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
@@ -323,19 +323,10 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, | |||
323 | } | 323 | } |
324 | 324 | ||
325 | if (!priv->echo_skb[idx]) { | 325 | if (!priv->echo_skb[idx]) { |
326 | struct sock *srcsk = skb->sk; | ||
327 | 326 | ||
328 | if (atomic_read(&skb->users) != 1) { | 327 | skb = can_create_echo_skb(skb); |
329 | struct sk_buff *old_skb = skb; | 328 | if (!skb) |
330 | 329 | return; | |
331 | skb = skb_clone(old_skb, GFP_ATOMIC); | ||
332 | kfree_skb(old_skb); | ||
333 | if (!skb) | ||
334 | return; | ||
335 | } else | ||
336 | skb_orphan(skb); | ||
337 | |||
338 | skb->sk = srcsk; | ||
339 | 330 | ||
340 | /* make settings for echo to reduce code in irq context */ | 331 | /* make settings for echo to reduce code in irq context */ |
341 | skb->protocol = htons(ETH_P_CAN); | 332 | skb->protocol = htons(ETH_P_CAN); |
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index e24e6690d672..2124c6790687 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/netdevice.h> | 18 | #include <linux/netdevice.h> |
19 | #include <linux/can.h> | 19 | #include <linux/can.h> |
20 | #include <linux/can/dev.h> | 20 | #include <linux/can/dev.h> |
21 | #include <linux/can/skb.h> | ||
21 | #include <linux/can/error.h> | 22 | #include <linux/can/error.h> |
22 | 23 | ||
23 | #include <linux/mfd/janz.h> | 24 | #include <linux/mfd/janz.h> |
@@ -1133,20 +1134,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg) | |||
1133 | */ | 1134 | */ |
1134 | static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb) | 1135 | static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb) |
1135 | { | 1136 | { |
1136 | struct sock *srcsk = skb->sk; | 1137 | skb = can_create_echo_skb(skb); |
1137 | 1138 | if (!skb) | |
1138 | if (atomic_read(&skb->users) != 1) { | 1139 | return; |
1139 | struct sk_buff *old_skb = skb; | ||
1140 | |||
1141 | skb = skb_clone(old_skb, GFP_ATOMIC); | ||
1142 | kfree_skb(old_skb); | ||
1143 | if (!skb) | ||
1144 | return; | ||
1145 | } else { | ||
1146 | skb_orphan(skb); | ||
1147 | } | ||
1148 | |||
1149 | skb->sk = srcsk; | ||
1150 | 1140 | ||
1151 | /* save this skb for tx interrupt echo handling */ | 1141 | /* save this skb for tx interrupt echo handling */ |
1152 | skb_queue_tail(&mod->echoq, skb); | 1142 | skb_queue_tail(&mod->echoq, skb); |
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 0a2a5ee79a17..4e94057ef5cf 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/if_ether.h> | 46 | #include <linux/if_ether.h> |
47 | #include <linux/can.h> | 47 | #include <linux/can.h> |
48 | #include <linux/can/dev.h> | 48 | #include <linux/can/dev.h> |
49 | #include <linux/can/skb.h> | ||
49 | #include <linux/slab.h> | 50 | #include <linux/slab.h> |
50 | #include <net/rtnetlink.h> | 51 | #include <net/rtnetlink.h> |
51 | 52 | ||
@@ -109,25 +110,23 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) | |||
109 | stats->rx_packets++; | 110 | stats->rx_packets++; |
110 | stats->rx_bytes += cfd->len; | 111 | stats->rx_bytes += cfd->len; |
111 | } | 112 | } |
112 | kfree_skb(skb); | 113 | consume_skb(skb); |
113 | return NETDEV_TX_OK; | 114 | return NETDEV_TX_OK; |
114 | } | 115 | } |
115 | 116 | ||
116 | /* perform standard echo handling for CAN network interfaces */ | 117 | /* perform standard echo handling for CAN network interfaces */ |
117 | 118 | ||
118 | if (loop) { | 119 | if (loop) { |
119 | struct sock *srcsk = skb->sk; | ||
120 | 120 | ||
121 | skb = skb_share_check(skb, GFP_ATOMIC); | 121 | skb = can_create_echo_skb(skb); |
122 | if (!skb) | 122 | if (!skb) |
123 | return NETDEV_TX_OK; | 123 | return NETDEV_TX_OK; |
124 | 124 | ||
125 | /* receive with packet counting */ | 125 | /* receive with packet counting */ |
126 | skb->sk = srcsk; | ||
127 | vcan_rx(skb, dev); | 126 | vcan_rx(skb, dev); |
128 | } else { | 127 | } else { |
129 | /* no looped packets => no counting */ | 128 | /* no looped packets => no counting */ |
130 | kfree_skb(skb); | 129 | consume_skb(skb); |
131 | } | 130 | } |
132 | return NETDEV_TX_OK; | 131 | return NETDEV_TX_OK; |
133 | } | 132 | } |