diff options
author | Oliver Hartkopp <socketcan@hartkopp.net> | 2014-01-30 10:11:28 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-03-06 21:30:03 -0800 |
commit | 8e88041811392a2d9ea989d6dc4a0430bf134700 (patch) | |
tree | 5cdcf70998349809f9e38cd2be561796e4473e7b /include | |
parent | b9776f59637c237b85d493c2cb48bd3e14e4ba7b (diff) | |
download | linux-3.10-8e88041811392a2d9ea989d6dc4a0430bf134700.tar.gz linux-3.10-8e88041811392a2d9ea989d6dc4a0430bf134700.tar.bz2 linux-3.10-8e88041811392a2d9ea989d6dc4a0430bf134700.zip |
can: add destructor for self generated skbs
[ Upstream commit 0ae89beb283a0db5980d1d4781c7d7be2f2810d6 ]
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/can/skb.h | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index 2f0543f7510..f9bbbb47266 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h @@ -11,7 +11,9 @@ #define CAN_SKB_H #include <linux/types.h> +#include <linux/skbuff.h> #include <linux/can.h> +#include <net/sock.h> /* * 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) skb_reserve(skb, sizeof(struct can_skb_priv)); } +static inline void can_skb_destructor(struct sk_buff *skb) +{ + sock_put(skb->sk); +} + +static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) +{ + if (sk) { + sock_hold(sk); + skb->destructor = can_skb_destructor; + skb->sk = sk; + } +} + +/* + * returns an unshared skb owned by the original sock to be echo'ed back + */ +static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb) +{ + if (skb_shared(skb)) { + struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); + + if (likely(nskb)) { + can_skb_set_owner(nskb, skb->sk); + consume_skb(skb); + return nskb; + } else { + kfree_skb(skb); + return NULL; + } + } + + /* we can assume to have an unshared skb with proper owner */ + return skb; +} + #endif /* CAN_SKB_H */ |