summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorMarco Elver <elver@google.com>2020-11-25 23:48:40 +0100
committerJakub Kicinski <kuba@kernel.org>2020-12-01 11:26:19 -0800
commitfa69ee5aa48b5b52e8028c2eb486906e9998d081 (patch)
tree3a93e691ed484fd22681f316ca1cb54719a112d9 /include
parent0fca55ed988a694f5896f36de2a8f18715a78279 (diff)
downloadlinux-fa69ee5aa48b5b52e8028c2eb486906e9998d081.tar.bz2
net: switch to storing KCOV handle directly in sk_buff
It turns out that usage of skb extensions can cause memory leaks. Ido Schimmel reported: "[...] there are instances that blindly overwrite 'skb->extensions' by invoking skb_copy_header() after __alloc_skb()." Therefore, give up on using skb extensions for KCOV handle, and instead directly store kcov_handle in sk_buff. Fixes: 6370cc3bbd8a ("net: add kcov handle to skb extensions") Fixes: 85ce50d337d1 ("net: kcov: don't select SKB_EXTENSIONS when there is no NET") Fixes: 97f53a08cba1 ("net: linux/skbuff.h: combine SKB_EXTENSIONS + KCOV handling") Link: https://lore.kernel.org/linux-wireless/20201121160941.GA485907@shredder.lan/ Reported-by: Ido Schimmel <idosch@idosch.org> Signed-off-by: Marco Elver <elver@google.com> Link: https://lore.kernel.org/r/20201125224840.2014773-1-elver@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/skbuff.h37
1 files changed, 13 insertions, 24 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 0a1239819fd2..333bcdc39635 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -701,6 +701,7 @@ typedef unsigned char *sk_buff_data_t;
* @transport_header: Transport layer header
* @network_header: Network layer header
* @mac_header: Link layer header
+ * @kcov_handle: KCOV remote handle for remote coverage collection
* @tail: Tail pointer
* @end: End pointer
* @head: Head of buffer
@@ -904,6 +905,10 @@ struct sk_buff {
__u16 network_header;
__u16 mac_header;
+#ifdef CONFIG_KCOV
+ u64 kcov_handle;
+#endif
+
/* private: */
__u32 headers_end[0];
/* public: */
@@ -4151,9 +4156,6 @@ enum skb_ext_id {
#if IS_ENABLED(CONFIG_MPTCP)
SKB_EXT_MPTCP,
#endif
-#if IS_ENABLED(CONFIG_KCOV)
- SKB_EXT_KCOV_HANDLE,
-#endif
SKB_EXT_NUM, /* must be last */
};
@@ -4608,35 +4610,22 @@ static inline void skb_reset_redirect(struct sk_buff *skb)
#endif
}
-#if IS_ENABLED(CONFIG_KCOV) && IS_ENABLED(CONFIG_SKB_EXTENSIONS)
static inline void skb_set_kcov_handle(struct sk_buff *skb,
const u64 kcov_handle)
{
- /* Do not allocate skb extensions only to set kcov_handle to zero
- * (as it is zero by default). However, if the extensions are
- * already allocated, update kcov_handle anyway since
- * skb_set_kcov_handle can be called to zero a previously set
- * value.
- */
- if (skb_has_extensions(skb) || kcov_handle) {
- u64 *kcov_handle_ptr = skb_ext_add(skb, SKB_EXT_KCOV_HANDLE);
-
- if (kcov_handle_ptr)
- *kcov_handle_ptr = kcov_handle;
- }
+#ifdef CONFIG_KCOV
+ skb->kcov_handle = kcov_handle;
+#endif
}
static inline u64 skb_get_kcov_handle(struct sk_buff *skb)
{
- u64 *kcov_handle = skb_ext_find(skb, SKB_EXT_KCOV_HANDLE);
-
- return kcov_handle ? *kcov_handle : 0;
-}
+#ifdef CONFIG_KCOV
+ return skb->kcov_handle;
#else
-static inline void skb_set_kcov_handle(struct sk_buff *skb,
- const u64 kcov_handle) { }
-static inline u64 skb_get_kcov_handle(struct sk_buff *skb) { return 0; }
-#endif /* CONFIG_KCOV && CONFIG_SKB_EXTENSIONS */
+ return 0;
+#endif
+}
#endif /* __KERNEL__ */
#endif /* _LINUX_SKBUFF_H */