Implement MappablePacketEndpoint for PACKET_MMAP and add tests.

PiperOrigin-RevId: 723590936
This commit is contained in:
Lucas Manning
2025-02-05 11:39:27 -08:00
committed by gVisor bot
parent e37e6814d3
commit 83a4caf2a7
7 changed files with 641 additions and 18 deletions
+2
View File
@@ -41,9 +41,11 @@ go_library(
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/ktime",
"//pkg/sentry/memmap",
"//pkg/sentry/socket",
"//pkg/sentry/socket/netfilter",
"//pkg/sentry/socket/netlink/nlmsg",
"//pkg/sentry/socket/netstack/packetmmap",
"//pkg/sentry/vfs",
"//pkg/sync",
"//pkg/syserr",
+55 -4
View File
@@ -51,9 +51,11 @@ import (
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/ktime"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/socket"
"gvisor.dev/gvisor/pkg/sentry/socket/netfilter"
epb "gvisor.dev/gvisor/pkg/sentry/socket/netstack/events_go_proto"
"gvisor.dev/gvisor/pkg/sentry/socket/netstack/packetmmap"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/syserr"
@@ -1868,10 +1870,7 @@ func SetSockOpt(t *kernel.Task, s socket.Socket, ep commonEndpoint, level int, n
return setSockOptIP(t, s, ep, name, optVal)
case linux.SOL_PACKET:
// gVisor doesn't support any SOL_PACKET options just return not
// supported. Returning nil here will result in tcpdump thinking AF_PACKET
// features are supported and proceed to use them and break.
return syserr.ErrProtocolNotAvailable
return setSockOptPacket(t, s, ep, name, optVal)
case linux.SOL_UDP,
linux.SOL_RAW:
@@ -2718,6 +2717,42 @@ func setSockOptIP(t *kernel.Task, s socket.Socket, ep commonEndpoint, name int,
return nil
}
func setSockOptPacket(t *kernel.Task, s socket.Socket, ep commonEndpoint, name int, optVal []byte) *syserr.Error {
switch name {
case linux.PACKET_RX_RING:
var tpacketReq linux.TpacketReq
tpacketReq.UnmarshalBytes(optVal)
req := tcpip.TpacketReq{
TpBlockSize: tpacketReq.TpBlockSize,
TpBlockNr: tpacketReq.TpBlockNr,
TpFrameSize: tpacketReq.TpFrameSize,
TpFrameNr: tpacketReq.TpFrameNr,
}
if err := ep.SetSockOpt(&req); err != nil {
return syserr.TranslateNetstackError(err)
}
if ep, ok := ep.(stack.MappablePacketEndpoint); ok {
var pme *packetmmap.Endpoint
if ep.GetPacketMMapEndpoint() != nil {
pme = ep.GetPacketMMapEndpoint().(*packetmmap.Endpoint)
if pme.Mapped() {
return syserr.ErrBusy
}
} else {
pme = &packetmmap.Endpoint{}
}
opts := ep.GetPacketMMapOpts(&req, true /* isRx */)
if err := pme.Init(t, opts); err != nil {
return syserr.FromError(err)
}
ep.SetPacketMMapEndpoint(pme)
} else {
return syserr.ErrNotSupported
}
}
return nil
}
// GetSockName implements the linux syscall getsockname(2) for sockets backed by
// tcpip.Endpoint.
func (s *sock) GetSockName(*kernel.Task) (linux.SockAddr, uint32, *syserr.Error) {
@@ -3543,3 +3578,19 @@ func (s *sock) EventRegister(e *waiter.Entry) error {
func (s *sock) EventUnregister(e *waiter.Entry) {
s.Queue.EventUnregister(e)
}
// ConfigureMMap implements vfs.FileDescriptionImpl.ConfigureMMap.
func (s *sock) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
if mappablePacketEP, ok := s.Endpoint.(stack.MappablePacketEndpoint); ok {
packetMMapEP := mappablePacketEP.GetPacketMMapEndpoint()
if packetMMapEP == nil {
return linuxerr.ENODEV
}
ep := packetMMapEP.(*packetmmap.Endpoint)
if err := vfs.GenericConfigureMMap(&s.vfsfd, ep, opts); err != nil {
return err
}
return ep.ConfigureMMap(ctx, opts)
}
return linuxerr.ENODEV
}