summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/transport
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2021-10-13 14:36:53 -0700
committergVisor bot <gvisor-bot@google.com>2021-10-13 14:40:04 -0700
commit1796cd89d516033800f9c887250481c26bab0ae0 (patch)
treeb3386a5ab483f0c3a62f32a18e2e5e326bbdfdb8 /pkg/tcpip/transport
parent82218937948bd59f8d20e44575405874d56f0ae7 (diff)
add create-only raw sockets
These can be used by applications to manipulate iptables rules without enabling arbitrary reads from and writes to the underlying packet socket. PiperOrigin-RevId: 402924733
Diffstat (limited to 'pkg/tcpip/transport')
-rw-r--r--pkg/tcpip/transport/internal/noop/BUILD14
-rw-r--r--pkg/tcpip/transport/internal/noop/endpoint.go172
-rw-r--r--pkg/tcpip/transport/raw/BUILD1
-rw-r--r--pkg/tcpip/transport/raw/protocol.go16
4 files changed, 203 insertions, 0 deletions
diff --git a/pkg/tcpip/transport/internal/noop/BUILD b/pkg/tcpip/transport/internal/noop/BUILD
new file mode 100644
index 000000000..171c41eb1
--- /dev/null
+++ b/pkg/tcpip/transport/internal/noop/BUILD
@@ -0,0 +1,14 @@
+load("//tools:defs.bzl", "go_library")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "noop",
+ srcs = ["endpoint.go"],
+ visibility = ["//pkg/tcpip/transport/raw:__pkg__"],
+ deps = [
+ "//pkg/tcpip",
+ "//pkg/tcpip/stack",
+ "//pkg/waiter",
+ ],
+)
diff --git a/pkg/tcpip/transport/internal/noop/endpoint.go b/pkg/tcpip/transport/internal/noop/endpoint.go
new file mode 100644
index 000000000..443b4e416
--- /dev/null
+++ b/pkg/tcpip/transport/internal/noop/endpoint.go
@@ -0,0 +1,172 @@
+// Copyright 2021 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 noop contains an endpoint that implements all tcpip.Endpoint
+// functions as noops.
+package noop
+
+import (
+ "fmt"
+ "io"
+
+ "gvisor.dev/gvisor/pkg/tcpip"
+ "gvisor.dev/gvisor/pkg/tcpip/stack"
+ "gvisor.dev/gvisor/pkg/waiter"
+)
+
+// endpoint can be created, but all interactions have no effect or
+// return errors.
+//
+// +stateify savable
+type endpoint struct {
+ tcpip.DefaultSocketOptionsHandler
+ ops tcpip.SocketOptions
+}
+
+// New returns an initialized noop endpoint.
+func New(stk *stack.Stack) tcpip.Endpoint {
+ // ep.ops must be in a valid, initialized state for callers of
+ // ep.SocketOptions.
+ var ep endpoint
+ ep.ops.InitHandler(&ep, stk, tcpip.GetStackSendBufferLimits, tcpip.GetStackReceiveBufferLimits)
+ return &ep
+}
+
+// Abort implements stack.TransportEndpoint.Abort.
+func (*endpoint) Abort() {
+ // No-op.
+}
+
+// Close implements tcpip.Endpoint.Close.
+func (*endpoint) Close() {
+ // No-op.
+}
+
+// ModerateRecvBuf implements tcpip.Endpoint.ModerateRecvBuf.
+func (*endpoint) ModerateRecvBuf(int) {
+ // No-op.
+}
+
+func (*endpoint) SetOwner(tcpip.PacketOwner) {
+ // No-op.
+}
+
+// Read implements tcpip.Endpoint.Read.
+func (*endpoint) Read(io.Writer, tcpip.ReadOptions) (tcpip.ReadResult, tcpip.Error) {
+ return tcpip.ReadResult{}, &tcpip.ErrNotPermitted{}
+}
+
+// Write implements tcpip.Endpoint.Write.
+func (*endpoint) Write(tcpip.Payloader, tcpip.WriteOptions) (int64, tcpip.Error) {
+ return 0, &tcpip.ErrNotPermitted{}
+}
+
+// Disconnect implements tcpip.Endpoint.Disconnect.
+func (*endpoint) Disconnect() tcpip.Error {
+ return &tcpip.ErrNotSupported{}
+}
+
+// Connect implements tcpip.Endpoint.Connect.
+func (*endpoint) Connect(tcpip.FullAddress) tcpip.Error {
+ return &tcpip.ErrNotPermitted{}
+}
+
+// Shutdown implements tcpip.Endpoint.Shutdown.
+func (*endpoint) Shutdown(tcpip.ShutdownFlags) tcpip.Error {
+ return &tcpip.ErrNotPermitted{}
+}
+
+// Listen implements tcpip.Endpoint.Listen.
+func (*endpoint) Listen(int) tcpip.Error {
+ return &tcpip.ErrNotSupported{}
+}
+
+// Accept implements tcpip.Endpoint.Accept.
+func (*endpoint) Accept(*tcpip.FullAddress) (tcpip.Endpoint, *waiter.Queue, tcpip.Error) {
+ return nil, nil, &tcpip.ErrNotSupported{}
+}
+
+// Bind implements tcpip.Endpoint.Bind.
+func (*endpoint) Bind(tcpip.FullAddress) tcpip.Error {
+ return &tcpip.ErrNotPermitted{}
+}
+
+// GetLocalAddress implements tcpip.Endpoint.GetLocalAddress.
+func (*endpoint) GetLocalAddress() (tcpip.FullAddress, tcpip.Error) {
+ return tcpip.FullAddress{}, &tcpip.ErrNotSupported{}
+}
+
+// GetRemoteAddress implements tcpip.Endpoint.GetRemoteAddress.
+func (*endpoint) GetRemoteAddress() (tcpip.FullAddress, tcpip.Error) {
+ return tcpip.FullAddress{}, &tcpip.ErrNotConnected{}
+}
+
+// Readiness implements tcpip.Endpoint.Readiness.
+func (*endpoint) Readiness(waiter.EventMask) waiter.EventMask {
+ return 0
+}
+
+// SetSockOpt implements tcpip.Endpoint.SetSockOpt.
+func (*endpoint) SetSockOpt(tcpip.SettableSocketOption) tcpip.Error {
+ return &tcpip.ErrUnknownProtocolOption{}
+}
+
+func (*endpoint) SetSockOptInt(tcpip.SockOptInt, int) tcpip.Error {
+ return &tcpip.ErrUnknownProtocolOption{}
+}
+
+// GetSockOpt implements tcpip.Endpoint.GetSockOpt.
+func (*endpoint) GetSockOpt(tcpip.GettableSocketOption) tcpip.Error {
+ return &tcpip.ErrUnknownProtocolOption{}
+}
+
+// GetSockOptInt implements tcpip.Endpoint.GetSockOptInt.
+func (*endpoint) GetSockOptInt(tcpip.SockOptInt) (int, tcpip.Error) {
+ return 0, &tcpip.ErrUnknownProtocolOption{}
+}
+
+// HandlePacket implements stack.RawTransportEndpoint.HandlePacket.
+func (*endpoint) HandlePacket(pkt *stack.PacketBuffer) {
+ panic(fmt.Sprintf("unreachable: noop.endpoint should never be registered, but got packet: %+v", pkt))
+}
+
+// State implements socket.Socket.State.
+func (*endpoint) State() uint32 {
+ return 0
+}
+
+// Wait implements stack.TransportEndpoint.Wait.
+func (*endpoint) Wait() {
+ // No-op.
+}
+
+// LastError implements tcpip.Endpoint.LastError.
+func (*endpoint) LastError() tcpip.Error {
+ return nil
+}
+
+// SocketOptions implements tcpip.Endpoint.SocketOptions.
+func (ep *endpoint) SocketOptions() *tcpip.SocketOptions {
+ return &ep.ops
+}
+
+// Info implements tcpip.Endpoint.Info.
+func (*endpoint) Info() tcpip.EndpointInfo {
+ return &stack.TransportEndpointInfo{}
+}
+
+// Stats returns a pointer to the endpoint stats.
+func (*endpoint) Stats() tcpip.EndpointStats {
+ return &tcpip.TransportEndpointStats{}
+}
diff --git a/pkg/tcpip/transport/raw/BUILD b/pkg/tcpip/transport/raw/BUILD
index b7e97e218..10b0c35fb 100644
--- a/pkg/tcpip/transport/raw/BUILD
+++ b/pkg/tcpip/transport/raw/BUILD
@@ -35,6 +35,7 @@ go_library(
"//pkg/tcpip/stack",
"//pkg/tcpip/transport",
"//pkg/tcpip/transport/internal/network",
+ "//pkg/tcpip/transport/internal/noop",
"//pkg/tcpip/transport/packet",
"//pkg/waiter",
],
diff --git a/pkg/tcpip/transport/raw/protocol.go b/pkg/tcpip/transport/raw/protocol.go
index e393b993d..624e2dbe7 100644
--- a/pkg/tcpip/transport/raw/protocol.go
+++ b/pkg/tcpip/transport/raw/protocol.go
@@ -17,6 +17,7 @@ package raw
import (
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
+ "gvisor.dev/gvisor/pkg/tcpip/transport/internal/noop"
"gvisor.dev/gvisor/pkg/tcpip/transport/packet"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -33,3 +34,18 @@ func (EndpointFactory) NewUnassociatedEndpoint(stack *stack.Stack, netProto tcpi
func (EndpointFactory) NewPacketEndpoint(stack *stack.Stack, cooked bool, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, tcpip.Error) {
return packet.NewEndpoint(stack, cooked, netProto, waiterQueue)
}
+
+// CreateOnlyFactory implements stack.RawFactory. It allows creation of raw
+// endpoints that do not support reading, writing, binding, etc.
+type CreateOnlyFactory struct{}
+
+// NewUnassociatedEndpoint implements stack.RawFactory.NewUnassociatedEndpoint.
+func (CreateOnlyFactory) NewUnassociatedEndpoint(stk *stack.Stack, _ tcpip.NetworkProtocolNumber, _ tcpip.TransportProtocolNumber, _ *waiter.Queue) (tcpip.Endpoint, tcpip.Error) {
+ return noop.New(stk), nil
+}
+
+// NewPacketEndpoint implements stack.RawFactory.NewPacketEndpoint.
+func (CreateOnlyFactory) NewPacketEndpoint(*stack.Stack, bool, tcpip.NetworkProtocolNumber, *waiter.Queue) (tcpip.Endpoint, tcpip.Error) {
+ // This isn't needed by anything, so it isn't implemented.
+ return nil, &tcpip.ErrNotPermitted{}
+}