From bb1ae811f4eb3ba59ab8e64672f06a83bc17fd4c Mon Sep 17 00:00:00 2001 From: Lucas Manning Date: Wed, 10 Nov 2021 14:09:13 -0800 Subject: [PATCH] Prevent PacketBuffers from being returned to the pool too early in nic. PacketBuffers were calling DecRef inside the forEach callback in deliverOutboundPacket and DeliverNetworkPacket, even though they were referenced in future iterations of the loop. This caused a data race. Reported-by: syzbot+10c56102ab3d68689806@syzkaller.appspotmail.com PiperOrigin-RevId: 408972907 --- pkg/tcpip/stack/nic.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go index 7cfb836ca..a79d8d07d 100644 --- a/pkg/tcpip/stack/nic.go +++ b/pkg/tcpip/stack/nic.go @@ -740,6 +740,11 @@ func (n *nic) DeliverNetworkPacket(remote, local tcpip.LinkAddress, protocol tcp // Deliver to interested packet endpoints without holding NIC lock. var packetEPPkt *PacketBuffer + defer func() { + if packetEPPkt != nil { + packetEPPkt.DecRef() + } + }() deliverPacketEPs := func(ep PacketEndpoint) { if packetEPPkt == nil { // Packet endpoints hold the full packet. @@ -754,7 +759,6 @@ func (n *nic) DeliverNetworkPacket(remote, local tcpip.LinkAddress, protocol tcp packetEPPkt = NewPacketBuffer(PacketBufferOptions{ Data: PayloadSince(pkt.LinkHeader()).ToVectorisedView(), }) - defer packetEPPkt.DecRef() // If a link header was populated in the original packet buffer, then // populate it in the packet buffer we provide to packet endpoints as // packet endpoints inspect link headers. @@ -799,6 +803,11 @@ func (n *nic) deliverOutboundPacket(remote tcpip.LinkAddress, pkt *PacketBuffer) local := n.LinkAddress() var packetEPPkt *PacketBuffer + defer func() { + if packetEPPkt != nil { + packetEPPkt.DecRef() + } + }() eps.forEach(func(ep PacketEndpoint) { if packetEPPkt == nil { // Packet endpoints hold the full packet. @@ -814,7 +823,6 @@ func (n *nic) deliverOutboundPacket(remote tcpip.LinkAddress, pkt *PacketBuffer) ReserveHeaderBytes: pkt.AvailableHeaderBytes(), Data: PayloadSince(pkt.NetworkHeader()).ToVectorisedView(), }) - defer packetEPPkt.DecRef() // Add the link layer header as outgoing packets are intercepted before // the link layer header is created and packet endpoints are interested // in the link header.