Patch "netlink, mmap: transform mmap skb into full skb on taps" has been added to the 3.14-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
netlink, mmap: transform mmap skb into full skb on taps
to the 3.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
netlink-mmap-transform-mmap-skb-into-full-skb-on-taps.patch
and it can be found in the queue-3.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Tue Sep 29 14:20:37 CEST 2015
From: Daniel Borkmann <[email protected]>
Date: Thu, 10 Sep 2015 20:05:46 +0200
Subject: netlink, mmap: transform mmap skb into full skb on taps
From: Daniel Borkmann <[email protected]>
[ Upstream commit 1853c949646005b5959c483becde86608f548f24 ]
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
--- net/netlink/af_netlink.c | 30 +++++++++++++++++++++++------- net/netlink/af_netlink.h | 9 +++++++++ 2 files changed, 32 insertions(+), 7 deletions(-)
net/netlink/af_netlink.c +23 -7
@@ -115,6 +115,24 @@ static inline struct hlist_head *nl_portreturn &hash->table[jhash_1word (portid, hash->rnd) & hash->mask]; } +static struct sk_buff *netlink_to_full_skb (const struct sk_buff *skb, +gfp_t gfp_mask) +{ +unsigned int len =skb_end_offset (skb); +struct sk_buff *new; + + new =alloc_skb (len, gfp_mask); +if (new ==NULL ) +return NULL ; + +NETLINK_CB (new).portid =NETLINK_CB (skb).portid; +NETLINK_CB (new).dst_group =NETLINK_CB (skb).dst_group; +NETLINK_CB (new).creds =NETLINK_CB (skb).creds; + +memcpy (skb_put (new, len), skb->data, len); +return new; +} +int netlink_add_tap (struct netlink_tap *nt) {if (unlikely (nt->dev->type !=ARPHRD_NETLINK ))
@@ -199,7 +217,11 @@ static int __netlink_deliver_tap_skb(strint ret = -ENOMEM ;dev_hold (dev); - nskb =skb_clone (skb,GFP_ATOMIC ); + +if (netlink_skb_is_mmaped (skb) ||is_vmalloc_addr (skb->head)) + nskb =netlink_to_full_skb (skb,GFP_ATOMIC ); +else + nskb =skb_clone (skb,GFP_ATOMIC );if (nskb) { nskb->dev = dev; nskb->protocol =htons ((u16 ) sk->sk_protocol);
@@ -271,11 +293,6 @@ static void netlink_rcv_wake(struct sock }#ifdef CONFIG_NETLINK_MMAP -static bool netlink_skb_is_mmaped (const struct sk_buff *skb) -{ -return NETLINK_CB (skb).flags &NETLINK_SKB_MMAPED ; -} -static bool netlink_rx_is_mmaped (struct sock *sk) {return nlk_sk (sk)->rx_ring.pg_vec !=NULL ;
@@ -827,7 +844,6 @@ static void netlink_ring_set_copied(stru }#else /* CONFIG_NETLINK_MMAP */ -#define netlink_skb_is_mmaped (skb) false#define netlink_rx_is_mmaped (sk) false#define netlink_tx_is_mmaped (sk) false#define netlink_mmap sock_no_mmap
net/netlink/af_netlink.h +9 -0
@@ -65,6 +65,15 @@ struct nl_portid_hash {u32 rnd; }; +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 nl_portid_hash hash;struct hlist_head mc_list;
Patches currently in stable-queue which might be from [email protected] are
queue-3.14/ipv6-fix-exthdrs-offload-registration-in-out_rt-path.patch queue-3.14/rtnetlink-verify-ifla_vf_info-attributes-before-passing-them-to-driver.patch queue-3.14/netlink-mmap-transform-mmap-skb-into-full-skb-on-taps.patch