packet: in packet_snd start writing at link layer allocation
Subsystems (3)
Willem de Bruijn
maintainerPATCH 1/1 packet: in packet_snd start writing at link layer allocation
From: Willem de Bruijn <[email protected]>
Packet sockets allow construction of packets shorter than dev->hard_header_len to accommodate protocols with variable length link layer headers. These packets are padded to dev->hard_header_len, because some device drivers interpret that as a minimum packet size.
packet_snd reserves dev->hard_header_len bytes on allocation. SOCK_DGRAM sockets call skb_push in dev_hard_header() to ensure that link layer headers are stored in the reserved range. SOCK_RAW sockets do the same in tpacket_snd, but not in packet_snd.
Syzbot was able to send a zero byte packet to a device with massive 116B link layer header, causing padding to cross over into skb_shinfo. Fix this by writing from the start of the llheader reserved range also in the case of packet_snd/SOCK_RAW.
Update skb_set_network_header to the new offset. This also corrects it for SOCK_DGRAM, where it incorrectly double counted reserve due to the skb_push in dev_hard_header.
--- net/packet/af_packet.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/packet/af_packet.c +3 -1
@@ -2903,13 +2903,15 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)if (skb ==NULL ) goto out_unlock; -skb_set_network_header (skb, reserve); +skb_reset_network_header (skb); err = -EINVAL ;if (sock->type ==SOCK_DGRAM ) { offset =dev_hard_header (skb, dev,ntohs (proto), addr,NULL , len);if (unlikely (offset <0 )) goto out_free; + }else if (reserve) { +skb_push (skb, reserve); }/* Returns -EFAULT on error */
Signature · 1 line
2.17.0.441.gb46fe60e1d-goog
David Miller
maintainerFrom: Willem de Bruijn <[email protected]>
Date: Fri, 11 May 2018 13:24:25 -0400
Quoted 17 lines
From: Willem de Bruijn <[email protected]>
Packet sockets allow construction of packets shorter than
dev->hard_header_lento accommodate protocols with variable length link layer headers. These packets are padded todev->hard_header_len, because some device drivers interpret that as a minimum packet size.
packet_sndreservesdev->hard_header_lenbytes on allocation.SOCK_DGRAMsockets callskb_pushindev_hard_header()to ensure that link layer headers are stored in the reserved range.SOCK_RAWsockets do the same intpacket_snd, but not inpacket_snd.Syzbot was able to send a zero byte packet to a device with massive 116B link layer header, causing padding to cross over into
skb_shinfo. Fix this by writing from the start of the llheader reserved range also in the case of packet_snd/SOCK_RAW.
Quoted 7 lines
Update
skb_set_network_headerto the new offset. This also corrects it forSOCK_DGRAM, where it incorrectly double counted reserve due to theskb_pushindev_hard_header.Fixes 9ed988cd5915 ("packet: validate variable length ll headers")Reported-by [email protected]Signed-off-by Willem de Bruijn <[email protected]>
Applied and queued up for -stable, thanks Willem.
Quoted 24 lines · David Miller
From: Willem de Bruijn <[email protected]>
Date: Fri, 11 May 2018 13:24:25 -0400Quoted 21 lines
From: Willem de Bruijn <[email protected]>
Packet sockets allow construction of packets shorter than
dev->hard_header_lento accommodate protocols with variable length link layer headers. These packets are padded todev->hard_header_len, because some device drivers interpret that as a minimum packet size.
packet_sndreservesdev->hard_header_lenbytes on allocation.SOCK_DGRAMsockets callskb_pushindev_hard_header()to ensure that link layer headers are stored in the reserved range.SOCK_RAWsockets do the same intpacket_snd, but not inpacket_snd.Syzbot was able to send a zero byte packet to a device with massive 116B link layer header, causing padding to cross over into
skb_shinfo. Fix this by writing from the start of the llheader reserved range also in the case of packet_snd/SOCK_RAW.Update
skb_set_network_headerto the new offset. This also corrects it forSOCK_DGRAM, where it incorrectly double counted reserve due to theskb_pushindev_hard_header.
Quoted 6 lines
Quoted 3 lines
Fixes 9ed988cd5915 ("packet: validate variable length ll headers")Reported-by [email protected]Signed-off-by Willem de Bruijn <[email protected]>Applied and queued up for -stable, thanks Willem.
Hi,
One of our regression tests started failing. Once this patch is reverted, test passes.
The tests add flow steering rules in the receiver side and in the sender side it send the packet with some RAW socket applications. Then received side gets completion with error.
Our verification team compared the packets between the stable and the broken version, in the broken version we have some extra bytes at the end of the packet.
It looks like some bad push to the SKB, maybe the conditional reserved addition should be more strict?
Any idea?
Regards,
Tariq
Willem de Bruijn
maintainerQuoted 45 lines · Tariq Toukan
Quoted 25 lines · David Miller
From: Willem de Bruijn <[email protected]>
Date: Fri, 11 May 2018 13:24:25 -0400Quoted 21 lines
From: Willem de Bruijn <[email protected]>
Packet sockets allow construction of packets shorter than
dev->hard_header_lento accommodate protocols with variable length link layer headers. These packets are padded todev->hard_header_len, because some device drivers interpret that as a minimum packet size.
packet_sndreservesdev->hard_header_lenbytes on allocation.SOCK_DGRAMsockets callskb_pushindev_hard_header()to ensure that link layer headers are stored in the reserved range.SOCK_RAWsockets do the same intpacket_snd, but not inpacket_snd.Syzbot was able to send a zero byte packet to a device with massive 116B link layer header, causing padding to cross over into
skb_shinfo. Fix this by writing from the start of the llheader reserved range also in the case of packet_snd/SOCK_RAW.Update
skb_set_network_headerto the new offset. This also corrects it forSOCK_DGRAM, where it incorrectly double counted reserve due to theskb_pushindev_hard_header.Quoted 7 lines
Quoted 3 lines
Fixes 9ed988cd5915 ("packet: validate variable length ll headers")Reported-by [email protected]Signed-off-by Willem de Bruijn <[email protected]>Applied and queued up for -stable, thanks Willem.
Hi,
One of our regression tests started failing. Once this patch is reverted, test passes.
The tests add flow steering rules in the receiver side and in the sender side it send the packet with some RAW socket applications. Then received side gets completion with error.
Quoted 8 lines
Our verification team compared the packets between the stable and the broken version, in the broken version we have some extra bytes at the end of the packet.
It looks like some bad push to the SKB, maybe the conditional reserved addition should be more strict?
Any idea?
Thanks for reporting, sorry for the breakage.
I think I might. This skb_push moves back the start of skb->data in the same way that tpacket_snd does. But it does not reduce the length passed to skb_put, so this might double count hard_header_len.
Let me construct a test.
Willem de Bruijn
maintainerQuoted 55 lines · Willem de Bruijn
Quoted 45 lines · Tariq Toukan
Quoted 25 lines · David Miller
From: Willem de Bruijn <[email protected]>
Date: Fri, 11 May 2018 13:24:25 -0400Quoted 21 lines
From: Willem de Bruijn <[email protected]>
Packet sockets allow construction of packets shorter than
dev->hard_header_lento accommodate protocols with variable length link layer headers. These packets are padded todev->hard_header_len, because some device drivers interpret that as a minimum packet size.
packet_sndreservesdev->hard_header_lenbytes on allocation.SOCK_DGRAMsockets callskb_pushindev_hard_header()to ensure that link layer headers are stored in the reserved range.SOCK_RAWsockets do the same intpacket_snd, but not inpacket_snd.Syzbot was able to send a zero byte packet to a device with massive 116B link layer header, causing padding to cross over into
skb_shinfo. Fix this by writing from the start of the llheader reserved range also in the case of packet_snd/SOCK_RAW.Update
skb_set_network_headerto the new offset. This also corrects it forSOCK_DGRAM, where it incorrectly double counted reserve due to theskb_pushindev_hard_header.Quoted 7 lines
Quoted 3 lines
Fixes 9ed988cd5915 ("packet: validate variable length ll headers")Reported-by [email protected]Signed-off-by Willem de Bruijn <[email protected]>Applied and queued up for -stable, thanks Willem.
Hi,
One of our regression tests started failing. Once this patch is reverted, test passes.
The tests add flow steering rules in the receiver side and in the sender side it send the packet with some RAW socket applications. Then received side gets completion with error.
Quoted 8 lines
Our verification team compared the packets between the stable and the broken version, in the broken version we have some extra bytes at the end of the packet.
It looks like some bad push to the SKB, maybe the conditional reserved addition should be more strict?
Any idea?
Quoted 7 lines
Thanks for reporting, sorry for the breakage.
I think I might. This
skb_pushmoves back the start ofskb->datain the same way thattpacket_snddoes. But it does not reduce the length passed toskb_put, so this might double counthard_header_len.Let me construct a test.
Indeed.
Still verifying, but this almost certainly has to be
@@ -2911,7 +2912,7 @@ static int packet_snd(struct socket *sock,
struct msghdr *msg, size_t len)
if (unlikely(offset < 0))
goto out_free;
} else if (reserve) {
- skb_push(skb, reserve);
+ skb_reserve(skb, -reserve);
}to move the start of the packet without changing its length.
Willem de Bruijn
maintainerQuoted 71 lines · Willem de Bruijn
Quoted 55 lines · Willem de Bruijn
Quoted 45 lines · Tariq Toukan
Quoted 25 lines · David Miller
From: Willem de Bruijn <[email protected]>
Date: Fri, 11 May 2018 13:24:25 -0400Quoted 21 lines
From: Willem de Bruijn <[email protected]>
Packet sockets allow construction of packets shorter than
dev->hard_header_lento accommodate protocols with variable length link layer headers. These packets are padded todev->hard_header_len, because some device drivers interpret that as a minimum packet size.
packet_sndreservesdev->hard_header_lenbytes on allocation.SOCK_DGRAMsockets callskb_pushindev_hard_header()to ensure that link layer headers are stored in the reserved range.SOCK_RAWsockets do the same intpacket_snd, but not inpacket_snd.Syzbot was able to send a zero byte packet to a device with massive 116B link layer header, causing padding to cross over into
skb_shinfo. Fix this by writing from the start of the llheader reserved range also in the case of packet_snd/SOCK_RAW.Update
skb_set_network_headerto the new offset. This also corrects it forSOCK_DGRAM, where it incorrectly double counted reserve due to theskb_pushindev_hard_header.Quoted 7 lines
Quoted 3 lines
Fixes 9ed988cd5915 ("packet: validate variable length ll headers")Reported-by [email protected]Signed-off-by Willem de Bruijn <[email protected]>Applied and queued up for -stable, thanks Willem.
Hi,
One of our regression tests started failing. Once this patch is reverted, test passes.
The tests add flow steering rules in the receiver side and in the sender side it send the packet with some RAW socket applications. Then received side gets completion with error.
Quoted 8 lines
Our verification team compared the packets between the stable and the broken version, in the broken version we have some extra bytes at the end of the packet.
It looks like some bad push to the SKB, maybe the conditional reserved addition should be more strict?
Any idea?
Quoted 7 lines
Thanks for reporting, sorry for the breakage.
I think I might. This
skb_pushmoves back the start ofskb->datain the same way thattpacket_snddoes. But it does not reduce the length passed toskb_put, so this might double counthard_header_len.Let me construct a test.
Indeed.
Still verifying, but this almost certainly has to be
@@ -2911,7 +2912,7 @@ static int packet_snd(struct socket *sock,
struct msghdr *msg,size_tlen)
Quoted 8 lines
if (unlikely(offset < 0)) goto out_free; } else if (reserve) { - skb_push(skb, reserve); + skb_reserve(skb, -reserve); }to move the start of the packet without changing its length.
I sent http://patchwork.ozlabs.org/patch/920126/
Again, thanks a lot for reporting this, Tariq. I'm working on some packet socket boundary condition tests for tools/testing/selftests/net, so that I cannot push such a mistake again.