Do not hold BridgeEndpoint.mu during dispatcher.DeliverNetworkPacket().

When the dispatcher is a IP endpoint, DeliverNetworkPacket() goes on to acquire
Stack.mu. This change drop the lock ordering requirement of
tcpip/stack.BridgeEndpoint.mu->tcpip/stack.Stack.mu.

Reported-by: syzbot+726c3b022bc408edd74c@syzkaller.appspotmail.com
PiperOrigin-RevId: 645421096
This commit is contained in:
Ayush Ranjan
2024-06-21 10:01:58 -07:00
committed by gVisor bot
parent 0853a7491d
commit c4dc0321aa
+8 -10
View File
@@ -40,7 +40,6 @@ func (p *bridgePort) ParseHeader(pkt *PacketBuffer) bool {
func (p *bridgePort) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt *PacketBuffer) {
bridge := p.bridge
bridge.mu.Lock()
defer bridge.mu.Unlock()
// Send the packet to all other ports.
for _, port := range bridge.ports {
@@ -55,7 +54,14 @@ func (p *bridgePort) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber,
newPkt.DecRef()
}
bridge.injectInboundLocked(protocol, pkt)
d := bridge.dispatcher
bridge.mu.Unlock()
if d != nil {
// The dispatcher may acquire Stack.mu in DeliverNetworkPacket(), which is
// ordered above bridge.mu. So call DeliverNetworkPacket() without holding
// bridge.mu to avoid circular locking.
d.DeliverNetworkPacket(protocol, pkt)
}
}
func (p *bridgePort) DeliverLinkPacket(protocol tcpip.NetworkProtocolNumber, pkt *PacketBuffer) {
@@ -149,14 +155,6 @@ func (b *BridgeEndpoint) DelNIC(nic *nic) tcpip.Error {
return nil
}
// +checklocks:b.mu
func (b *BridgeEndpoint) injectInboundLocked(protocol tcpip.NetworkProtocolNumber, pkt *PacketBuffer) {
d := b.dispatcher
if d != nil {
d.DeliverNetworkPacket(protocol, pkt)
}
}
// MTU implements stack.LinkEndpoint.MTU.
func (b *BridgeEndpoint) MTU() uint32 {
if b.mtu > header.EthernetMinimumSize {