mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Merge pull request #2130 from nybidari:iptables
PiperOrigin-RevId: 303208407
This commit is contained in:
@@ -509,3 +509,44 @@ const (
|
||||
// Enable all flags.
|
||||
XT_UDP_INV_MASK = 0x03
|
||||
)
|
||||
|
||||
// IPTOwnerInfo holds data for matching packets with owner. It corresponds
|
||||
// to struct ipt_owner_info in libxt_owner.c of iptables binary.
|
||||
type IPTOwnerInfo struct {
|
||||
// UID is user id which created the packet.
|
||||
UID uint32
|
||||
|
||||
// GID is group id which created the packet.
|
||||
GID uint32
|
||||
|
||||
// PID is process id of the process which created the packet.
|
||||
PID uint32
|
||||
|
||||
// SID is session id which created the packet.
|
||||
SID uint32
|
||||
|
||||
// Comm is the command name which created the packet.
|
||||
Comm [16]byte
|
||||
|
||||
// Match is used to match UID/GID of the socket. See the
|
||||
// XT_OWNER_* flags below.
|
||||
Match uint8
|
||||
|
||||
// Invert flips the meaning of Match field.
|
||||
Invert uint8
|
||||
}
|
||||
|
||||
// SizeOfIPTOwnerInfo is the size of an XTOwnerMatchInfo.
|
||||
const SizeOfIPTOwnerInfo = 34
|
||||
|
||||
// Flags in IPTOwnerInfo.Match. Corresponding constants are in
|
||||
// include/uapi/linux/netfilter/xt_owner.h.
|
||||
const (
|
||||
// Match the UID of the packet.
|
||||
XT_OWNER_UID = 1 << 0
|
||||
// Match the GID of the packet.
|
||||
XT_OWNER_GID = 1 << 1
|
||||
// Match if the socket exists for the packet. Forwarded
|
||||
// packets do not have an associated socket.
|
||||
XT_OWNER_SOCKET = 1 << 2
|
||||
)
|
||||
|
||||
@@ -29,6 +29,7 @@ func TestSizes(t *testing.T) {
|
||||
{IPTGetEntries{}, SizeOfIPTGetEntries},
|
||||
{IPTGetinfo{}, SizeOfIPTGetinfo},
|
||||
{IPTIP{}, SizeOfIPTIP},
|
||||
{IPTOwnerInfo{}, SizeOfIPTOwnerInfo},
|
||||
{IPTReplace{}, SizeOfIPTReplace},
|
||||
{XTCounters{}, SizeOfXTCounters},
|
||||
{XTEntryMatch{}, SizeOfXTEntryMatch},
|
||||
|
||||
@@ -863,3 +863,15 @@ func (t *Task) SetOOMScoreAdj(adj int32) error {
|
||||
atomic.StoreInt32(&t.tg.oomScoreAdj, adj)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UID returns t's uid.
|
||||
// TODO(gvisor.dev/issue/170): This method is not namespaced yet.
|
||||
func (t *Task) UID() uint32 {
|
||||
return uint32(t.Credentials().EffectiveKUID)
|
||||
}
|
||||
|
||||
// GID returns t's gid.
|
||||
// TODO(gvisor.dev/issue/170): This method is not namespaced yet.
|
||||
func (t *Task) GID() uint32 {
|
||||
return uint32(t.Credentials().EffectiveKGID)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ go_library(
|
||||
srcs = [
|
||||
"extensions.go",
|
||||
"netfilter.go",
|
||||
"owner_matcher.go",
|
||||
"targets.go",
|
||||
"tcp_matcher.go",
|
||||
"udp_matcher.go",
|
||||
|
||||
@@ -517,11 +517,10 @@ func SetEntries(stk *stack.Stack, optVal []byte) *syserr.Error {
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/170): Support other chains.
|
||||
// Since we only support modifying the INPUT chain and redirect for
|
||||
// PREROUTING chain right now, make sure all other chains point to
|
||||
// ACCEPT rules.
|
||||
// Since we only support modifying the INPUT, PREROUTING and OUTPUT chain right now,
|
||||
// make sure all other chains point to ACCEPT rules.
|
||||
for hook, ruleIdx := range table.BuiltinChains {
|
||||
if hook != stack.Input && hook != stack.Prerouting {
|
||||
if hook == stack.Forward || hook == stack.Postrouting {
|
||||
if _, ok := table.Rules[ruleIdx].Target.(stack.AcceptTarget); !ok {
|
||||
nflog("hook %d is unsupported.", hook)
|
||||
return syserr.ErrInvalidArgument
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package netfilter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/binary"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
const matcherNameOwner = "owner"
|
||||
|
||||
func init() {
|
||||
registerMatchMaker(ownerMarshaler{})
|
||||
}
|
||||
|
||||
// ownerMarshaler implements matchMaker for owner matching.
|
||||
type ownerMarshaler struct{}
|
||||
|
||||
// name implements matchMaker.name.
|
||||
func (ownerMarshaler) name() string {
|
||||
return matcherNameOwner
|
||||
}
|
||||
|
||||
// marshal implements matchMaker.marshal.
|
||||
func (ownerMarshaler) marshal(mr stack.Matcher) []byte {
|
||||
matcher := mr.(*OwnerMatcher)
|
||||
iptOwnerInfo := linux.IPTOwnerInfo{
|
||||
UID: matcher.uid,
|
||||
GID: matcher.gid,
|
||||
}
|
||||
|
||||
// Support for UID match.
|
||||
// TODO(gvisor.dev/issue/170): Need to support gid match.
|
||||
if matcher.matchUID {
|
||||
iptOwnerInfo.Match = linux.XT_OWNER_UID
|
||||
} else if matcher.matchGID {
|
||||
panic("GID match is not supported.")
|
||||
} else {
|
||||
panic("UID match is not set.")
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, linux.SizeOfIPTOwnerInfo)
|
||||
return marshalEntryMatch(matcherNameOwner, binary.Marshal(buf, usermem.ByteOrder, iptOwnerInfo))
|
||||
}
|
||||
|
||||
// unmarshal implements matchMaker.unmarshal.
|
||||
func (ownerMarshaler) unmarshal(buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
|
||||
if len(buf) < linux.SizeOfIPTOwnerInfo {
|
||||
return nil, fmt.Errorf("buf has insufficient size for owner match: %d", len(buf))
|
||||
}
|
||||
|
||||
// For alignment reasons, the match's total size may
|
||||
// exceed what's strictly necessary to hold matchData.
|
||||
var matchData linux.IPTOwnerInfo
|
||||
binary.Unmarshal(buf[:linux.SizeOfIPTOwnerInfo], usermem.ByteOrder, &matchData)
|
||||
nflog("parseMatchers: parsed IPTOwnerInfo: %+v", matchData)
|
||||
|
||||
if matchData.Invert != 0 {
|
||||
return nil, fmt.Errorf("invert flag is not supported for owner match")
|
||||
}
|
||||
|
||||
// Support for UID match.
|
||||
// TODO(gvisor.dev/issue/170): Need to support gid match.
|
||||
if matchData.Match&linux.XT_OWNER_UID != linux.XT_OWNER_UID {
|
||||
return nil, fmt.Errorf("owner match is only supported for uid")
|
||||
}
|
||||
|
||||
// Check Flags.
|
||||
var owner OwnerMatcher
|
||||
owner.uid = matchData.UID
|
||||
owner.gid = matchData.GID
|
||||
owner.matchUID = true
|
||||
|
||||
return &owner, nil
|
||||
}
|
||||
|
||||
type OwnerMatcher struct {
|
||||
uid uint32
|
||||
gid uint32
|
||||
matchUID bool
|
||||
matchGID bool
|
||||
invert uint8
|
||||
}
|
||||
|
||||
// Name implements Matcher.Name.
|
||||
func (*OwnerMatcher) Name() string {
|
||||
return matcherNameOwner
|
||||
}
|
||||
|
||||
// Match implements Matcher.Match.
|
||||
func (om *OwnerMatcher) Match(hook stack.Hook, pkt stack.PacketBuffer, interfaceName string) (bool, bool) {
|
||||
// Support only for OUTPUT chain.
|
||||
// TODO(gvisor.dev/issue/170): Need to support for POSTROUTING chain also.
|
||||
if hook != stack.Output {
|
||||
return false, true
|
||||
}
|
||||
|
||||
// If the packet owner is not set, drop the packet.
|
||||
// Support for uid match.
|
||||
// TODO(gvisor.dev/issue/170): Need to support gid match.
|
||||
if pkt.Owner == nil || !om.matchUID {
|
||||
return false, true
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/170): Need to add tests to verify
|
||||
// drop rule when packet UID does not match owner matcher UID.
|
||||
if pkt.Owner.UID() != om.uid {
|
||||
return false, false
|
||||
}
|
||||
|
||||
return true, false
|
||||
}
|
||||
@@ -126,6 +126,12 @@ func (p *provider) Socket(t *kernel.Task, stype linux.SockType, protocol int) (*
|
||||
ep, e = eps.Stack.NewRawEndpoint(transProto, p.netProto, wq, associated)
|
||||
} else {
|
||||
ep, e = eps.Stack.NewEndpoint(transProto, p.netProto, wq)
|
||||
|
||||
// Assign task to PacketOwner interface to get the UID and GID for
|
||||
// iptables owner matching.
|
||||
if e == nil {
|
||||
ep.SetOwner(t)
|
||||
}
|
||||
}
|
||||
if e != nil {
|
||||
return nil, syserr.TranslateNetstackError(e)
|
||||
|
||||
@@ -244,6 +244,14 @@ func (e *endpoint) WritePacket(r *stack.Route, gso *stack.GSO, params stack.Netw
|
||||
ip := e.addIPHeader(r, &pkt.Header, pkt.Data.Size(), params)
|
||||
pkt.NetworkHeader = buffer.View(ip)
|
||||
|
||||
// iptables filtering. All packets that reach here are locally
|
||||
// generated.
|
||||
ipt := e.stack.IPTables()
|
||||
if ok := ipt.Check(stack.Output, pkt); !ok {
|
||||
// iptables is telling us to drop the packet.
|
||||
return nil
|
||||
}
|
||||
|
||||
if r.Loop&stack.PacketLoop != 0 {
|
||||
// The inbound path expects the network header to still be in
|
||||
// the PacketBuffer's Data field.
|
||||
@@ -280,7 +288,14 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts []stack.Pac
|
||||
return len(pkts), nil
|
||||
}
|
||||
|
||||
// iptables filtering. All packets that reach here are locally
|
||||
// generated.
|
||||
ipt := e.stack.IPTables()
|
||||
for i := range pkts {
|
||||
if ok := ipt.Check(stack.Output, pkts[i]); !ok {
|
||||
// iptables is telling us to drop the packet.
|
||||
continue
|
||||
}
|
||||
ip := e.addIPHeader(r, &pkts[i].Header, pkts[i].DataSize, params)
|
||||
pkts[i].NetworkHeader = buffer.View(ip)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
|
||||
package stack
|
||||
|
||||
import "gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/buffer"
|
||||
)
|
||||
|
||||
// A PacketBuffer contains all the data of a network packet.
|
||||
//
|
||||
@@ -59,6 +62,10 @@ type PacketBuffer struct {
|
||||
// Hash is the transport layer hash of this packet. A value of zero
|
||||
// indicates no valid hash has been set.
|
||||
Hash uint32
|
||||
|
||||
// Owner is implemented by task to get the uid and gid.
|
||||
// Only set for locally generated packets.
|
||||
Owner tcpip.PacketOwner
|
||||
}
|
||||
|
||||
// Clone makes a copy of pk. It clones the Data field, which creates a new
|
||||
|
||||
@@ -56,6 +56,8 @@ func (f *fakeTransportEndpoint) Stats() tcpip.EndpointStats {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeTransportEndpoint) SetOwner(owner tcpip.PacketOwner) {}
|
||||
|
||||
func newFakeTransportEndpoint(s *stack.Stack, proto *fakeTransportProtocol, netProto tcpip.NetworkProtocolNumber, uniqueID uint64) tcpip.Endpoint {
|
||||
return &fakeTransportEndpoint{stack: s, TransportEndpointInfo: stack.TransportEndpointInfo{NetProto: netProto}, proto: proto, uniqueID: uniqueID}
|
||||
}
|
||||
|
||||
@@ -336,6 +336,15 @@ type ControlMessages struct {
|
||||
PacketInfo IPPacketInfo
|
||||
}
|
||||
|
||||
// PacketOwner is used to get UID and GID of the packet.
|
||||
type PacketOwner interface {
|
||||
// UID returns UID of the packet.
|
||||
UID() uint32
|
||||
|
||||
// GID returns GID of the packet.
|
||||
GID() uint32
|
||||
}
|
||||
|
||||
// Endpoint is the interface implemented by transport protocols (e.g., tcp, udp)
|
||||
// that exposes functionality like read, write, connect, etc. to users of the
|
||||
// networking stack.
|
||||
@@ -470,6 +479,9 @@ type Endpoint interface {
|
||||
|
||||
// Stats returns a reference to the endpoint stats.
|
||||
Stats() EndpointStats
|
||||
|
||||
// SetOwner sets the task owner to the endpoint owner.
|
||||
SetOwner(owner PacketOwner)
|
||||
}
|
||||
|
||||
// EndpointInfo is the interface implemented by each endpoint info struct.
|
||||
|
||||
@@ -73,6 +73,9 @@ type endpoint struct {
|
||||
route stack.Route `state:"manual"`
|
||||
ttl uint8
|
||||
stats tcpip.TransportEndpointStats `state:"nosave"`
|
||||
|
||||
// owner is used to get uid and gid of the packet.
|
||||
owner tcpip.PacketOwner
|
||||
}
|
||||
|
||||
func newEndpoint(s *stack.Stack, netProto tcpip.NetworkProtocolNumber, transProto tcpip.TransportProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) {
|
||||
@@ -133,6 +136,10 @@ func (e *endpoint) Close() {
|
||||
// ModerateRecvBuf implements tcpip.Endpoint.ModerateRecvBuf.
|
||||
func (e *endpoint) ModerateRecvBuf(copied int) {}
|
||||
|
||||
func (e *endpoint) SetOwner(owner tcpip.PacketOwner) {
|
||||
e.owner = owner
|
||||
}
|
||||
|
||||
// IPTables implements tcpip.Endpoint.IPTables.
|
||||
func (e *endpoint) IPTables() (stack.IPTables, error) {
|
||||
return e.stack.IPTables(), nil
|
||||
@@ -321,7 +328,7 @@ func (e *endpoint) write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, <-c
|
||||
|
||||
switch e.NetProto {
|
||||
case header.IPv4ProtocolNumber:
|
||||
err = send4(route, e.ID.LocalPort, v, e.ttl)
|
||||
err = send4(route, e.ID.LocalPort, v, e.ttl, e.owner)
|
||||
|
||||
case header.IPv6ProtocolNumber:
|
||||
err = send6(route, e.ID.LocalPort, v, e.ttl)
|
||||
@@ -415,7 +422,7 @@ func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||
}
|
||||
}
|
||||
|
||||
func send4(r *stack.Route, ident uint16, data buffer.View, ttl uint8) *tcpip.Error {
|
||||
func send4(r *stack.Route, ident uint16, data buffer.View, ttl uint8, owner tcpip.PacketOwner) *tcpip.Error {
|
||||
if len(data) < header.ICMPv4MinimumSize {
|
||||
return tcpip.ErrInvalidEndpointState
|
||||
}
|
||||
@@ -444,6 +451,7 @@ func send4(r *stack.Route, ident uint16, data buffer.View, ttl uint8) *tcpip.Err
|
||||
Header: hdr,
|
||||
Data: data.ToVectorisedView(),
|
||||
TransportHeader: buffer.View(icmpv4),
|
||||
Owner: owner,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -392,3 +392,5 @@ func (ep *endpoint) Info() tcpip.EndpointInfo {
|
||||
func (ep *endpoint) Stats() tcpip.EndpointStats {
|
||||
return &ep.stats
|
||||
}
|
||||
|
||||
func (ep *endpoint) SetOwner(owner tcpip.PacketOwner) {}
|
||||
|
||||
@@ -80,6 +80,9 @@ type endpoint struct {
|
||||
// Connect(), and is valid only when conneted is true.
|
||||
route stack.Route `state:"manual"`
|
||||
stats tcpip.TransportEndpointStats `state:"nosave"`
|
||||
|
||||
// owner is used to get uid and gid of the packet.
|
||||
owner tcpip.PacketOwner
|
||||
}
|
||||
|
||||
// NewEndpoint returns a raw endpoint for the given protocols.
|
||||
@@ -159,6 +162,10 @@ func (e *endpoint) Close() {
|
||||
// ModerateRecvBuf implements tcpip.Endpoint.ModerateRecvBuf.
|
||||
func (e *endpoint) ModerateRecvBuf(copied int) {}
|
||||
|
||||
func (e *endpoint) SetOwner(owner tcpip.PacketOwner) {
|
||||
e.owner = owner
|
||||
}
|
||||
|
||||
// IPTables implements tcpip.Endpoint.IPTables.
|
||||
func (e *endpoint) IPTables() (stack.IPTables, error) {
|
||||
return e.stack.IPTables(), nil
|
||||
@@ -348,10 +355,12 @@ func (e *endpoint) finishWrite(payloadBytes []byte, route *stack.Route) (int64,
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
hdr := buffer.NewPrependable(len(payloadBytes) + int(route.MaxHeaderLength()))
|
||||
if err := route.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: e.TransProto, TTL: route.DefaultTTL(), TOS: stack.DefaultTOS}, stack.PacketBuffer{
|
||||
Header: hdr,
|
||||
Data: buffer.View(payloadBytes).ToVectorisedView(),
|
||||
Owner: e.owner,
|
||||
}); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ func (l *listenContext) createConnectingEndpoint(s *segment, iss seqnum.Value, i
|
||||
// and then performs the TCP 3-way handshake.
|
||||
//
|
||||
// The new endpoint is returned with e.mu held.
|
||||
func (l *listenContext) createEndpointAndPerformHandshake(s *segment, opts *header.TCPSynOptions, queue *waiter.Queue) (*endpoint, *tcpip.Error) {
|
||||
func (l *listenContext) createEndpointAndPerformHandshake(s *segment, opts *header.TCPSynOptions, queue *waiter.Queue, owner tcpip.PacketOwner) (*endpoint, *tcpip.Error) {
|
||||
// Create new endpoint.
|
||||
irs := s.sequenceNumber
|
||||
isn := generateSecureISN(s.id, l.stack.Seed())
|
||||
@@ -284,6 +284,7 @@ func (l *listenContext) createEndpointAndPerformHandshake(s *segment, opts *head
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ep.owner = owner
|
||||
|
||||
// listenEP is nil when listenContext is used by tcp.Forwarder.
|
||||
deferAccept := time.Duration(0)
|
||||
@@ -414,7 +415,7 @@ func (e *endpoint) handleSynSegment(ctx *listenContext, s *segment, opts *header
|
||||
}()
|
||||
defer s.decRef()
|
||||
|
||||
n, err := ctx.createEndpointAndPerformHandshake(s, opts, &waiter.Queue{})
|
||||
n, err := ctx.createEndpointAndPerformHandshake(s, opts, &waiter.Queue{}, e.owner)
|
||||
if err != nil {
|
||||
e.stack.Stats().TCP.FailedConnectionAttempts.Increment()
|
||||
e.stats.FailedConnectionAttempts.Increment()
|
||||
|
||||
@@ -745,7 +745,7 @@ func (e *endpoint) sendSynTCP(r *stack.Route, tf tcpFields, opts header.TCPSynOp
|
||||
|
||||
func (e *endpoint) sendTCP(r *stack.Route, tf tcpFields, data buffer.VectorisedView, gso *stack.GSO) *tcpip.Error {
|
||||
tf.txHash = e.txHash
|
||||
if err := sendTCP(r, tf, data, gso); err != nil {
|
||||
if err := sendTCP(r, tf, data, gso, e.owner); err != nil {
|
||||
e.stats.SendErrors.SegmentSendToNetworkFailed.Increment()
|
||||
return err
|
||||
}
|
||||
@@ -787,7 +787,7 @@ func buildTCPHdr(r *stack.Route, tf tcpFields, pkt *stack.PacketBuffer, gso *sta
|
||||
}
|
||||
}
|
||||
|
||||
func sendTCPBatch(r *stack.Route, tf tcpFields, data buffer.VectorisedView, gso *stack.GSO) *tcpip.Error {
|
||||
func sendTCPBatch(r *stack.Route, tf tcpFields, data buffer.VectorisedView, gso *stack.GSO, owner tcpip.PacketOwner) *tcpip.Error {
|
||||
optLen := len(tf.opts)
|
||||
if tf.rcvWnd > 0xffff {
|
||||
tf.rcvWnd = 0xffff
|
||||
@@ -816,6 +816,7 @@ func sendTCPBatch(r *stack.Route, tf tcpFields, data buffer.VectorisedView, gso
|
||||
pkts[i].DataSize = packetSize
|
||||
pkts[i].Data = data
|
||||
pkts[i].Hash = tf.txHash
|
||||
pkts[i].Owner = owner
|
||||
buildTCPHdr(r, tf, &pkts[i], gso)
|
||||
off += packetSize
|
||||
tf.seq = tf.seq.Add(seqnum.Size(packetSize))
|
||||
@@ -833,14 +834,14 @@ func sendTCPBatch(r *stack.Route, tf tcpFields, data buffer.VectorisedView, gso
|
||||
|
||||
// sendTCP sends a TCP segment with the provided options via the provided
|
||||
// network endpoint and under the provided identity.
|
||||
func sendTCP(r *stack.Route, tf tcpFields, data buffer.VectorisedView, gso *stack.GSO) *tcpip.Error {
|
||||
func sendTCP(r *stack.Route, tf tcpFields, data buffer.VectorisedView, gso *stack.GSO, owner tcpip.PacketOwner) *tcpip.Error {
|
||||
optLen := len(tf.opts)
|
||||
if tf.rcvWnd > 0xffff {
|
||||
tf.rcvWnd = 0xffff
|
||||
}
|
||||
|
||||
if r.Loop&stack.PacketLoop == 0 && gso != nil && gso.Type == stack.GSOSW && int(gso.MSS) < data.Size() {
|
||||
return sendTCPBatch(r, tf, data, gso)
|
||||
return sendTCPBatch(r, tf, data, gso, owner)
|
||||
}
|
||||
|
||||
pkt := stack.PacketBuffer{
|
||||
@@ -849,6 +850,7 @@ func sendTCP(r *stack.Route, tf tcpFields, data buffer.VectorisedView, gso *stac
|
||||
DataSize: data.Size(),
|
||||
Data: data,
|
||||
Hash: tf.txHash,
|
||||
Owner: owner,
|
||||
}
|
||||
buildTCPHdr(r, tf, &pkt, gso)
|
||||
|
||||
|
||||
@@ -603,6 +603,9 @@ type endpoint struct {
|
||||
// txHash is the transport layer hash to be set on outbound packets
|
||||
// emitted by this endpoint.
|
||||
txHash uint32
|
||||
|
||||
// owner is used to get uid and gid of the packet.
|
||||
owner tcpip.PacketOwner
|
||||
}
|
||||
|
||||
// UniqueID implements stack.TransportEndpoint.UniqueID.
|
||||
@@ -1132,6 +1135,10 @@ func (e *endpoint) ModerateRecvBuf(copied int) {
|
||||
e.rcvListMu.Unlock()
|
||||
}
|
||||
|
||||
func (e *endpoint) SetOwner(owner tcpip.PacketOwner) {
|
||||
e.owner = owner
|
||||
}
|
||||
|
||||
// IPTables implements tcpip.Endpoint.IPTables.
|
||||
func (e *endpoint) IPTables() (stack.IPTables, error) {
|
||||
return e.stack.IPTables(), nil
|
||||
|
||||
@@ -157,7 +157,7 @@ func (r *ForwarderRequest) CreateEndpoint(queue *waiter.Queue) (tcpip.Endpoint,
|
||||
TSVal: r.synOptions.TSVal,
|
||||
TSEcr: r.synOptions.TSEcr,
|
||||
SACKPermitted: r.synOptions.SACKPermitted,
|
||||
}, queue)
|
||||
}, queue, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ func replyWithReset(s *segment) {
|
||||
seq: seq,
|
||||
ack: ack,
|
||||
rcvWnd: 0,
|
||||
}, buffer.VectorisedView{}, nil /* gso */)
|
||||
}, buffer.VectorisedView{}, nil /* gso */, nil /* PacketOwner */)
|
||||
}
|
||||
|
||||
// SetOption implements stack.TransportProtocol.SetOption.
|
||||
|
||||
@@ -143,6 +143,9 @@ type endpoint struct {
|
||||
|
||||
// TODO(b/142022063): Add ability to save and restore per endpoint stats.
|
||||
stats tcpip.TransportEndpointStats `state:"nosave"`
|
||||
|
||||
// owner is used to get uid and gid of the packet.
|
||||
owner tcpip.PacketOwner
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
@@ -484,7 +487,7 @@ func (e *endpoint) write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, <-c
|
||||
useDefaultTTL = false
|
||||
}
|
||||
|
||||
if err := sendUDP(route, buffer.View(v).ToVectorisedView(), e.ID.LocalPort, dstPort, ttl, useDefaultTTL, e.sendTOS); err != nil {
|
||||
if err := sendUDP(route, buffer.View(v).ToVectorisedView(), e.ID.LocalPort, dstPort, ttl, useDefaultTTL, e.sendTOS, e.owner); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return int64(len(v)), nil, nil
|
||||
@@ -886,7 +889,7 @@ func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
|
||||
|
||||
// sendUDP sends a UDP segment via the provided network endpoint and under the
|
||||
// provided identity.
|
||||
func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort uint16, ttl uint8, useDefaultTTL bool, tos uint8) *tcpip.Error {
|
||||
func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort uint16, ttl uint8, useDefaultTTL bool, tos uint8, owner tcpip.PacketOwner) *tcpip.Error {
|
||||
// Allocate a buffer for the UDP header.
|
||||
hdr := buffer.NewPrependable(header.UDPMinimumSize + int(r.MaxHeaderLength()))
|
||||
|
||||
@@ -916,6 +919,7 @@ func sendUDP(r *stack.Route, data buffer.VectorisedView, localPort, remotePort u
|
||||
Header: hdr,
|
||||
Data: data,
|
||||
TransportHeader: buffer.View(udp),
|
||||
Owner: owner,
|
||||
}); err != nil {
|
||||
r.Stats().UDP.PacketSendErrors.Increment()
|
||||
return err
|
||||
@@ -1356,3 +1360,7 @@ func (*endpoint) Wait() {}
|
||||
func isBroadcastOrMulticast(a tcpip.Address) bool {
|
||||
return a == header.IPv4Broadcast || header.IsV4MulticastAddress(a) || header.IsV6MulticastAddress(a)
|
||||
}
|
||||
|
||||
func (e *endpoint) SetOwner(owner tcpip.PacketOwner) {
|
||||
e.owner = owner
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user