tcpip/link/fdbased: socket operation on non-socket
xjasonlyu opened this issue · comments
Description
Since commit e511fc9 removed the WritePacket
method from tcpip/link/fdbased package, this error may occur under some certain circumstances.
e.g. When we use tcpip/link/tun to open a TUN device:
fd, err := tun.Open(t.name)
if err != nil {
return nil, fmt.Errorf("create tun: %w", err)
}
Then pass the TUN fd as a fdbased.Option and add the endpoint to stack:
ep, err := fdbased.New(&fdbased.Options{
FDs: []int{fd},
...
})
The WritePackets
method would be called to write back packets:
gvisor/pkg/tcpip/link/fdbased/endpoint.go
Line 671 in e511fc9
Then the sendBatch
:
gvisor/pkg/tcpip/link/fdbased/endpoint.go
Line 689 in e511fc9
However, in the the sendBatch
, the else
would be hit and call the rawfile.NonBlockingSendMMsg(batchFD, mmsgHdrs)
:
gvisor/pkg/tcpip/link/fdbased/endpoint.go
Lines 637 to 657 in e511fc9
So the issue happens here, the SENDMMSG
syscall is used on a non-socket fd (TUN fd instead) and cause the socket operation on non-socket
error:
gvisor/pkg/tcpip/link/rawfile/rawfile_unsafe.go
Lines 135 to 142 in e511fc9
Steps to reproduce
Mentioned above.
runsc version
null
docker version (if using docker)
null
uname
null
kubectl (if using Kubernetes)
null
repo state (if built from source)
null
runsc debug logs (if available)
null
Thanks for the detailed report. I will take a look.
We just need to store that the underlying FD is not a socket and degrade WritePackets to writePacket always.
We do the socket check fdbased.New() but its not plumbed through to the write path. We should do that.