Go version
go version go1.24.3 linux/amd64
Output of go env
in your module/workspace:
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1142805223=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/workspaces/vxlan-cni/go.mod'
GOMODCACHE='/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/root/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.3'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
When reading ICMP messages via PacketConn.ReadFrom
, ICMP message data is silently dropped if the provided buffer is not large enough to contain both the ICMP header and the IP header. This is not documented anywhere, and the function is only supposed to load the buffer with ICMP message data, not any IP header data. Currently, to use this function properly, the buffer size must be maximum IP header size + maximum ICMP message size
. Even though this works around the issue, the additional space in the buffer is still completely wasted.
See https://github.com/solidDoWant/repro-go-bugs/blob/icmp-buffer-1/main.go for a step by step minimal reproduction and explanation. Just clone, go run .
, and review the output.
What did you see happen?
I wrote a short program to reproduce this issue. It creates a very basic ICMP message listener, and logs the buffer contents for ICMP echo requests. A pipe (|
) is inserted after the last byte reportedly returned by the ReadFrom
function. The program calls ping
via the exec
package to send ICMP echo requests to the loopback address.
All errors are checked, and the program will panic if one occurs.
$ go run .
IP datagram of 63 bytes, one under the buffer size.
This has a 20 byte IP header, 8 byte ICMP header, and 35 byte payload.
Received an ICMP echo request with 43 bytes (header + payload) from 127.0.0.1:
0000: 00 00 c5 4d 00 4c 00 01 dc 3e 6b 68 00 00 00 00
0010: e4 80 05 00 00 00 00 00 cd ef ab cd ef ab cd ef
0020: ab cd ef ab cd ef ab cd ef ab cd|00 cd ef ab cd
0030: ef ab cd ef ab cd ef ab cd ef ab cd ef ab cd 00
------------------------------------------------------------
IP datagram of 64 bytes, exactly the buffer size.
This has a 20 byte IP header, 8 byte ICMP header, and 36 byte payload.
Received an ICMP echo request with 44 bytes (header + payload) from 127.0.0.1:
0000: 00 00 95 59 00 4d 00 01 dc 3e 6b 68 00 00 00 00
0010: 13 85 05 00 00 00 00 00 cd ef ab cd ef ab cd ef
0020: ab cd ef ab cd ef ab cd ef ab cd ef|cd ef ab cd
0030: ef ab cd ef ab cd ef ab cd ef ab cd ef ab cd ef
------------------------------------------------------------
IP datagram of 65 bytes, one over the buffer size.
This has a 20 byte IP header, 8 byte ICMP header, and 37 byte payload.
Notice that the reported message size is 44 bytes, and an error is not reported (there is no panic).
Received an ICMP echo request with 44 bytes (header + payload) from 127.0.0.1:
0000: 00 00 9c 53 00 4e 00 01 dc 3e 6b 68 00 00 00 00
0010: 61 89 05 00 00 00 00 00 cd ef ab cd ef ab cd ef
0020: ab cd ef ab cd ef ab cd ef ab cd ef|cd ef ab cd
0030: ef ab cd ef ab cd ef ab cd ef ab cd ef ab cd ef
Notice that when the ICMP message is increased above the buffer size, the remaining bytes are silently dropped. A tcpdump
capture confirms that the ping
utility is sending messages exactly as expected.
What did you expect to see?
There are two issues here: * The buffer size must be larger than the ICMP message received. * When the buffer is not large enough to hold the ICMP message, there's no way to tell. No error is returned, and the IP datagram size is not provided.
I would expect that the buffer only needs to be as large as the received ICMP message, and that if it is not large enough, an error is returned.
Comment From: gabyhelp
Related Issues
- x/net/icmp: PacketConn.ReadFrom on an unprivileged PacketConn on darwin returns the entire IP packet #47369
- x/net/icmp: icmp ReadFrom cannot read any data on the Android and Linux system #59084 (closed)
- x/net/icmp: listen icmp in Windows not work properly #38427
- x/net/icmp: checksums are not checked when parsing a message #70340
- x/net/icmp: bind fails SOCK_DGRAM IPPROTO_ICMP #39891
- ipv6 header was stripped from the ip packets in packetConn read apis #40143 (closed)
- x/net/icmp: Malformed Interface Identification Object #28686 (closed)
- net: ListenPacket cannot receive packets from non-localhost #66662
- x/net/icmp: Hogs CPU on Windows, doesn't capture packets #33117
Related Discussions
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)