Skip to content

x/net: invalid address when reading socket error queue with SO_TIMESTAMPING #47926

@mitinarseny

Description

@mitinarseny

What version of Go are you using (go version)?

$ go version
go version go1.16.6 linux/amd64

In my go.mod:

golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/mitinarseny/.cache/go-build"
GOENV="/home/mitinarseny/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/mitinarseny/dev/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/mitinarseny/dev/go"
GOPRIVATE=""
GOROOT="/usr/lib/go"
GOSUMDB="off"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/mitinarseny/dev/pingo/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2246281240=/tmp/go-build -gno-record-gcc-switches"

My Linux kernel is:

$ uname -a
Linux mitinarseny 5.13.8_1 #1 SMP Wed Aug 4 15:28:27 UTC 2021 x86_64 GNU/Linux

What did you do?

I am trying to implement socket timestamps in pingo.

Firstly, create socket with following:

s, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, unix.IPPROTO_ICMP)
if err != nil {
	return nil, os.NewSyscallError("socket", err)
}
if err := unix.SetsockoptInt(s, unix.IPPROTO_IP, unix.IP_RECVERR, 1); err != nil {
	unix.Close(s)
	return nil, os.NewSyscallError("setsockopt", err)
}
// TODO: this may be not supported
if err := unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_TIMESTAMPNS, 1); err != nil {
	unix.Close(s)
	return nil, os.NewSyscallError("setsockopt", err)
}
// TODO: unix.SOF_TIMESTAMPING_OPT_TSONLY
if err := unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_TIMESTAMPING,
	unix.SOF_TIMESTAMPING_RX_SOFTWARE|
	unix.SOF_TIMESTAMPING_TX_SOFTWARE|
	unix.SOF_TIMESTAMPING_OPT_CMSG|
	unix.SOF_TIMESTAMPING_OPT_ID|
	unix.SOF_TIMESTAMPING_TX_SCHED|
	unix.SOF_TIMESTAMPING_SOFTWARE); err != nil {
	unix.Close(s)
	return nil, os.NewSyscallError("setsockopt", err)
}
if err := unix.Bind(s, sockaddr(laddr)); err != nil {
	unix.Close(s)
	return nil, os.NewSyscallError("bind", err)
}
f := os.NewFile(uintptr(s), "datagram-oriented icmp")
c, err := net.FilePacketConn(f)
if cerr := f.Close(); cerr != nil {
	return nil, cerr
}
return c, err

Then, create ipv4.PacketConn:

c4 := ipv4.NewPacketConn(c)

Then I am trying to receive multiple messages with from socket's error queue:

n, err := p.c4.ReadBatch(ms, unix.MSG_ERRQUEUE|unix.MSG_DONTWAIT)

What did you expect to see?

Nil error

What did you see instead?

The error at this point is following:

read udp 0.0.0.0:59: invalid address

Which originates from here:
https://github.com/golang/net/blob/60bc85c4be6d32924bcfddb728394cb8713f2c78/internal/socket/rawconn_mmsg.go#L22-L24
https://github.com/golang/net/blob/60bc85c4be6d32924bcfddb728394cb8713f2c78/internal/socket/sys_posix.go#L67-L70

I guess, kernel does not put any address for transmit timestamp messages, so there should be nothing to parse. This leads to an error, which is created by errors.New, which is unable to detect with errors.Is from the perspective of caller.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      close