| From foo@baz Thu Feb 27 20:11:26 PST 2014 |
| From: Antonio Quartulli <antonio@meshcoding.com> |
| Date: Sat, 15 Feb 2014 21:50:37 +0100 |
| Subject: batman-adv: fix potential kernel paging error for unicast transmissions |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Antonio Quartulli <antonio@meshcoding.com> |
| |
| [ Upstream commit 70b271a78beba787155d6696aacd7c4d4a251c50 ] |
| |
| batadv_send_skb_prepare_unicast(_4addr) might reallocate the |
| skb's data. If it does then our ethhdr pointer is not valid |
| anymore in batadv_send_skb_unicast(), resulting in a kernel |
| paging error. |
| |
| Fixing this by refetching the ethhdr pointer after the |
| potential reallocation. |
| |
| Signed-off-by: Linus Lüssing <linus.luessing@web.de> |
| Signed-off-by: Antonio Quartulli <antonio@meshcoding.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/batman-adv/send.c | 9 +++++++-- |
| 1 file changed, 7 insertions(+), 2 deletions(-) |
| |
| --- a/net/batman-adv/send.c |
| +++ b/net/batman-adv/send.c |
| @@ -256,9 +256,9 @@ static int batadv_send_skb_unicast(struc |
| struct batadv_orig_node *orig_node, |
| unsigned short vid) |
| { |
| - struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
| + struct ethhdr *ethhdr; |
| struct batadv_unicast_packet *unicast_packet; |
| - int ret = NET_XMIT_DROP; |
| + int ret = NET_XMIT_DROP, hdr_size; |
| |
| if (!orig_node) |
| goto out; |
| @@ -267,12 +267,16 @@ static int batadv_send_skb_unicast(struc |
| case BATADV_UNICAST: |
| if (!batadv_send_skb_prepare_unicast(skb, orig_node)) |
| goto out; |
| + |
| + hdr_size = sizeof(*unicast_packet); |
| break; |
| case BATADV_UNICAST_4ADDR: |
| if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, |
| orig_node, |
| packet_subtype)) |
| goto out; |
| + |
| + hdr_size = sizeof(struct batadv_unicast_4addr_packet); |
| break; |
| default: |
| /* this function supports UNICAST and UNICAST_4ADDR only. It |
| @@ -281,6 +285,7 @@ static int batadv_send_skb_unicast(struc |
| goto out; |
| } |
| |
| + ethhdr = (struct ethhdr *)(skb->data + hdr_size); |
| unicast_packet = (struct batadv_unicast_packet *)skb->data; |
| |
| /* inform the destination node that we are still missing a correct route |