mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Marshallable socket opitons.
Socket option values are now required to implement marshal.Marshallable. Co-authored-by: Rahat Mahmood <rahat@google.com> PiperOrigin-RevId: 322831612
This commit is contained in:
committed by
gVisor bot
co-authored by
Rahat Mahmood
parent
384369e01e
commit
6f7f739967
@@ -72,6 +72,9 @@ go_library(
|
||||
"//pkg/abi",
|
||||
"//pkg/binary",
|
||||
"//pkg/bits",
|
||||
"//pkg/usermem",
|
||||
"//tools/go_marshal/marshal",
|
||||
"//tools/go_marshal/primitive",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
+134
-12
@@ -14,6 +14,14 @@
|
||||
|
||||
package linux
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/primitive"
|
||||
)
|
||||
|
||||
// This file contains structures required to support netfilter, specifically
|
||||
// the iptables tool.
|
||||
|
||||
@@ -76,6 +84,8 @@ const (
|
||||
|
||||
// IPTEntry is an iptable rule. It corresponds to struct ipt_entry in
|
||||
// include/uapi/linux/netfilter_ipv4/ip_tables.h.
|
||||
//
|
||||
// +marshal
|
||||
type IPTEntry struct {
|
||||
// IP is used to filter packets based on the IP header.
|
||||
IP IPTIP
|
||||
@@ -112,21 +122,41 @@ type IPTEntry struct {
|
||||
// SizeOfIPTEntry is the size of an IPTEntry.
|
||||
const SizeOfIPTEntry = 112
|
||||
|
||||
// KernelIPTEntry is identical to IPTEntry, but includes the Elems field. This
|
||||
// struct marshaled via the binary package to write an IPTEntry to userspace.
|
||||
// KernelIPTEntry is identical to IPTEntry, but includes the Elems field.
|
||||
// KernelIPTEntry itself is not Marshallable but it implements some methods of
|
||||
// marshal.Marshallable that help in other implementations of Marshallable.
|
||||
type KernelIPTEntry struct {
|
||||
IPTEntry
|
||||
Entry IPTEntry
|
||||
|
||||
// Elems holds the data for all this rule's matches followed by the
|
||||
// target. It is variable length -- users have to iterate over any
|
||||
// matches and use TargetOffset and NextOffset to make sense of the
|
||||
// data.
|
||||
Elems []byte
|
||||
Elems primitive.ByteSlice
|
||||
}
|
||||
|
||||
// SizeBytes implements marshal.Marshallable.SizeBytes.
|
||||
func (ke *KernelIPTEntry) SizeBytes() int {
|
||||
return ke.Entry.SizeBytes() + ke.Elems.SizeBytes()
|
||||
}
|
||||
|
||||
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
|
||||
func (ke *KernelIPTEntry) MarshalBytes(dst []byte) {
|
||||
ke.Entry.MarshalBytes(dst)
|
||||
ke.Elems.MarshalBytes(dst[ke.Entry.SizeBytes():])
|
||||
}
|
||||
|
||||
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
|
||||
func (ke *KernelIPTEntry) UnmarshalBytes(src []byte) {
|
||||
ke.Entry.UnmarshalBytes(src)
|
||||
ke.Elems.UnmarshalBytes(src[ke.Entry.SizeBytes():])
|
||||
}
|
||||
|
||||
// IPTIP contains information for matching a packet's IP header.
|
||||
// It corresponds to struct ipt_ip in
|
||||
// include/uapi/linux/netfilter_ipv4/ip_tables.h.
|
||||
//
|
||||
// +marshal
|
||||
type IPTIP struct {
|
||||
// Src is the source IP address.
|
||||
Src InetAddr
|
||||
@@ -189,6 +219,8 @@ const SizeOfIPTIP = 84
|
||||
|
||||
// XTCounters holds packet and byte counts for a rule. It corresponds to struct
|
||||
// xt_counters in include/uapi/linux/netfilter/x_tables.h.
|
||||
//
|
||||
// +marshal
|
||||
type XTCounters struct {
|
||||
// Pcnt is the packet count.
|
||||
Pcnt uint64
|
||||
@@ -321,6 +353,8 @@ const SizeOfXTRedirectTarget = 56
|
||||
|
||||
// IPTGetinfo is the argument for the IPT_SO_GET_INFO sockopt. It corresponds
|
||||
// to struct ipt_getinfo in include/uapi/linux/netfilter_ipv4/ip_tables.h.
|
||||
//
|
||||
// +marshal
|
||||
type IPTGetinfo struct {
|
||||
Name TableName
|
||||
ValidHooks uint32
|
||||
@@ -336,6 +370,8 @@ const SizeOfIPTGetinfo = 84
|
||||
// IPTGetEntries is the argument for the IPT_SO_GET_ENTRIES sockopt. It
|
||||
// corresponds to struct ipt_get_entries in
|
||||
// include/uapi/linux/netfilter_ipv4/ip_tables.h.
|
||||
//
|
||||
// +marshal
|
||||
type IPTGetEntries struct {
|
||||
Name TableName
|
||||
Size uint32
|
||||
@@ -350,13 +386,103 @@ type IPTGetEntries struct {
|
||||
const SizeOfIPTGetEntries = 40
|
||||
|
||||
// KernelIPTGetEntries is identical to IPTGetEntries, but includes the
|
||||
// Entrytable field. This struct marshaled via the binary package to write an
|
||||
// KernelIPTGetEntries to userspace.
|
||||
// Entrytable field. This has been manually made marshal.Marshallable since it
|
||||
// is dynamically sized.
|
||||
type KernelIPTGetEntries struct {
|
||||
IPTGetEntries
|
||||
Entrytable []KernelIPTEntry
|
||||
}
|
||||
|
||||
// SizeBytes implements marshal.Marshallable.SizeBytes.
|
||||
func (ke *KernelIPTGetEntries) SizeBytes() int {
|
||||
res := ke.IPTGetEntries.SizeBytes()
|
||||
for _, entry := range ke.Entrytable {
|
||||
res += entry.SizeBytes()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
|
||||
func (ke *KernelIPTGetEntries) MarshalBytes(dst []byte) {
|
||||
ke.IPTGetEntries.MarshalBytes(dst)
|
||||
marshalledUntil := ke.IPTGetEntries.SizeBytes()
|
||||
for i := 0; i < len(ke.Entrytable); i++ {
|
||||
ke.Entrytable[i].MarshalBytes(dst[marshalledUntil:])
|
||||
marshalledUntil += ke.Entrytable[i].SizeBytes()
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.
|
||||
func (ke *KernelIPTGetEntries) UnmarshalBytes(src []byte) {
|
||||
ke.IPTGetEntries.UnmarshalBytes(src)
|
||||
unmarshalledUntil := ke.IPTGetEntries.SizeBytes()
|
||||
for i := 0; i < len(ke.Entrytable); i++ {
|
||||
ke.Entrytable[i].UnmarshalBytes(src[unmarshalledUntil:])
|
||||
unmarshalledUntil += ke.Entrytable[i].SizeBytes()
|
||||
}
|
||||
}
|
||||
|
||||
// Packed implements marshal.Marshallable.Packed.
|
||||
func (ke *KernelIPTGetEntries) Packed() bool {
|
||||
// KernelIPTGetEntries isn't packed because the ke.Entrytable contains an
|
||||
// indirection to the actual data we want to marshal (the slice data
|
||||
// pointer), and the memory for KernelIPTGetEntries contains the slice
|
||||
// header which we don't want to marshal.
|
||||
return false
|
||||
}
|
||||
|
||||
// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.
|
||||
func (ke *KernelIPTGetEntries) MarshalUnsafe(dst []byte) {
|
||||
// Fall back to safe Marshal because the type in not packed.
|
||||
ke.MarshalBytes(dst)
|
||||
}
|
||||
|
||||
// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.
|
||||
func (ke *KernelIPTGetEntries) UnmarshalUnsafe(src []byte) {
|
||||
// Fall back to safe Unmarshal because the type in not packed.
|
||||
ke.UnmarshalBytes(src)
|
||||
}
|
||||
|
||||
// CopyIn implements marshal.Marshallable.CopyIn.
|
||||
func (ke *KernelIPTGetEntries) CopyIn(task marshal.Task, addr usermem.Addr) (int, error) {
|
||||
buf := task.CopyScratchBuffer(ke.SizeBytes()) // escapes: okay.
|
||||
length, err := task.CopyInBytes(addr, buf) // escapes: okay.
|
||||
// Unmarshal unconditionally. If we had a short copy-in, this results in a
|
||||
// partially unmarshalled struct.
|
||||
ke.UnmarshalBytes(buf) // escapes: fallback.
|
||||
return length, err
|
||||
}
|
||||
|
||||
// CopyOut implements marshal.Marshallable.CopyOut.
|
||||
func (ke *KernelIPTGetEntries) CopyOut(task marshal.Task, addr usermem.Addr) (int, error) {
|
||||
// Type KernelIPTGetEntries doesn't have a packed layout in memory, fall
|
||||
// back to MarshalBytes.
|
||||
return task.CopyOutBytes(addr, ke.marshalAll(task))
|
||||
}
|
||||
|
||||
// CopyOutN implements marshal.Marshallable.CopyOutN.
|
||||
func (ke *KernelIPTGetEntries) CopyOutN(task marshal.Task, addr usermem.Addr, limit int) (int, error) {
|
||||
// Type KernelIPTGetEntries doesn't have a packed layout in memory, fall
|
||||
// back to MarshalBytes.
|
||||
return task.CopyOutBytes(addr, ke.marshalAll(task)[:limit])
|
||||
}
|
||||
|
||||
func (ke *KernelIPTGetEntries) marshalAll(task marshal.Task) []byte {
|
||||
buf := task.CopyScratchBuffer(ke.SizeBytes())
|
||||
ke.MarshalBytes(buf)
|
||||
return buf
|
||||
}
|
||||
|
||||
// WriteTo implements io.WriterTo.WriteTo.
|
||||
func (ke *KernelIPTGetEntries) WriteTo(w io.Writer) (int64, error) {
|
||||
buf := make([]byte, ke.SizeBytes())
|
||||
ke.MarshalBytes(buf)
|
||||
length, err := w.Write(buf)
|
||||
return int64(length), err
|
||||
}
|
||||
|
||||
var _ marshal.Marshallable = (*KernelIPTGetEntries)(nil)
|
||||
|
||||
// IPTReplace is the argument for the IPT_SO_SET_REPLACE sockopt. It
|
||||
// corresponds to struct ipt_replace in
|
||||
// include/uapi/linux/netfilter_ipv4/ip_tables.h.
|
||||
@@ -374,12 +500,6 @@ type IPTReplace struct {
|
||||
// Entries [0]IPTEntry
|
||||
}
|
||||
|
||||
// KernelIPTReplace is identical to IPTReplace, but includes the Entries field.
|
||||
type KernelIPTReplace struct {
|
||||
IPTReplace
|
||||
Entries [0]IPTEntry
|
||||
}
|
||||
|
||||
// SizeOfIPTReplace is the size of an IPTReplace.
|
||||
const SizeOfIPTReplace = 96
|
||||
|
||||
@@ -392,6 +512,8 @@ func (en ExtensionName) String() string {
|
||||
}
|
||||
|
||||
// TableName holds the name of a netfilter table.
|
||||
//
|
||||
// +marshal
|
||||
type TableName [XT_TABLE_MAXNAMELEN]byte
|
||||
|
||||
// String implements fmt.Stringer.
|
||||
|
||||
@@ -234,6 +234,8 @@ const (
|
||||
const SockAddrMax = 128
|
||||
|
||||
// InetAddr is struct in_addr, from uapi/linux/in.h.
|
||||
//
|
||||
// +marshal
|
||||
type InetAddr [4]byte
|
||||
|
||||
// SockAddrInet is struct sockaddr_in, from uapi/linux/in.h.
|
||||
@@ -303,6 +305,8 @@ func (s *SockAddrUnix) implementsSockAddr() {}
|
||||
func (s *SockAddrNetlink) implementsSockAddr() {}
|
||||
|
||||
// Linger is struct linger, from include/linux/socket.h.
|
||||
//
|
||||
// +marshal
|
||||
type Linger struct {
|
||||
OnOff int32
|
||||
Linger int32
|
||||
@@ -317,6 +321,8 @@ const SizeOfLinger = 8
|
||||
// the end of this struct or within existing unusued space, so its size grows
|
||||
// over time. The current iteration is based on linux v4.17. New versions are
|
||||
// always backwards compatible.
|
||||
//
|
||||
// +marshal
|
||||
type TCPInfo struct {
|
||||
State uint8
|
||||
CaState uint8
|
||||
@@ -414,6 +420,8 @@ var SizeOfControlMessageHeader = int(binary.Size(ControlMessageHeader{}))
|
||||
// A ControlMessageCredentials is an SCM_CREDENTIALS socket control message.
|
||||
//
|
||||
// ControlMessageCredentials represents struct ucred from linux/socket.h.
|
||||
//
|
||||
// +marshal
|
||||
type ControlMessageCredentials struct {
|
||||
PID int32
|
||||
UID uint32
|
||||
|
||||
@@ -20,5 +20,6 @@ go_library(
|
||||
"//pkg/syserr",
|
||||
"//pkg/tcpip",
|
||||
"//pkg/usermem",
|
||||
"//tools/go_marshal/marshal",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -40,6 +40,8 @@ go_library(
|
||||
"//pkg/tcpip/stack",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"//tools/go_marshal/marshal",
|
||||
"//tools/go_marshal/primitive",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -36,6 +36,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/primitive"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -319,7 +321,7 @@ func (s *socketOpsCommon) Shutdown(t *kernel.Task, how int) *syserr.Error {
|
||||
}
|
||||
|
||||
// GetSockOpt implements socket.Socket.GetSockOpt.
|
||||
func (s *socketOpsCommon) GetSockOpt(t *kernel.Task, level int, name int, outPtr usermem.Addr, outLen int) (interface{}, *syserr.Error) {
|
||||
func (s *socketOpsCommon) GetSockOpt(t *kernel.Task, level int, name int, outPtr usermem.Addr, outLen int) (marshal.Marshallable, *syserr.Error) {
|
||||
if outLen < 0 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
@@ -364,7 +366,8 @@ func (s *socketOpsCommon) GetSockOpt(t *kernel.Task, level int, name int, outPtr
|
||||
if err != nil {
|
||||
return nil, syserr.FromError(err)
|
||||
}
|
||||
return opt, nil
|
||||
optP := primitive.ByteSlice(opt)
|
||||
return &optP, nil
|
||||
}
|
||||
|
||||
// SetSockOpt implements socket.Socket.SetSockOpt.
|
||||
|
||||
@@ -145,7 +145,7 @@ func convertNetstackToBinary(stack *stack.Stack, tablename linux.TableName) (lin
|
||||
|
||||
// Each rule corresponds to an entry.
|
||||
entry := linux.KernelIPTEntry{
|
||||
IPTEntry: linux.IPTEntry{
|
||||
Entry: linux.IPTEntry{
|
||||
IP: linux.IPTIP{
|
||||
Protocol: uint16(rule.Filter.Protocol),
|
||||
},
|
||||
@@ -153,20 +153,20 @@ func convertNetstackToBinary(stack *stack.Stack, tablename linux.TableName) (lin
|
||||
TargetOffset: linux.SizeOfIPTEntry,
|
||||
},
|
||||
}
|
||||
copy(entry.IPTEntry.IP.Dst[:], rule.Filter.Dst)
|
||||
copy(entry.IPTEntry.IP.DstMask[:], rule.Filter.DstMask)
|
||||
copy(entry.IPTEntry.IP.Src[:], rule.Filter.Src)
|
||||
copy(entry.IPTEntry.IP.SrcMask[:], rule.Filter.SrcMask)
|
||||
copy(entry.IPTEntry.IP.OutputInterface[:], rule.Filter.OutputInterface)
|
||||
copy(entry.IPTEntry.IP.OutputInterfaceMask[:], rule.Filter.OutputInterfaceMask)
|
||||
copy(entry.Entry.IP.Dst[:], rule.Filter.Dst)
|
||||
copy(entry.Entry.IP.DstMask[:], rule.Filter.DstMask)
|
||||
copy(entry.Entry.IP.Src[:], rule.Filter.Src)
|
||||
copy(entry.Entry.IP.SrcMask[:], rule.Filter.SrcMask)
|
||||
copy(entry.Entry.IP.OutputInterface[:], rule.Filter.OutputInterface)
|
||||
copy(entry.Entry.IP.OutputInterfaceMask[:], rule.Filter.OutputInterfaceMask)
|
||||
if rule.Filter.DstInvert {
|
||||
entry.IPTEntry.IP.InverseFlags |= linux.IPT_INV_DSTIP
|
||||
entry.Entry.IP.InverseFlags |= linux.IPT_INV_DSTIP
|
||||
}
|
||||
if rule.Filter.SrcInvert {
|
||||
entry.IPTEntry.IP.InverseFlags |= linux.IPT_INV_SRCIP
|
||||
entry.Entry.IP.InverseFlags |= linux.IPT_INV_SRCIP
|
||||
}
|
||||
if rule.Filter.OutputInterfaceInvert {
|
||||
entry.IPTEntry.IP.InverseFlags |= linux.IPT_INV_VIA_OUT
|
||||
entry.Entry.IP.InverseFlags |= linux.IPT_INV_VIA_OUT
|
||||
}
|
||||
|
||||
for _, matcher := range rule.Matchers {
|
||||
@@ -178,8 +178,8 @@ func convertNetstackToBinary(stack *stack.Stack, tablename linux.TableName) (lin
|
||||
panic(fmt.Sprintf("matcher %T is not 64-bit aligned", matcher))
|
||||
}
|
||||
entry.Elems = append(entry.Elems, serialized...)
|
||||
entry.NextOffset += uint16(len(serialized))
|
||||
entry.TargetOffset += uint16(len(serialized))
|
||||
entry.Entry.NextOffset += uint16(len(serialized))
|
||||
entry.Entry.TargetOffset += uint16(len(serialized))
|
||||
}
|
||||
|
||||
// Serialize and append the target.
|
||||
@@ -188,11 +188,11 @@ func convertNetstackToBinary(stack *stack.Stack, tablename linux.TableName) (lin
|
||||
panic(fmt.Sprintf("target %T is not 64-bit aligned", rule.Target))
|
||||
}
|
||||
entry.Elems = append(entry.Elems, serialized...)
|
||||
entry.NextOffset += uint16(len(serialized))
|
||||
entry.Entry.NextOffset += uint16(len(serialized))
|
||||
|
||||
nflog("convert to binary: adding entry: %+v", entry)
|
||||
|
||||
entries.Size += uint32(entry.NextOffset)
|
||||
entries.Size += uint32(entry.Entry.NextOffset)
|
||||
entries.Entrytable = append(entries.Entrytable, entry)
|
||||
info.NumEntries++
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ go_library(
|
||||
"//pkg/tcpip",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"//tools/go_marshal/marshal",
|
||||
"//tools/go_marshal/primitive",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/primitive"
|
||||
)
|
||||
|
||||
const sizeOfInt32 int = 4
|
||||
@@ -330,7 +332,7 @@ func (s *socketOpsCommon) Shutdown(t *kernel.Task, how int) *syserr.Error {
|
||||
}
|
||||
|
||||
// GetSockOpt implements socket.Socket.GetSockOpt.
|
||||
func (s *socketOpsCommon) GetSockOpt(t *kernel.Task, level int, name int, outPtr usermem.Addr, outLen int) (interface{}, *syserr.Error) {
|
||||
func (s *socketOpsCommon) GetSockOpt(t *kernel.Task, level int, name int, outPtr usermem.Addr, outLen int) (marshal.Marshallable, *syserr.Error) {
|
||||
switch level {
|
||||
case linux.SOL_SOCKET:
|
||||
switch name {
|
||||
@@ -340,24 +342,26 @@ func (s *socketOpsCommon) GetSockOpt(t *kernel.Task, level int, name int, outPtr
|
||||
}
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
return int32(s.sendBufferSize), nil
|
||||
sendBufferSizeP := primitive.Int32(s.sendBufferSize)
|
||||
return &sendBufferSizeP, nil
|
||||
|
||||
case linux.SO_RCVBUF:
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
// We don't have limit on receiving size.
|
||||
return int32(math.MaxInt32), nil
|
||||
recvBufferSizeP := primitive.Int32(math.MaxInt32)
|
||||
return &recvBufferSizeP, nil
|
||||
|
||||
case linux.SO_PASSCRED:
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
var passcred int32
|
||||
var passcred primitive.Int32
|
||||
if s.Passcred() {
|
||||
passcred = 1
|
||||
}
|
||||
return passcred, nil
|
||||
return &passcred, nil
|
||||
|
||||
default:
|
||||
socket.GetSockOptEmitUnimplementedEvent(t, name)
|
||||
|
||||
@@ -51,6 +51,8 @@ go_library(
|
||||
"//pkg/tcpip/transport/udp",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"//tools/go_marshal/marshal",
|
||||
"//tools/go_marshal/primitive",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/primitive"
|
||||
)
|
||||
|
||||
// SocketVFS2 encapsulates all the state needed to represent a network stack
|
||||
@@ -200,7 +202,7 @@ func (s *SocketVFS2) Ioctl(ctx context.Context, uio usermem.IO, args arch.Syscal
|
||||
|
||||
// GetSockOpt implements the linux syscall getsockopt(2) for sockets backed by
|
||||
// tcpip.Endpoint.
|
||||
func (s *SocketVFS2) GetSockOpt(t *kernel.Task, level, name int, outPtr usermem.Addr, outLen int) (interface{}, *syserr.Error) {
|
||||
func (s *SocketVFS2) GetSockOpt(t *kernel.Task, level, name int, outPtr usermem.Addr, outLen int) (marshal.Marshallable, *syserr.Error) {
|
||||
// TODO(b/78348848): Unlike other socket options, SO_TIMESTAMP is
|
||||
// implemented specifically for netstack.SocketVFS2 rather than
|
||||
// commonEndpoint. commonEndpoint should be extended to support socket
|
||||
@@ -210,25 +212,25 @@ func (s *SocketVFS2) GetSockOpt(t *kernel.Task, level, name int, outPtr usermem.
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
val := int32(0)
|
||||
val := primitive.Int32(0)
|
||||
s.readMu.Lock()
|
||||
defer s.readMu.Unlock()
|
||||
if s.sockOptTimestamp {
|
||||
val = 1
|
||||
}
|
||||
return val, nil
|
||||
return &val, nil
|
||||
}
|
||||
if level == linux.SOL_TCP && name == linux.TCP_INQ {
|
||||
if outLen < sizeOfInt32 {
|
||||
return nil, syserr.ErrInvalidArgument
|
||||
}
|
||||
val := int32(0)
|
||||
val := primitive.Int32(0)
|
||||
s.readMu.Lock()
|
||||
defer s.readMu.Unlock()
|
||||
if s.sockOptInq {
|
||||
val = 1
|
||||
}
|
||||
return val, nil
|
||||
return &val, nil
|
||||
}
|
||||
|
||||
if s.skType == linux.SOCK_RAW && level == linux.IPPROTO_IP {
|
||||
@@ -246,7 +248,7 @@ func (s *SocketVFS2) GetSockOpt(t *kernel.Task, level, name int, outPtr usermem.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return info, nil
|
||||
return &info, nil
|
||||
|
||||
case linux.IPT_SO_GET_ENTRIES:
|
||||
if outLen < linux.SizeOfIPTGetEntries {
|
||||
@@ -261,7 +263,7 @@ func (s *SocketVFS2) GetSockOpt(t *kernel.Task, level, name int, outPtr usermem.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return entries, nil
|
||||
return &entries, nil
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
)
|
||||
|
||||
// ControlMessages represents the union of unix control messages and tcpip
|
||||
@@ -86,7 +87,7 @@ type SocketOps interface {
|
||||
Shutdown(t *kernel.Task, how int) *syserr.Error
|
||||
|
||||
// GetSockOpt implements the getsockopt(2) linux syscall.
|
||||
GetSockOpt(t *kernel.Task, level int, name int, outPtr usermem.Addr, outLen int) (interface{}, *syserr.Error)
|
||||
GetSockOpt(t *kernel.Task, level int, name int, outPtr usermem.Addr, outLen int) (marshal.Marshallable, *syserr.Error)
|
||||
|
||||
// SetSockOpt implements the setsockopt(2) linux syscall.
|
||||
SetSockOpt(t *kernel.Task, level int, name int, opt []byte) *syserr.Error
|
||||
|
||||
@@ -35,5 +35,6 @@ go_library(
|
||||
"//pkg/tcpip",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"//tools/go_marshal/marshal",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -40,6 +40,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
)
|
||||
|
||||
// SocketOperations is a Unix socket. It is similar to a netstack socket,
|
||||
@@ -184,7 +185,7 @@ func (s *SocketOperations) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO,
|
||||
|
||||
// GetSockOpt implements the linux syscall getsockopt(2) for sockets backed by
|
||||
// a transport.Endpoint.
|
||||
func (s *SocketOperations) GetSockOpt(t *kernel.Task, level, name int, outPtr usermem.Addr, outLen int) (interface{}, *syserr.Error) {
|
||||
func (s *SocketOperations) GetSockOpt(t *kernel.Task, level, name int, outPtr usermem.Addr, outLen int) (marshal.Marshallable, *syserr.Error) {
|
||||
return netstack.GetSockOpt(t, s, s.ep, linux.AF_UNIX, s.ep.Type(), level, name, outLen)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
)
|
||||
|
||||
// SocketVFS2 implements socket.SocketVFS2 (and by extension,
|
||||
@@ -89,7 +90,7 @@ func NewFileDescription(ep transport.Endpoint, stype linux.SockType, flags uint3
|
||||
|
||||
// GetSockOpt implements the linux syscall getsockopt(2) for sockets backed by
|
||||
// a transport.Endpoint.
|
||||
func (s *SocketVFS2) GetSockOpt(t *kernel.Task, level int, name int, outPtr usermem.Addr, outLen int) (interface{}, *syserr.Error) {
|
||||
func (s *SocketVFS2) GetSockOpt(t *kernel.Task, level, name int, outPtr usermem.Addr, outLen int) (marshal.Marshallable, *syserr.Error) {
|
||||
return netstack.GetSockOpt(t, s, s.ep, linux.AF_UNIX, s.ep.Type(), level, name, outLen)
|
||||
}
|
||||
|
||||
|
||||
@@ -99,5 +99,7 @@ go_library(
|
||||
"//pkg/syserror",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"//tools/go_marshal/marshal",
|
||||
"//tools/go_marshal/primitive",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -29,6 +29,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/primitive"
|
||||
)
|
||||
|
||||
// LINT.IfChange
|
||||
@@ -474,7 +476,7 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
|
||||
}
|
||||
|
||||
if v != nil {
|
||||
if _, err := t.CopyOut(optValAddr, v); err != nil {
|
||||
if _, err := v.CopyOut(t, optValAddr); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
}
|
||||
@@ -484,7 +486,7 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
|
||||
|
||||
// getSockOpt tries to handle common socket options, or dispatches to a specific
|
||||
// socket implementation.
|
||||
func getSockOpt(t *kernel.Task, s socket.Socket, level, name int, optValAddr usermem.Addr, len int) (interface{}, *syserr.Error) {
|
||||
func getSockOpt(t *kernel.Task, s socket.Socket, level, name int, optValAddr usermem.Addr, len int) (marshal.Marshallable, *syserr.Error) {
|
||||
if level == linux.SOL_SOCKET {
|
||||
switch name {
|
||||
case linux.SO_TYPE, linux.SO_DOMAIN, linux.SO_PROTOCOL:
|
||||
@@ -496,13 +498,16 @@ func getSockOpt(t *kernel.Task, s socket.Socket, level, name int, optValAddr use
|
||||
switch name {
|
||||
case linux.SO_TYPE:
|
||||
_, skType, _ := s.Type()
|
||||
return int32(skType), nil
|
||||
v := primitive.Int32(skType)
|
||||
return &v, nil
|
||||
case linux.SO_DOMAIN:
|
||||
family, _, _ := s.Type()
|
||||
return int32(family), nil
|
||||
v := primitive.Int32(family)
|
||||
return &v, nil
|
||||
case linux.SO_PROTOCOL:
|
||||
_, _, protocol := s.Type()
|
||||
return int32(protocol), nil
|
||||
v := primitive.Int32(protocol)
|
||||
return &v, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,7 +544,7 @@ func SetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
|
||||
return 0, nil, syserror.EINVAL
|
||||
}
|
||||
buf := t.CopyScratchBuffer(int(optLen))
|
||||
if _, err := t.CopyIn(optValAddr, &buf); err != nil {
|
||||
if _, err := t.CopyInBytes(optValAddr, buf); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -72,5 +72,7 @@ go_library(
|
||||
"//pkg/syserror",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"//tools/go_marshal/marshal",
|
||||
"//tools/go_marshal/primitive",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -30,6 +30,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/syserr"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/marshal"
|
||||
"gvisor.dev/gvisor/tools/go_marshal/primitive"
|
||||
)
|
||||
|
||||
// minListenBacklog is the minimum reasonable backlog for listening sockets.
|
||||
@@ -477,7 +479,7 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
|
||||
}
|
||||
|
||||
if v != nil {
|
||||
if _, err := t.CopyOut(optValAddr, v); err != nil {
|
||||
if _, err := v.CopyOut(t, optValAddr); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
}
|
||||
@@ -487,7 +489,7 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
|
||||
|
||||
// getSockOpt tries to handle common socket options, or dispatches to a specific
|
||||
// socket implementation.
|
||||
func getSockOpt(t *kernel.Task, s socket.SocketVFS2, level, name int, optValAddr usermem.Addr, len int) (interface{}, *syserr.Error) {
|
||||
func getSockOpt(t *kernel.Task, s socket.SocketVFS2, level, name int, optValAddr usermem.Addr, len int) (marshal.Marshallable, *syserr.Error) {
|
||||
if level == linux.SOL_SOCKET {
|
||||
switch name {
|
||||
case linux.SO_TYPE, linux.SO_DOMAIN, linux.SO_PROTOCOL:
|
||||
@@ -499,13 +501,16 @@ func getSockOpt(t *kernel.Task, s socket.SocketVFS2, level, name int, optValAddr
|
||||
switch name {
|
||||
case linux.SO_TYPE:
|
||||
_, skType, _ := s.Type()
|
||||
return int32(skType), nil
|
||||
v := primitive.Int32(skType)
|
||||
return &v, nil
|
||||
case linux.SO_DOMAIN:
|
||||
family, _, _ := s.Type()
|
||||
return int32(family), nil
|
||||
v := primitive.Int32(family)
|
||||
return &v, nil
|
||||
case linux.SO_PROTOCOL:
|
||||
_, _, protocol := s.Type()
|
||||
return int32(protocol), nil
|
||||
v := primitive.Int32(protocol)
|
||||
return &v, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,7 +547,7 @@ func SetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
|
||||
return 0, nil, syserror.EINVAL
|
||||
}
|
||||
buf := t.CopyScratchBuffer(int(optLen))
|
||||
if _, err := t.CopyIn(optValAddr, &buf); err != nil {
|
||||
if _, err := t.CopyInBytes(optValAddr, buf); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user