summaryrefslogtreecommitdiff
path: root/net/netlink/af_netlink.h
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2015-09-10 21:05:46 +0300
committerDavid S. Miller <davem@davemloft.net>2015-09-12 00:36:49 +0300
commit1853c949646005b5959c483becde86608f548f24 (patch)
tree2ee10a97fd0d6a3c22340094f0dd211ef9da2fd1 /net/netlink/af_netlink.h
parent64d1def7d33856824d2c5c6fd6d4579d4d54bb87 (diff)
downloadlinux-1853c949646005b5959c483becde86608f548f24.tar.xz
netlink, mmap: transform mmap skb into full skb on taps
Ken-ichirou reported that running netlink in mmap mode for receive in combination with nlmon will throw a NULL pointer dereference in __kfree_skb() on nlmon_xmit(), in my case I can also trigger an "unable to handle kernel paging request". The problem is the skb_clone() in __netlink_deliver_tap_skb() for skbs that are mmaped. I.e. the cloned skb doesn't have a destructor, whereas the mmap netlink skb has it pointed to netlink_skb_destructor(), set in the handler netlink_ring_setup_skb(). There, skb->head is being set to NULL, so that in such cases, __kfree_skb() doesn't perform a skb_release_data() via skb_release_all(), where skb->head is possibly being freed through kfree(head) into slab allocator, although netlink mmap skb->head points to the mmap buffer. Similarly, the same has to be done also for large netlink skbs where the data area is vmalloced. Therefore, as discussed, make a copy for these rather rare cases for now. This fixes the issue on my and Ken-ichirou's test-cases. Reference: http://thread.gmane.org/gmane.linux.network/371129 Fixes: bcbde0d449ed ("net: netlink: virtual tap device management") Reported-by: Ken-ichirou MATSUZAWA <chamaken@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Tested-by: Ken-ichirou MATSUZAWA <chamaken@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/af_netlink.h')
-rw-r--r--net/netlink/af_netlink.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index 89008405d6b4..df9a06090db6 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -59,6 +59,15 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk)
return container_of(sk, struct netlink_sock, sk);
}
+static inline bool netlink_skb_is_mmaped(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NETLINK_MMAP
+ return NETLINK_CB(skb).flags & NETLINK_SKB_MMAPED;
+#else
+ return false;
+#endif /* CONFIG_NETLINK_MMAP */
+}
+
struct netlink_table {
struct rhashtable hash;
struct hlist_head mc_list;