Fix connection locking in firewall packet handler

This commit is contained in:
Daniel 2022-03-30 16:28:13 +02:00
parent 7d1f7a0d0f
commit ec09c8a948

View file

@ -580,10 +580,7 @@ func (conn *Connection) SetFirewallHandler(handler FirewallHandler) {
conn.pktQueue = make(chan packet.Packet, 1000) conn.pktQueue = make(chan packet.Packet, 1000)
// start handling // start handling
module.StartWorker("packet handler", func(ctx context.Context) error { module.StartWorker("packet handler", conn.packetHandlerWorker)
conn.packetHandler()
return nil
})
} }
conn.firewallHandler = handler conn.firewallHandler = handler
} }
@ -608,36 +605,47 @@ func (conn *Connection) HandlePacket(pkt packet.Packet) {
} }
} }
// packetHandler sequentially handles queued packets. // packetHandlerWorker sequentially handles queued packets.
func (conn *Connection) packetHandler() { func (conn *Connection) packetHandlerWorker(ctx context.Context) error {
for pkt := range conn.pktQueue { for {
select {
case pkt := <-conn.pktQueue:
if pkt == nil { if pkt == nil {
return return nil
} }
// get handler packetHandlerHandleConn(conn, pkt)
conn.Lock()
// execute handler or verdict case <-ctx.Done():
conn.Lock()
defer conn.Unlock()
conn.firewallHandler = nil
return nil
}
}
}
func packetHandlerHandleConn(conn *Connection, pkt packet.Packet) {
conn.Lock()
defer conn.Unlock()
// Handle packet with appropriate handler.
if conn.firewallHandler != nil { if conn.firewallHandler != nil {
conn.firewallHandler(conn, pkt) conn.firewallHandler(conn, pkt)
} else { } else {
defaultFirewallHandler(conn, pkt) defaultFirewallHandler(conn, pkt)
} }
// log verdict // Log verdict.
log.Tracer(pkt.Ctx()).Infof("filter: connection %s %s: %s", conn, conn.Verdict.Verb(), conn.Reason.Msg) log.Tracer(pkt.Ctx()).Infof("filter: connection %s %s: %s", conn, conn.Verdict.Verb(), conn.Reason.Msg)
// submit trace logs // Submit trace logs.
log.Tracer(pkt.Ctx()).Submit() log.Tracer(pkt.Ctx()).Submit()
// save does not touch any changing data // Save() itself does not touch any changing data.
// must not be locked, will deadlock with cleaner functions // Must not be locked - would deadlock with cleaner functions.
if conn.saveWhenFinished { if conn.saveWhenFinished {
conn.saveWhenFinished = false conn.saveWhenFinished = false
conn.Save() conn.Save()
} }
conn.Unlock()
}
} }
// GetActiveInspectors returns the list of active inspectors. // GetActiveInspectors returns the list of active inspectors.