device: clear pointers when returning elems to pools

Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
Josh Bleecher Snyder 2020-12-04 15:36:21 -08:00
parent 01d3aaa7f4
commit d3ff2d6b62
3 changed files with 24 additions and 1 deletions

View file

@ -65,6 +65,7 @@ func (device *Device) GetInboundElement() *QueueInboundElement {
} }
func (device *Device) PutInboundElement(msg *QueueInboundElement) { func (device *Device) PutInboundElement(msg *QueueInboundElement) {
msg.clearPointers()
if PreallocatedBuffersPerPool == 0 { if PreallocatedBuffersPerPool == 0 {
device.pool.inboundElementPool.Put(msg) device.pool.inboundElementPool.Put(msg)
} else { } else {
@ -81,6 +82,7 @@ func (device *Device) GetOutboundElement() *QueueOutboundElement {
} }
func (device *Device) PutOutboundElement(msg *QueueOutboundElement) { func (device *Device) PutOutboundElement(msg *QueueOutboundElement) {
msg.clearPointers()
if PreallocatedBuffersPerPool == 0 { if PreallocatedBuffersPerPool == 0 {
device.pool.outboundElementPool.Put(msg) device.pool.outboundElementPool.Put(msg)
} else { } else {

View file

@ -37,6 +37,17 @@ type QueueInboundElement struct {
endpoint conn.Endpoint endpoint conn.Endpoint
} }
// clearPointers clears elem fields that contain pointers.
// This makes the garbage collector's life easier and
// avoids accidentally keeping other objects around unnecessarily.
// It also reduces the possible collateral damage from use-after-free bugs.
func (elem *QueueInboundElement) clearPointers() {
elem.buffer = nil
elem.packet = nil
elem.keypair = nil
elem.endpoint = nil
}
func (elem *QueueInboundElement) Drop() { func (elem *QueueInboundElement) Drop() {
atomic.StoreInt32(&elem.dropped, AtomicTrue) atomic.StoreInt32(&elem.dropped, AtomicTrue)
} }

View file

@ -58,9 +58,19 @@ func (device *Device) NewOutboundElement() *QueueOutboundElement {
elem.buffer = device.GetMessageBuffer() elem.buffer = device.GetMessageBuffer()
elem.Mutex = sync.Mutex{} elem.Mutex = sync.Mutex{}
elem.nonce = 0 elem.nonce = 0
// keypair and peer were cleared (if necessary) by clearPointers.
return elem
}
// clearPointers clears elem fields that contain pointers.
// This makes the garbage collector's life easier and
// avoids accidentally keeping other objects around unnecessarily.
// It also reduces the possible collateral damage from use-after-free bugs.
func (elem *QueueOutboundElement) clearPointers() {
elem.buffer = nil
elem.packet = nil
elem.keypair = nil elem.keypair = nil
elem.peer = nil elem.peer = nil
return elem
} }
func (elem *QueueOutboundElement) Drop() { func (elem *QueueOutboundElement) Drop() {