From 5c0a5ee4be909301cc355346ee7e5fe79458878f Mon Sep 17 00:00:00 2001 From: JackDoan Date: Mon, 27 Jul 2026 15:37:03 -0500 Subject: [PATCH] overlay/tio: guard Offload.Write against zero-length buffers Write took &buf[0] before calling writeWithScratch, so the len==0 guard in the helper could never run -- a zero-length buffer panicked on the index instead of returning. Hoist the guard above the indexing and fold writeWithScratch into Write since it was the only caller and duplicated the iovec setup. Co-Authored-By: Claude Fable 5 --- overlay/tio/tio_gso_linux.go | 14 ++++---------- overlay/tio/tun_linux_offload_test.go | 12 ++++++++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/overlay/tio/tio_gso_linux.go b/overlay/tio/tio_gso_linux.go index 37a2f9f2..64ca75e6 100644 --- a/overlay/tio/tio_gso_linux.go +++ b/overlay/tio/tio_gso_linux.go @@ -276,22 +276,16 @@ func (r *Offload) decodeRead(pktLen int) error { } func (r *Offload) Write(buf []byte) (int, error) { + if len(buf) == 0 { + return 0, nil + } iovs := [2]unix.Iovec{ {Base: &validVnetHdr[0]}, {Base: &buf[0]}, } iovs[0].SetLen(virtio.Size) iovs[1].SetLen(len(buf)) - return r.writeWithScratch(buf, &iovs) -} - -func (r *Offload) writeWithScratch(buf []byte, iovs *[2]unix.Iovec) (int, error) { - if len(buf) == 0 { - return 0, nil - } - iovs[1].Base = &buf[0] - iovs[1].SetLen(len(buf)) - return r.rawWrite(unsafe.Slice(&iovs[0], len(iovs))) + return r.rawWrite(unsafe.Slice(&iovs[0], 2)) } func (r *Offload) rawWrite(iovs []unix.Iovec) (int, error) { diff --git a/overlay/tio/tun_linux_offload_test.go b/overlay/tio/tun_linux_offload_test.go index d2b69fae..59d88cca 100644 --- a/overlay/tio/tun_linux_offload_test.go +++ b/overlay/tio/tun_linux_offload_test.go @@ -854,3 +854,15 @@ func TestDecodeReadFitsMaxTSOAtDrainThreshold(t *testing.T) { t.Fatalf("got %d segments, want %d", gotSegs, wantSegs) } } + +// TestOffloadWriteZeroLength: a zero-length Write must be a no-op, not a +// panic. The guard used to live below the &buf[0] that tripped on it. +func TestOffloadWriteZeroLength(t *testing.T) { + tf := &Offload{fd: -1} // any write reaching the fd would fail loudly + for _, buf := range [][]byte{nil, {}} { + n, err := tf.Write(buf) + if n != 0 || err != nil { + t.Errorf("Write(len=0) = (%d, %v), want (0, nil)", n, err) + } + } +}