Skip to content
This repository was archived by the owner on Oct 30, 2021. It is now read-only.

Commit 0ae89be

Browse files
hartkoppdavem330
authored andcommitted
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 376c731 (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>
1 parent 920a0fd commit 0ae89be

File tree

6 files changed

+53
-34
lines changed

6 files changed

+53
-34
lines changed

drivers/net/can/dev.c

+3-12
Original file line numberDiff line numberDiff line change
@@ -323,19 +323,10 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
323323
}
324324

325325
if (!priv->echo_skb[idx]) {
326-
struct sock *srcsk = skb->sk;
327326

328-
if (atomic_read(&skb->users) != 1) {
329-
struct sk_buff *old_skb = skb;
330-
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;
327+
skb = can_create_echo_skb(skb);
328+
if (!skb)
329+
return;
339330

340331
/* make settings for echo to reduce code in irq context */
341332
skb->protocol = htons(ETH_P_CAN);

drivers/net/can/janz-ican3.c

+4-14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/netdevice.h>
1919
#include <linux/can.h>
2020
#include <linux/can/dev.h>
21+
#include <linux/can/skb.h>
2122
#include <linux/can/error.h>
2223

2324
#include <linux/mfd/janz.h>
@@ -1133,20 +1134,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg)
11331134
*/
11341135
static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb)
11351136
{
1136-
struct sock *srcsk = skb->sk;
1137-
1138-
if (atomic_read(&skb->users) != 1) {
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;
1137+
skb = can_create_echo_skb(skb);
1138+
if (!skb)
1139+
return;
11501140

11511141
/* save this skb for tx interrupt echo handling */
11521142
skb_queue_tail(&mod->echoq, skb);

drivers/net/can/vcan.c

+4-5
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <linux/if_ether.h>
4747
#include <linux/can.h>
4848
#include <linux/can/dev.h>
49+
#include <linux/can/skb.h>
4950
#include <linux/slab.h>
5051
#include <net/rtnetlink.h>
5152

@@ -109,25 +110,23 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev)
109110
stats->rx_packets++;
110111
stats->rx_bytes += cfd->len;
111112
}
112-
kfree_skb(skb);
113+
consume_skb(skb);
113114
return NETDEV_TX_OK;
114115
}
115116

116117
/* perform standard echo handling for CAN network interfaces */
117118

118119
if (loop) {
119-
struct sock *srcsk = skb->sk;
120120

121-
skb = skb_share_check(skb, GFP_ATOMIC);
121+
skb = can_create_echo_skb(skb);
122122
if (!skb)
123123
return NETDEV_TX_OK;
124124

125125
/* receive with packet counting */
126-
skb->sk = srcsk;
127126
vcan_rx(skb, dev);
128127
} else {
129128
/* no looped packets => no counting */
130-
kfree_skb(skb);
129+
consume_skb(skb);
131130
}
132131
return NETDEV_TX_OK;
133132
}

include/linux/can/skb.h

+38
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
#define CAN_SKB_H
1212

1313
#include <linux/types.h>
14+
#include <linux/skbuff.h>
1415
#include <linux/can.h>
16+
#include <net/sock.h>
1517

1618
/*
1719
* The struct can_skb_priv is used to transport additional information along
@@ -42,4 +44,40 @@ static inline void can_skb_reserve(struct sk_buff *skb)
4244
skb_reserve(skb, sizeof(struct can_skb_priv));
4345
}
4446

47+
static inline void can_skb_destructor(struct sk_buff *skb)
48+
{
49+
sock_put(skb->sk);
50+
}
51+
52+
static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
53+
{
54+
if (sk) {
55+
sock_hold(sk);
56+
skb->destructor = can_skb_destructor;
57+
skb->sk = sk;
58+
}
59+
}
60+
61+
/*
62+
* returns an unshared skb owned by the original sock to be echo'ed back
63+
*/
64+
static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
65+
{
66+
if (skb_shared(skb)) {
67+
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
68+
69+
if (likely(nskb)) {
70+
can_skb_set_owner(nskb, skb->sk);
71+
consume_skb(skb);
72+
return nskb;
73+
} else {
74+
kfree_skb(skb);
75+
return NULL;
76+
}
77+
}
78+
79+
/* we can assume to have an unshared skb with proper owner */
80+
return skb;
81+
}
82+
4583
#endif /* CAN_SKB_H */

net/can/af_can.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include <linux/skbuff.h>
5858
#include <linux/can.h>
5959
#include <linux/can/core.h>
60+
#include <linux/can/skb.h>
6061
#include <linux/ratelimit.h>
6162
#include <net/net_namespace.h>
6263
#include <net/sock.h>
@@ -290,7 +291,7 @@ int can_send(struct sk_buff *skb, int loop)
290291
return -ENOMEM;
291292
}
292293

293-
newskb->sk = skb->sk;
294+
can_skb_set_owner(newskb, skb->sk);
294295
newskb->ip_summed = CHECKSUM_UNNECESSARY;
295296
newskb->pkt_type = PACKET_BROADCAST;
296297
}

net/can/bcm.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ static void bcm_can_tx(struct bcm_op *op)
268268

269269
/* send with loopback */
270270
skb->dev = dev;
271-
skb->sk = op->sk;
271+
can_skb_set_owner(skb, op->sk);
272272
can_send(skb, 1);
273273

274274
/* update statistics */
@@ -1223,7 +1223,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
12231223

12241224
can_skb_prv(skb)->ifindex = dev->ifindex;
12251225
skb->dev = dev;
1226-
skb->sk = sk;
1226+
can_skb_set_owner(skb, sk);
12271227
err = can_send(skb, 1); /* send with loopback */
12281228
dev_put(dev);
12291229

0 commit comments

Comments
 (0)