net/tstun: fix gvisor inbound GSO packet injection (#13283)

buffs[0] was not sized to hold pkt with GSO, resulting in a panic.

Updates tailscale/corp#22511

Signed-off-by: Jordan Whited <jordan@tailscale.com>
pull/13282/head
Jordan Whited 3 months ago committed by GitHub
parent a2c42d3cd4
commit 31cdbd68b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1258,8 +1258,8 @@ func (t *Wrapper) SetJailedFilter(filt *filter.Filter) {
// //
// pkt will be copied into buffs before writing to the underlying tun.Device. // pkt will be copied into buffs before writing to the underlying tun.Device.
// Therefore, callers must allocate and pass a buffs slice that is sized // Therefore, callers must allocate and pass a buffs slice that is sized
// appropriately for holding pkt.Size() + PacketStartOffset as either a single // appropriately for holding pkt.Size() + PacketStartOffset as a single
// element (buffs[0]), or split across multiple elements if the originating // element (buffs[0]) and split across multiple elements if the originating
// stack supports GSO. sizes must be sized with similar consideration, // stack supports GSO. sizes must be sized with similar consideration,
// len(buffs) should be equal to len(sizes). If any len(buffs[<index>]) was // len(buffs) should be equal to len(sizes). If any len(buffs[<index>]) was
// mutated by InjectInboundPacketBuffer it will be reset to cap(buffs[<index>]) // mutated by InjectInboundPacketBuffer it will be reset to cap(buffs[<index>])

@ -826,13 +826,18 @@ func (ns *Impl) DialContextUDP(ctx context.Context, ipp netip.AddrPort) (*gonet.
// across subsequent inbound packet injection calls. // across subsequent inbound packet injection calls.
func (ns *Impl) getInjectInboundBuffsSizes() (buffs [][]byte, sizes []int) { func (ns *Impl) getInjectInboundBuffsSizes() (buffs [][]byte, sizes []int) {
batchSize := 1 batchSize := 1
if ns.linkEP.SupportedGSO() == stack.HostGSOSupported { gsoEnabled := ns.linkEP.SupportedGSO() == stack.HostGSOSupported
if gsoEnabled {
batchSize = conn.IdealBatchSize batchSize = conn.IdealBatchSize
} }
buffs = make([][]byte, batchSize) buffs = make([][]byte, batchSize)
sizes = make([]int, batchSize) sizes = make([]int, batchSize)
for i := 0; i < batchSize; i++ { for i := 0; i < batchSize; i++ {
buffs[i] = make([]byte, tstun.PacketStartOffset+tstun.DefaultTUNMTU()) if i == 0 && gsoEnabled {
buffs[i] = make([]byte, tstun.PacketStartOffset+ns.linkEP.GSOMaxSize())
} else {
buffs[i] = make([]byte, tstun.PacketStartOffset+tstun.DefaultTUNMTU())
}
} }
return buffs, sizes return buffs, sizes
} }

Loading…
Cancel
Save