6lowpan: iphc: reset mac_header after decompress to fix panic
Subsystems (5)
PATCH 1/1 6lowpan: iphc: reset mac_header after decompress to fix panic
After decompression of 6lowpan socket data, an IPv6 header is inserted before the existing socket payload. After this, we reset the network_header value of the skb to account for the difference in payload size from prior to decompression + the addition of the IPv6 header.
However, we fail to reset the mac_header value.
Leaving the mac_header value untouched here, can cause a calculation error in net/packet/af_packet.c packet_rcv() function when an AF_PACKET socket is opened in SOCK_RAW mode for use on a 6lowpan interface.
On line 2088, the data pointer is moved backward by the value returned from skb_mac_header(). If skb->data is adjusted so that it is before the skb->head pointer (which can happen when an old value of mac_header is left in place) the kernel generates a panic in net/core/skbuff.c line 1717.
This panic can be generated by BLE 6lowpan interfaces (such as bt0) and 802.15.4 interfaces (such as lowpan0) as they both use the same 6lowpan sources for compression and decompression.
--- net/6lowpan/iphc.c | 1 + 1 file changed, 1 insertion(+)
net/6lowpan/iphc.c +1 -0
@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, hdr.hop_limit, &hdr.daddr);skb_push (skb,sizeof (hdr)); +skb_reset_mac_header (skb);skb_reset_network_header (skb);skb_copy_to_linear_data (skb, &hdr,sizeof (hdr));
Signature · 1 line
2.17.0
Hi,
Quoted 32 lines · Michael Scott
After decompression of 6lowpan socket data, an IPv6 header is inserted before the existing socket payload. After this, we reset the
network_headervalue of the skb to account for the difference in payload size from prior to decompression + the addition of the IPv6 header.However, we fail to reset the
mac_headervalue.Leaving the
mac_headervalue untouched here, can cause a calculation error innet/packet/af_packet.cpacket_rcv()function when anAF_PACKETsocket is opened inSOCK_RAWmode for use on a 6lowpan interface.On line 2088, the data pointer is moved backward by the value returned from
skb_mac_header(). Ifskb->datais adjusted so that it is before theskb->headpointer (which can happen when an old value ofmac_headeris left in place) the kernel generates a panic innet/core/skbuff.cline 1717.This panic can be generated by BLE 6lowpan interfaces (such as bt0) and 802.15.4 interfaces (such as lowpan0) as they both use the same 6lowpan sources for compression and decompression.
Signed-off-by Michael Scott <[email protected]>--- net/6lowpan/iphc.c | 1 + 1 file changed, 1 insertion(+)net/6lowpan/iphc.c +0
-0
net/6lowpan/iphc.c int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, · line 776
Quoted 7 lines
net/6lowpan/iphc.c +1
-0@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, hdr.hop_limit, &hdr.daddr);skb_push (skb,sizeof (hdr)); +skb_reset_mac_header (skb);skb_reset_network_header (skb);skb_copy_to_linear_data (skb, &hdr,sizeof (hdr));
I think it's good to make that if the mac_header gets a dangled pointer. But we don't have a mac header at this point anymore...
There exists also some functionality that the MAC header is not set, I suppose this can be usefuly for tun like interfaces e.g. RAW IP what we have here.
skb_mac_header_was_set
which does:
return skb->mac_header != (typeof(skb->mac_header))~0U;
maybe we can set it as (typeof(skb->mac_header))~0U and then everything will run as far the kernel will not crash anymore.
Question is for me: which upper layer wants access MAC header here on receive path?
It cannot parsed anyhow because so far I know no upper layer can parse at the moment 802.15.4 frames (which is a complex format). Maybe over some header_ops callback?
- Alex
Hello Alexander,
Quoted 55 lines · Alexander Aring
Hi,
Quoted 32 lines · Michael Scott
After decompression of 6lowpan socket data, an IPv6 header is inserted before the existing socket payload. After this, we reset the
network_headervalue of the skb to account for the difference in payload size from prior to decompression + the addition of the IPv6 header.However, we fail to reset the
mac_headervalue.Leaving the
mac_headervalue untouched here, can cause a calculation error innet/packet/af_packet.cpacket_rcv()function when anAF_PACKETsocket is opened inSOCK_RAWmode for use on a 6lowpan interface.On line 2088, the data pointer is moved backward by the value returned from
skb_mac_header(). Ifskb->datais adjusted so that it is before theskb->headpointer (which can happen when an old value ofmac_headeris left in place) the kernel generates a panic innet/core/skbuff.cline 1717.This panic can be generated by BLE 6lowpan interfaces (such as bt0) and 802.15.4 interfaces (such as lowpan0) as they both use the same 6lowpan sources for compression and decompression.
Signed-off-by Michael Scott <[email protected]>--- net/6lowpan/iphc.c | 1 + 1 file changed, 1 insertion(+)net/6lowpan/iphc.c +0
-0net/6lowpan/iphc.c int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, · line 776
Quoted 7 lines
net/6lowpan/iphc.c +1
-0@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, hdr.hop_limit, &hdr.daddr);skb_push (skb,sizeof (hdr)); +skb_reset_mac_header (skb);skb_reset_network_header (skb);skb_copy_to_linear_data (skb, &hdr,sizeof (hdr));I think it's good to make that if the
mac_headergets a dangled pointer. But we don't have a mac header at this point anymore...There exists also some functionality that the MAC header is not set, I suppose this can be usefuly for tun like interfaces e.g. RAW IP what we have here.
skb_mac_header_was_setwhich does:
return
skb->mac_header!= (typeof(skb->mac_header))~0U;
Quoted 8 lines
maybe we can set it as (typeof(skb->mac_header))~0U and then everything will run as far the kernel will not crash anymore.
Question is for me: which upper layer wants access MAC header here on receive path?
It cannot parsed anyhow because so far I know no upper layer can parse at the moment 802.15.4 frames (which is a complex format). Maybe over someheader_opscallback?
I was testing a C program which performs NAT64 handling on packets
destined to a certain IPv6 subnet (64:ff9b::). To do this, the application opens a RAW socket like this: sniff_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); It then sets promiscuous mode and enters a looping call of:
length = recv(sniff_sock, buffer, PACKET_BUFFER, MSG_TRUNC); My host PC kernel would then promptly crash on me. (I'm going to purposely avoid the obvious point of: this probably isn't the best way to parse packets for NAT64 translation as you will get every single packet incoming or outgoing on the host.) Turns out, testing the program on an 802.15.4 6lowpan interface exposed some of the issues which this mailing list (but not myself) is well aware of (no L2 data in the RAW packets) and also led me to debugging this patch to stop the kernel crash. TL;DR: To summarize, any PF_PACKET SOCK_RAW socket which recv()'s IPv6 data from a 6lowpan node will cause this kernel crash eventually (checked on kernel 4.15, 4.16, 4.17 and 4.18-rc1). - Mike
Quoted 2 lines
- Alex
Hi,
Quoted 2 lines · Michael Scott
Hello Alexander,
...
Quoted 6 lines
Quoted 5 lines
Question is for me: which upper layer wants access MAC header here on receive path?
It cannot parsed anyhow because so far I know no upper layer can parse at the moment 802.15.4 frames (which is a complex format). Maybe over someheader_opscallback?
Quoted 17 lines
I was testing a C program which performs NAT64 handling on packets destined to a certain IPv6 subnet (64:ff9b::). To do this, the application opens a RAW socket like this:
sniff_sock=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); It then sets promiscuous mode and enters a looping call of:
length =recv(sniff_sock, buffer, PACKET_BUFFER, MSG_TRUNC); My host PC kernel would then promptly crash on me. (I'm going to purposely avoid the obvious point of: this probably isn't the best way to parse packets for NAT64 translation as you will get every single packet incoming or outgoing on the host.) Turns out, testing the program on an 802.15.4 6lowpan interface exposed some of the issues which this mailing list (but not myself) is well aware of (no L2 data in the RAW packets) and also led me to debugging this patch to stop the kernel crash. TL;DR: To summarize, anyPF_PACKETSOCK_RAWsocket which recv()'s IPv6 data from a 6lowpan node will cause this kernel crash eventually (checked on kernel 4.15, 4.16, 4.17 and 4.18-rc1). - MikeQuoted 1 line
"any PF_PACKET SOCK_RAW" can't be otherwise I would also see it with my sniffer programs e.g. wireshark or tcpdump which use libpcap.
There need to be some different in the handling. This is what I have currently in my mind.
I currently not sure how to set skb->mac_header if interface is RAW_IP. It seems there is an indicator that mac header is not set. Example:
net/6lowpan/iphc.c +1 -0
@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, hdr.hop_limit, &hdr.daddr);skb_push (skb,sizeof (hdr)); + skb->mac_header = (typeof(skb->mac_header))~0U;skb_reset_network_header (skb);skb_copy_to_linear_data (skb, &hdr,sizeof (hdr));
Maybe we should lookup what skb->mac_header points to on tun interfaces then do the same.
- Alex
Hi,
Quoted 52 lines · Alexander Aring
Hi,
Quoted 2 lines · Michael Scott
Hello Alexander,
...
Quoted 6 lines
Quoted 5 lines
Question is for me: which upper layer wants access MAC header here on receive path?
It cannot parsed anyhow because so far I know no upper layer can parse at the moment 802.15.4 frames (which is a complex format). Maybe over someheader_opscallback?Quoted 17 lines
I was testing a C program which performs NAT64 handling on packets destined to a certain IPv6 subnet (64:ff9b::). To do this, the application opens a RAW socket like this:
sniff_sock=socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); It then sets promiscuous mode and enters a looping call of:
length =recv(sniff_sock, buffer, PACKET_BUFFER, MSG_TRUNC); My host PC kernel would then promptly crash on me. (I'm going to purposely avoid the obvious point of: this probably isn't the best way to parse packets for NAT64 translation as you will get every single packet incoming or outgoing on the host.) Turns out, testing the program on an 802.15.4 6lowpan interface exposed some of the issues which this mailing list (but not myself) is well aware of (no L2 data in the RAW packets) and also led me to debugging this patch to stop the kernel crash. TL;DR: To summarize, anyPF_PACKETSOCK_RAWsocket which recv()'s IPv6 data from a 6lowpan node will cause this kernel crash eventually (checked on kernel 4.15, 4.16, 4.17 and 4.18-rc1). - MikeQuoted 1 line
"any
PF_PACKETSOCK_RAW" can't be otherwise I would also see it with my sniffer programs e.g. wireshark or tcpdump which use libpcap.There need to be some different in the handling. This is what I have currently in my mind.
I currently not sure how to set
skb->mac_headerif interface isRAW_IP. It seems there is an indicator that mac header is not set. Example:net/6lowpan/iphc.c +1
-0@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, hdr.hop_limit, &hdr.daddr);skb_push (skb,sizeof (hdr)); + skb->mac_header = (typeof(skb->mac_header))~0U;skb_reset_network_header (skb);skb_copy_to_linear_data (skb, &hdr,sizeof (hdr));
Quoted 2 lines
Maybe we should lookup what
skb->mac_headerpoints to on tun interfaces then do the same.
So far I see [0] tun does the same as your patch approach does. network header and mac header points to the same.
I think then we should go with your patch.
Then we just need to solve the issue to get mac header information on top of lowpan socket layer... out of scope issue but indeed we need to solve that. As we talked there exists even UDP protocols which needs mac header information. It's in a pretty early state, I have no idea how this fits sometimes with fragmentation handling together. At least for L2 address handling and fragmentation it should be fine (one of the fragment indentifier).
- Alex
[0] https://elixir.bootlin.com/linux/v4.18-rc3/source/drivers/net/tun.c#L1912
Quoted 18 lines · Michael Scott
After decompression of 6lowpan socket data, an IPv6 header is inserted before the existing socket payload. After this, we reset the
network_headervalue of the skb to account for the difference in payload size from prior to decompression + the addition of the IPv6 header.However, we fail to reset the
mac_headervalue.Leaving the
mac_headervalue untouched here, can cause a calculation error innet/packet/af_packet.cpacket_rcv()function when anAF_PACKETsocket is opened inSOCK_RAWmode for use on a 6lowpan interface.On line 2088, the data pointer is moved backward by the value returned from
skb_mac_header(). Ifskb->datais adjusted so that it is before theskb->headpointer (which can happen when an old value ofmac_headeris left in place) the kernel generates a panic innet/core/skbuff.cline 1717.
Quoted 5 lines
This panic can be generated by BLE 6lowpan interfaces (such as bt0) and 802.15.4 interfaces (such as lowpan0) as they both use the same 6lowpan sources for compression and decompression.
Signed-off-by Michael Scott <[email protected]>
Thanks!
- Alex
Stefan Schmidt
maintainerHello Jukka.
Quoted 33 lines · Michael Scott
After decompression of 6lowpan socket data, an IPv6 header is inserted before the existing socket payload. After this, we reset the
network_headervalue of the skb to account for the difference in payload size from prior to decompression + the addition of the IPv6 header.However, we fail to reset the
mac_headervalue.Leaving the
mac_headervalue untouched here, can cause a calculation error innet/packet/af_packet.cpacket_rcv()function when anAF_PACKETsocket is opened inSOCK_RAWmode for use on a 6lowpan interface.On line 2088, the data pointer is moved backward by the value returned from
skb_mac_header(). Ifskb->datais adjusted so that it is before theskb->headpointer (which can happen when an old value ofmac_headeris left in place) the kernel generates a panic innet/core/skbuff.cline 1717.This panic can be generated by BLE 6lowpan interfaces (such as bt0) and 802.15.4 interfaces (such as lowpan0) as they both use the same 6lowpan sources for compression and decompression.
Signed-off-by Michael Scott <[email protected]>--- net/6lowpan/iphc.c | 1 + 1 file changed, 1 insertion(+)net/6lowpan/iphc.c +0
-0
net/6lowpan/iphc.c int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, · line 776
Quoted 7 lines
net/6lowpan/iphc.c +1
-0@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, hdr.hop_limit, &hdr.daddr);skb_push (skb,sizeof (hdr)); +skb_reset_mac_header (skb);skb_reset_network_header (skb);skb_copy_to_linear_data (skb, &hdr,sizeof (hdr));
Alex acked this patch for the ieee802154 side. Could you test it for the bluetooth 6lowpan side and ack or nack as well?
So far plain 6lowpan subsystem patches would still go through the bluetooth tree after Alex and you acked them. I guess Marcel or Johan just waiting for your review.
regards
Stefan Schmidt
Quoted 19 lines · Michael Scott
After decompression of 6lowpan socket data, an IPv6 header is inserted
before the existing socket payload. After this, we reset thenetwork_headervalue of the skb to account for the difference in payload
size from prior to decompression + the addition of the IPv6 header.Signed-off-by Michael Scott <[email protected]>--- net/6lowpan/iphc.c | 1 + 1 file changed, 1 insertion(+)net/6lowpan/iphc.c +0
-0
net/6lowpan/iphc.c int lowpan_header_decompress(struct sk_buff *skb, · line 776
Quoted 7 lines
net/6lowpan/iphc.c +1
-0@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb,const struct net_device *dev, hdr.hop_limit, &hdr.daddr);skb_push (skb,sizeof (hdr)); +skb_reset_mac_header (skb);skb_reset_network_header (skb);skb_copy_to_linear_data (skb, &hdr,sizeof (hdr));
Cheers,
Jukka
Hello.
Quoted 32 lines · Michael Scott
After decompression of 6lowpan socket data, an IPv6 header is inserted before the existing socket payload. After this, we reset the
network_headervalue of the skb to account for the difference in payload size from prior to decompression + the addition of the IPv6 header.However, we fail to reset the
mac_headervalue.Leaving the
mac_headervalue untouched here, can cause a calculation error innet/packet/af_packet.cpacket_rcv()function when anAF_PACKETsocket is opened inSOCK_RAWmode for use on a 6lowpan interface.On line 2088, the data pointer is moved backward by the value returned from
skb_mac_header(). Ifskb->datais adjusted so that it is before theskb->headpointer (which can happen when an old value ofmac_headeris left in place) the kernel generates a panic innet/core/skbuff.cline 1717.This panic can be generated by BLE 6lowpan interfaces (such as bt0) and 802.15.4 interfaces (such as lowpan0) as they both use the same 6lowpan sources for compression and decompression.
Signed-off-by Michael Scott <[email protected]>--- net/6lowpan/iphc.c | 1 + 1 file changed, 1 insertion(+)net/6lowpan/iphc.c +0
-0
net/6lowpan/iphc.c int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, · line 775
Quoted 6 lines
net/6lowpan/iphc.c +1
-0@@ -770,6 +770,7 @@ int lowpan_header_decompress(struct sk_buff *skb, const struct net_device *dev, hdr.hop_limit, &hdr.daddr);skb_push (skb,sizeof (hdr)); +skb_reset_mac_header (skb);skb_reset_network_header (skb);skb_copy_to_linear_data (skb, &hdr,sizeof (hdr));
This showed no problems in my ieee802154 + 6lowpan tests.
regards
Stefan Schmidt
Marcel Holtmann
maintainerHi Michael,
Quoted 18 lines
After decompression of 6lowpan socket data, an IPv6 header is inserted before the existing socket payload. After this, we reset the
network_headervalue of the skb to account for the difference in payload size from prior to decompression + the addition of the IPv6 header.However, we fail to reset the
mac_headervalue.Leaving the
mac_headervalue untouched here, can cause a calculation error innet/packet/af_packet.cpacket_rcv()function when anAF_PACKETsocket is opened inSOCK_RAWmode for use on a 6lowpan interface.On line 2088, the data pointer is moved backward by the value returned from
skb_mac_header(). Ifskb->datais adjusted so that it is before theskb->headpointer (which can happen when an old value ofmac_headeris left in place) the kernel generates a panic innet/core/skbuff.cline 1717.
Quoted 8 lines
This panic can be generated by BLE 6lowpan interfaces (such as bt0) and 802.15.4 interfaces (such as lowpan0) as they both use the same 6lowpan sources for compression and decompression.
Signed-off-by Michael Scott <[email protected]>---
net/6lowpan/iphc.c| 1 +1 file changed, 1 insertion(+)
patch has been applied to bluetooth-next tree.
Regards
Marcel