diff options
author | Kevin Krakauer <krakauer@google.com> | 2019-05-22 13:44:07 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-05-22 13:45:15 -0700 |
commit | c1cdf18e7bd21a9785462914ca8aa2056c81369a (patch) | |
tree | 2d53aca7fb685405940c49ac83f29743a5c96293 /pkg | |
parent | 69eac1198f3dae9a41ddf1903e9dda7972ed5d77 (diff) |
UDP and TCP raw socket support.
PiperOrigin-RevId: 249511348
Change-Id: I34539092cc85032d9473ff4dd308fc29dc9bfd6b
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/socket/epsocket/provider.go | 4 | ||||
-rw-r--r-- | pkg/tcpip/stack/nic.go | 8 | ||||
-rw-r--r-- | pkg/tcpip/stack/transport_demuxer.go | 36 | ||||
-rw-r--r-- | pkg/tcpip/transport/raw/endpoint.go | 2 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/BUILD | 1 | ||||
-rw-r--r-- | pkg/tcpip/transport/tcp/protocol.go | 3 | ||||
-rw-r--r-- | pkg/tcpip/transport/udp/BUILD | 2 | ||||
-rw-r--r-- | pkg/tcpip/transport/udp/endpoint.go | 2 | ||||
-rw-r--r-- | pkg/tcpip/transport/udp/protocol.go | 7 |
9 files changed, 48 insertions, 17 deletions
diff --git a/pkg/sentry/socket/epsocket/provider.go b/pkg/sentry/socket/epsocket/provider.go index 5a89a63fb..fb1815c2d 100644 --- a/pkg/sentry/socket/epsocket/provider.go +++ b/pkg/sentry/socket/epsocket/provider.go @@ -70,6 +70,10 @@ func getTransportProtocol(ctx context.Context, stype transport.SockType, protoco switch protocol { case syscall.IPPROTO_ICMP: return header.ICMPv4ProtocolNumber, nil + case syscall.IPPROTO_UDP: + return header.UDPProtocolNumber, nil + case syscall.IPPROTO_TCP: + return header.TCPProtocolNumber, nil } } return 0, syserr.ErrInvalidArgument diff --git a/pkg/tcpip/stack/nic.go b/pkg/tcpip/stack/nic.go index a4117d98e..50d35de88 100644 --- a/pkg/tcpip/stack/nic.go +++ b/pkg/tcpip/stack/nic.go @@ -593,6 +593,14 @@ func (n *NIC) DeliverTransportPacket(r *Route, protocol tcpip.TransportProtocolN } transProto := state.proto + + // Raw socket packets are delivered based solely on the transport + // protocol number. We do not inspect the payload to ensure it's + // validly formed. + if !n.demux.deliverRawPacket(r, protocol, netHeader, vv) { + n.stack.demux.deliverRawPacket(r, protocol, netHeader, vv) + } + if len(vv.First()) < transProto.MinimumPacketSize() { n.stack.stats.MalformedRcvdPackets.Increment() return diff --git a/pkg/tcpip/stack/transport_demuxer.go b/pkg/tcpip/stack/transport_demuxer.go index 807c3ba5e..605bfadeb 100644 --- a/pkg/tcpip/stack/transport_demuxer.go +++ b/pkg/tcpip/stack/transport_demuxer.go @@ -286,20 +286,10 @@ func (d *transportDemuxer) deliverPacket(r *Route, protocol tcpip.TransportProto destEps = append(destEps, ep) } - // As in net/ipv4/ip_input.c:ip_local_deliver, attempt to deliver via - // raw endpoint first. If there are multipe raw endpoints, they all - // receive the packet. - foundRaw := false - for _, rawEP := range eps.rawEndpoints { - // Each endpoint gets its own copy of the packet for the sake - // of save/restore. - rawEP.HandlePacket(r, buffer.NewViewFromBytes(netHeader), vv.ToView().ToVectorisedView()) - foundRaw = true - } eps.mu.RUnlock() // Fail if we didn't find at least one matching transport endpoint. - if len(destEps) == 0 && !foundRaw { + if len(destEps) == 0 { // UDP packet could not be delivered to an unknown destination port. if protocol == header.UDPProtocolNumber { r.Stats().UDP.UnknownPortErrors.Increment() @@ -315,6 +305,30 @@ func (d *transportDemuxer) deliverPacket(r *Route, protocol tcpip.TransportProto return true } +// deliverRawPacket attempts to deliver the given packet and returns whether it +// was delivered successfully. +func (d *transportDemuxer) deliverRawPacket(r *Route, protocol tcpip.TransportProtocolNumber, netHeader buffer.View, vv buffer.VectorisedView) bool { + eps, ok := d.protocol[protocolIDs{r.NetProto, protocol}] + if !ok { + return false + } + + // As in net/ipv4/ip_input.c:ip_local_deliver, attempt to deliver via + // raw endpoint first. If there are multiple raw endpoints, they all + // receive the packet. + foundRaw := false + eps.mu.RLock() + for _, rawEP := range eps.rawEndpoints { + // Each endpoint gets its own copy of the packet for the sake + // of save/restore. + rawEP.HandlePacket(r, buffer.NewViewFromBytes(netHeader), vv.ToView().ToVectorisedView()) + foundRaw = true + } + eps.mu.RUnlock() + + return foundRaw +} + // deliverControlPacket attempts to deliver the given control packet. Returns // true if it found an endpoint, false otherwise. func (d *transportDemuxer) deliverControlPacket(net tcpip.NetworkProtocolNumber, trans tcpip.TransportProtocolNumber, typ ControlType, extra uint32, vv buffer.VectorisedView, id TransportEndpointID) bool { diff --git a/pkg/tcpip/transport/raw/endpoint.go b/pkg/tcpip/transport/raw/endpoint.go index 1a16a3607..e7b383ad5 100644 --- a/pkg/tcpip/transport/raw/endpoint.go +++ b/pkg/tcpip/transport/raw/endpoint.go @@ -280,7 +280,7 @@ func (ep *endpoint) finishWrite(payload tcpip.Payload, route *stack.Route) (uint switch ep.netProto { case header.IPv4ProtocolNumber: hdr := buffer.NewPrependable(len(payloadBytes) + int(route.MaxHeaderLength())) - if err := route.WritePacket(nil /* gso */, hdr, buffer.View(payloadBytes).ToVectorisedView(), header.ICMPv4ProtocolNumber, route.DefaultTTL()); err != nil { + if err := route.WritePacket(nil /* gso */, hdr, buffer.View(payloadBytes).ToVectorisedView(), ep.transProto, route.DefaultTTL()); err != nil { return 0, nil, err } diff --git a/pkg/tcpip/transport/tcp/BUILD b/pkg/tcpip/transport/tcp/BUILD index d44d63e95..e31b03f7d 100644 --- a/pkg/tcpip/transport/tcp/BUILD +++ b/pkg/tcpip/transport/tcp/BUILD @@ -49,6 +49,7 @@ go_library( "//pkg/tcpip/header", "//pkg/tcpip/seqnum", "//pkg/tcpip/stack", + "//pkg/tcpip/transport/raw", "//pkg/tmutex", "//pkg/waiter", "@com_github_google_btree//:go_default_library", diff --git a/pkg/tcpip/transport/tcp/protocol.go b/pkg/tcpip/transport/tcp/protocol.go index b86473891..d31a1edcb 100644 --- a/pkg/tcpip/transport/tcp/protocol.go +++ b/pkg/tcpip/transport/tcp/protocol.go @@ -29,6 +29,7 @@ import ( "gvisor.googlesource.com/gvisor/pkg/tcpip/header" "gvisor.googlesource.com/gvisor/pkg/tcpip/seqnum" "gvisor.googlesource.com/gvisor/pkg/tcpip/stack" + "gvisor.googlesource.com/gvisor/pkg/tcpip/transport/raw" "gvisor.googlesource.com/gvisor/pkg/waiter" ) @@ -104,7 +105,7 @@ func (*protocol) NewEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolN // NewRawEndpoint creates a new raw TCP endpoint. Raw TCP sockets are currently // unsupported. It implements stack.TransportProtocol.NewRawEndpoint. func (p *protocol) NewRawEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { - return nil, tcpip.ErrUnknownProtocol + return raw.NewEndpoint(stack, netProto, header.TCPProtocolNumber, waiterQueue) } // MinimumPacketSize returns the minimum valid tcp packet size. diff --git a/pkg/tcpip/transport/udp/BUILD b/pkg/tcpip/transport/udp/BUILD index 361132a25..b9520d6e0 100644 --- a/pkg/tcpip/transport/udp/BUILD +++ b/pkg/tcpip/transport/udp/BUILD @@ -28,12 +28,12 @@ go_library( imports = ["gvisor.googlesource.com/gvisor/pkg/tcpip/buffer"], visibility = ["//visibility:public"], deps = [ - "//pkg/log", "//pkg/sleep", "//pkg/tcpip", "//pkg/tcpip/buffer", "//pkg/tcpip/header", "//pkg/tcpip/stack", + "//pkg/tcpip/transport/raw", "//pkg/waiter", ], ) diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go index 0ed0902b0..d9ca097c9 100644 --- a/pkg/tcpip/transport/udp/endpoint.go +++ b/pkg/tcpip/transport/udp/endpoint.go @@ -51,6 +51,8 @@ const ( // have concurrent goroutines make calls into the endpoint, they are properly // synchronized. // +// It implements tcpip.Endpoint. +// // +stateify savable type endpoint struct { // The following fields are initialized at creation time and do not diff --git a/pkg/tcpip/transport/udp/protocol.go b/pkg/tcpip/transport/udp/protocol.go index 8b47cce17..3d31dfbf1 100644 --- a/pkg/tcpip/transport/udp/protocol.go +++ b/pkg/tcpip/transport/udp/protocol.go @@ -25,6 +25,7 @@ import ( "gvisor.googlesource.com/gvisor/pkg/tcpip/buffer" "gvisor.googlesource.com/gvisor/pkg/tcpip/header" "gvisor.googlesource.com/gvisor/pkg/tcpip/stack" + "gvisor.googlesource.com/gvisor/pkg/tcpip/transport/raw" "gvisor.googlesource.com/gvisor/pkg/waiter" ) @@ -48,10 +49,10 @@ func (*protocol) NewEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolN return newEndpoint(stack, netProto, waiterQueue), nil } -// NewRawEndpoint creates a new raw UDP endpoint. Raw UDP sockets are currently -// unsupported. It implements stack.TransportProtocol.NewRawEndpoint. +// NewRawEndpoint creates a new raw UDP endpoint. It implements +// stack.TransportProtocol.NewRawEndpoint. func (p *protocol) NewRawEndpoint(stack *stack.Stack, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) { - return nil, tcpip.ErrUnknownProtocol + return raw.NewEndpoint(stack, netProto, header.UDPProtocolNumber, waiterQueue) } // MinimumPacketSize returns the minimum valid udp packet size. |