summaryrefslogtreecommitdiffhomepage
path: root/pkg
diff options
context:
space:
mode:
authorGhanan Gowripalan <ghanan@google.com>2021-09-09 17:07:37 -0700
committergVisor bot <gvisor-bot@google.com>2021-09-09 17:10:17 -0700
commit2572af38860ed8a5aa37f0ad705a360628a4ed10 (patch)
tree88f7ac7db4797b5d1437ed4cf9f0dc37bad57e70 /pkg
parent833d933afda03706328ac556d08294a78e372a6a (diff)
Remove linux-compat loopback hacks from packet endpoint
Previously, gVisor did not represent loopback devices as an ethernet device as Linux does. To maintain Linux API compatibility for packet sockets, a workaround was used to add an ethernet header if a link header was not already present in the packet buffer delivered to a packet endpoint. However, this workaround is a bug for non-ethernet based interfaces; not all links use an ethernet header (e.g. pure L3/TUN interfaces). As of 3b4bb947517d0d9010120aaa1c3989fd6abf278e, gVisor represents loopback devices as an ethernet-based device so this workaround can now be removed. BUG: https://fxbug.dev/81592 Updates #6530, #6531. PiperOrigin-RevId: 395819151
Diffstat (limited to 'pkg')
-rw-r--r--pkg/sentry/socket/socket.go2
-rw-r--r--pkg/tcpip/link/channel/channel.go23
-rw-r--r--pkg/tcpip/transport/packet/endpoint.go86
3 files changed, 46 insertions, 65 deletions
diff --git a/pkg/sentry/socket/socket.go b/pkg/sentry/socket/socket.go
index 83b9d9389..841d5bd55 100644
--- a/pkg/sentry/socket/socket.go
+++ b/pkg/sentry/socket/socket.go
@@ -743,6 +743,8 @@ func AddressAndFamily(addr []byte) (tcpip.FullAddress, uint16, *syserr.Error) {
return tcpip.FullAddress{}, family, syserr.ErrInvalidArgument
}
a.UnmarshalUnsafe(addr[:sockAddrLinkSize])
+ // TODO(https://gvisor.dev/issue/6530): Do not assume all interfaces have
+ // an ethernet address.
if a.Family != linux.AF_PACKET || a.HardwareAddrLen != header.EthernetAddressSize {
return tcpip.FullAddress{}, family, syserr.ErrInvalidArgument
}
diff --git a/pkg/tcpip/link/channel/channel.go b/pkg/tcpip/link/channel/channel.go
index d02eea93c..658557d62 100644
--- a/pkg/tcpip/link/channel/channel.go
+++ b/pkg/tcpip/link/channel/channel.go
@@ -28,7 +28,9 @@ import (
// PacketInfo holds all the information about an outbound packet.
type PacketInfo struct {
- Pkt *stack.PacketBuffer
+ Pkt *stack.PacketBuffer
+
+ // TODO(https://gvisor.dev/issue/6537): Remove these fields.
Proto tcpip.NetworkProtocolNumber
Route stack.RouteInfo
}
@@ -244,7 +246,10 @@ func (e *Endpoint) WritePacket(r stack.RouteInfo, protocol tcpip.NetworkProtocol
Route: r,
}
- e.q.Write(p)
+ // Write returns false if the queue is full. A full queue is not an error
+ // from the perspective of a LinkEndpoint so we ignore Write's return
+ // value and always return nil from this method.
+ _ = e.q.Write(p)
return nil
}
@@ -292,4 +297,16 @@ func (*Endpoint) AddHeader(tcpip.LinkAddress, tcpip.LinkAddress, tcpip.NetworkPr
}
// WriteRawPacket implements stack.LinkEndpoint.
-func (*Endpoint) WriteRawPacket(*stack.PacketBuffer) tcpip.Error { return &tcpip.ErrNotSupported{} }
+func (e *Endpoint) WriteRawPacket(pkt *stack.PacketBuffer) tcpip.Error {
+ p := PacketInfo{
+ Pkt: pkt,
+ Proto: pkt.NetworkProtocolNumber,
+ }
+
+ // Write returns false if the queue is full. A full queue is not an error
+ // from the perspective of a LinkEndpoint so we ignore Write's return
+ // value and always return nil from this method.
+ _ = e.q.Write(p)
+
+ return nil
+}
diff --git a/pkg/tcpip/transport/packet/endpoint.go b/pkg/tcpip/transport/packet/endpoint.go
index 89b4720aa..0554d2f4a 100644
--- a/pkg/tcpip/transport/packet/endpoint.go
+++ b/pkg/tcpip/transport/packet/endpoint.go
@@ -25,7 +25,6 @@
package packet
import (
- "fmt"
"io"
"time"
@@ -424,76 +423,39 @@ func (ep *endpoint) HandlePacket(nicID tcpip.NICID, localAddr tcpip.LinkAddress,
wasEmpty := ep.rcvBufSize == 0
- // Push new packet into receive list and increment the buffer size.
- var packet packet
+ rcvdPkt := packet{
+ packetInfo: tcpip.LinkPacketInfo{
+ Protocol: netProto,
+ PktType: pkt.PktType,
+ },
+ senderAddr: tcpip.FullAddress{
+ NIC: nicID,
+ },
+ receivedAt: ep.stack.Clock().Now(),
+ }
+
if !pkt.LinkHeader().View().IsEmpty() {
- // Get info directly from the ethernet header.
hdr := header.Ethernet(pkt.LinkHeader().View())
- packet.senderAddr = tcpip.FullAddress{
- NIC: nicID,
- Addr: tcpip.Address(hdr.SourceAddress()),
- }
- packet.packetInfo.Protocol = netProto
- packet.packetInfo.PktType = pkt.PktType
- } else {
- // Guess the would-be ethernet header.
- packet.senderAddr = tcpip.FullAddress{
- NIC: nicID,
- Addr: tcpip.Address(localAddr),
- }
- packet.packetInfo.Protocol = netProto
- packet.packetInfo.PktType = pkt.PktType
+ rcvdPkt.senderAddr.Addr = tcpip.Address(hdr.SourceAddress())
}
if ep.cooked {
- // Cooked packets can simply be queued.
- switch pkt.PktType {
- case tcpip.PacketHost:
- packet.data = pkt.Data().ExtractVV()
- case tcpip.PacketOutgoing:
- // Strip Link Header.
- var combinedVV buffer.VectorisedView
- if v := pkt.NetworkHeader().View(); !v.IsEmpty() {
- combinedVV.AppendView(v)
- }
- if v := pkt.TransportHeader().View(); !v.IsEmpty() {
- combinedVV.AppendView(v)
- }
- combinedVV.Append(pkt.Data().ExtractVV())
- packet.data = combinedVV
- default:
- panic(fmt.Sprintf("unexpected PktType in pkt: %+v", pkt))
+ // Cooked packet endpoints don't include the link-headers in received
+ // packets.
+ if v := pkt.NetworkHeader().View(); !v.IsEmpty() {
+ rcvdPkt.data.AppendView(v)
}
- } else {
- // Raw packets need their ethernet headers prepended before
- // queueing.
- var linkHeader buffer.View
- if pkt.PktType != tcpip.PacketOutgoing {
- if pkt.LinkHeader().View().IsEmpty() {
- // We weren't provided with an actual ethernet header,
- // so fake one.
- ethFields := header.EthernetFields{
- SrcAddr: tcpip.LinkAddress([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
- DstAddr: localAddr,
- Type: netProto,
- }
- fakeHeader := make(header.Ethernet, header.EthernetMinimumSize)
- fakeHeader.Encode(&ethFields)
- linkHeader = buffer.View(fakeHeader)
- } else {
- linkHeader = append(buffer.View(nil), pkt.LinkHeader().View()...)
- }
- combinedVV := linkHeader.ToVectorisedView()
- combinedVV.Append(pkt.Data().ExtractVV())
- packet.data = combinedVV
- } else {
- packet.data = buffer.NewVectorisedView(pkt.Size(), pkt.Views())
+ if v := pkt.TransportHeader().View(); !v.IsEmpty() {
+ rcvdPkt.data.AppendView(v)
}
+ rcvdPkt.data.Append(pkt.Data().ExtractVV())
+ } else {
+ // Raw packet endpoints include link-headers in received packets.
+ rcvdPkt.data = buffer.NewVectorisedView(pkt.Size(), pkt.Views())
}
- packet.receivedAt = ep.stack.Clock().Now()
- ep.rcvList.PushBack(&packet)
- ep.rcvBufSize += packet.data.Size()
+ ep.rcvList.PushBack(&rcvdPkt)
+ ep.rcvBufSize += rcvdPkt.data.Size()
ep.rcvMu.Unlock()
ep.stats.PacketsReceived.Increment()