summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/socket/rpcinet
diff options
context:
space:
mode:
authorBrian Geffon <bgeffon@google.com>2018-06-05 15:43:55 -0700
committerShentubot <shentubot@google.com>2018-06-05 15:45:35 -0700
commitff7b4a156f95a587b5df4de89a22c200fceabb96 (patch)
treedbf2206d66db40f71c1d92784cbc60126a59e1d3 /pkg/sentry/socket/rpcinet
parent343020ca275298fe9ea3320628454cad5f0052aa (diff)
Add support for rpcinet owned procfs files.
This change will add support for /proc/sys/net and /proc/net which will be managed and owned by rpcinet. This will allow these inodes to be forward as rpcs. PiperOrigin-RevId: 199370799 Change-Id: I2c876005d98fe55dd126145163bee5a645458ce4
Diffstat (limited to 'pkg/sentry/socket/rpcinet')
-rw-r--r--pkg/sentry/socket/rpcinet/conn/conn.go20
-rw-r--r--pkg/sentry/socket/rpcinet/stack.go90
2 files changed, 45 insertions, 65 deletions
diff --git a/pkg/sentry/socket/rpcinet/conn/conn.go b/pkg/sentry/socket/rpcinet/conn/conn.go
index ea6ec87ed..f4c8489b1 100644
--- a/pkg/sentry/socket/rpcinet/conn/conn.go
+++ b/pkg/sentry/socket/rpcinet/conn/conn.go
@@ -147,6 +147,26 @@ func (c *RPCConnection) RPCReadFile(path string) ([]byte, *syserr.Error) {
return res.(*pb.ReadFileResponse_Data).Data, nil
}
+// RPCWriteFile will execute the WriteFile helper RPC method which avoids the
+// common pattern of open(2), write(2), write(2), close(2) by doing all
+// operations as a single RPC.
+func (c *RPCConnection) RPCWriteFile(path string, data []byte) (int64, *syserr.Error) {
+ req := &pb.SyscallRequest_WriteFile{&pb.WriteFileRequest{
+ Path: path,
+ Content: data,
+ }}
+
+ id, ch := c.NewRequest(pb.SyscallRequest{Args: req}, false /* ignoreResult */)
+ <-ch
+
+ res := c.Request(id).Result.(*pb.SyscallResponse_WriteFile).WriteFile
+ if e := res.ErrorNumber; e != 0 {
+ return int64(res.Written), syserr.FromHost(syscall.Errno(e))
+ }
+
+ return int64(res.Written), nil
+}
+
// Request retrieves the request corresponding to the given request ID.
//
// The channel returned by NewRequest must have been closed before Request can
diff --git a/pkg/sentry/socket/rpcinet/stack.go b/pkg/sentry/socket/rpcinet/stack.go
index 503e0e932..bcb89fb34 100644
--- a/pkg/sentry/socket/rpcinet/stack.go
+++ b/pkg/sentry/socket/rpcinet/stack.go
@@ -16,50 +16,24 @@ package rpcinet
import (
"fmt"
- "strings"
"syscall"
- "gvisor.googlesource.com/gvisor/pkg/sentry/context"
"gvisor.googlesource.com/gvisor/pkg/sentry/inet"
"gvisor.googlesource.com/gvisor/pkg/sentry/socket/hostinet"
"gvisor.googlesource.com/gvisor/pkg/sentry/socket/rpcinet/conn"
"gvisor.googlesource.com/gvisor/pkg/sentry/socket/rpcinet/notifier"
- "gvisor.googlesource.com/gvisor/pkg/sentry/usermem"
- "gvisor.googlesource.com/gvisor/pkg/syserror"
+ "gvisor.googlesource.com/gvisor/pkg/syserr"
"gvisor.googlesource.com/gvisor/pkg/unet"
)
// Stack implements inet.Stack for RPC backed sockets.
type Stack struct {
- // We intentionally do not allow these values to be changed to remain
- // consistent with the other networking stacks.
interfaces map[int32]inet.Interface
interfaceAddrs map[int32][]inet.InterfaceAddr
- supportsIPv6 bool
- tcpRecvBufSize inet.TCPBufferSize
- tcpSendBufSize inet.TCPBufferSize
- tcpSACKEnabled bool
rpcConn *conn.RPCConnection
notifier *notifier.Notifier
}
-func readTCPBufferSizeFile(conn *conn.RPCConnection, filename string) (inet.TCPBufferSize, error) {
- contents, se := conn.RPCReadFile(filename)
- if se != nil {
- return inet.TCPBufferSize{}, fmt.Errorf("failed to read %s: %v", filename, se)
- }
- ioseq := usermem.BytesIOSequence(contents)
- fields := make([]int32, 3)
- if n, err := usermem.CopyInt32StringsInVec(context.Background(), ioseq.IO, ioseq.Addrs, fields, ioseq.Opts); n != ioseq.NumBytes() || err != nil {
- return inet.TCPBufferSize{}, fmt.Errorf("failed to parse %s (%q): got %v after %d/%d bytes", filename, contents, err, n, ioseq.NumBytes())
- }
- return inet.TCPBufferSize{
- Min: int(fields[0]),
- Default: int(fields[1]),
- Max: int(fields[2]),
- }, nil
-}
-
// NewStack returns a Stack containing the current state of the host network
// stack.
func NewStack(fd int32) (*Stack, error) {
@@ -80,31 +54,6 @@ func NewStack(fd int32) (*Stack, error) {
return nil, e
}
- // Load the configuration values from procfs.
- tcpRMem, e := readTCPBufferSizeFile(stack.rpcConn, "/proc/sys/net/ipv4/tcp_rmem")
- if e != nil {
- return nil, e
- }
- stack.tcpRecvBufSize = tcpRMem
-
- tcpWMem, e := readTCPBufferSizeFile(stack.rpcConn, "/proc/sys/net/ipv4/tcp_wmem")
- if e != nil {
- return nil, e
- }
- stack.tcpSendBufSize = tcpWMem
-
- ipv6, se := stack.rpcConn.RPCReadFile("/proc/net/if_inet6")
- if len(string(ipv6)) > 0 {
- stack.supportsIPv6 = true
- }
-
- sackFile := "/proc/sys/net/ipv4/tcp_sack"
- sack, se := stack.rpcConn.RPCReadFile(sackFile)
- if se != nil {
- return nil, fmt.Errorf("failed to read %s: %v", sackFile, se)
- }
- stack.tcpSACKEnabled = strings.TrimSpace(string(sack)) != "0"
-
links, err := stack.DoNetlinkRouteRequest(syscall.RTM_GETLINK)
if err != nil {
return nil, fmt.Errorf("RTM_GETLINK failed: %v", err)
@@ -123,6 +72,21 @@ func NewStack(fd int32) (*Stack, error) {
return stack, nil
}
+// RPCReadFile will execute the ReadFile helper RPC method which avoids the
+// common pattern of open(2), read(2), close(2) by doing all three operations
+// as a single RPC. It will read the entire file or return EFBIG if the file
+// was too large.
+func (s *Stack) RPCReadFile(path string) ([]byte, *syserr.Error) {
+ return s.rpcConn.RPCReadFile(path)
+}
+
+// RPCWriteFile will execute the WriteFile helper RPC method which avoids the
+// common pattern of open(2), write(2), write(2), close(2) by doing all
+// operations as a single RPC.
+func (s *Stack) RPCWriteFile(path string, data []byte) (int64, *syserr.Error) {
+ return s.rpcConn.RPCWriteFile(path, data)
+}
+
// Interfaces implements inet.Stack.Interfaces.
func (s *Stack) Interfaces() map[int32]inet.Interface {
return s.interfaces
@@ -135,41 +99,37 @@ func (s *Stack) InterfaceAddrs() map[int32][]inet.InterfaceAddr {
// SupportsIPv6 implements inet.Stack.SupportsIPv6.
func (s *Stack) SupportsIPv6() bool {
- return s.supportsIPv6
+ panic("rpcinet handles procfs directly this method should not be called")
}
// TCPReceiveBufferSize implements inet.Stack.TCPReceiveBufferSize.
func (s *Stack) TCPReceiveBufferSize() (inet.TCPBufferSize, error) {
- return s.tcpRecvBufSize, nil
+ panic("rpcinet handles procfs directly this method should not be called")
}
// SetTCPReceiveBufferSize implements inet.Stack.SetTCPReceiveBufferSize.
func (s *Stack) SetTCPReceiveBufferSize(size inet.TCPBufferSize) error {
- // To keep all the supported stacks consistent we don't allow changing this
- // value even though it would be possible via an RPC.
- return syserror.EACCES
+ panic("rpcinet handles procfs directly this method should not be called")
+
}
// TCPSendBufferSize implements inet.Stack.TCPSendBufferSize.
func (s *Stack) TCPSendBufferSize() (inet.TCPBufferSize, error) {
- return s.tcpSendBufSize, nil
+ panic("rpcinet handles procfs directly this method should not be called")
+
}
// SetTCPSendBufferSize implements inet.Stack.SetTCPSendBufferSize.
func (s *Stack) SetTCPSendBufferSize(size inet.TCPBufferSize) error {
- // To keep all the supported stacks consistent we don't allow changing this
- // value even though it would be possible via an RPC.
- return syserror.EACCES
+ panic("rpcinet handles procfs directly this method should not be called")
}
// TCPSACKEnabled implements inet.Stack.TCPSACKEnabled.
func (s *Stack) TCPSACKEnabled() (bool, error) {
- return s.tcpSACKEnabled, nil
+ panic("rpcinet handles procfs directly this method should not be called")
}
// SetTCPSACKEnabled implements inet.Stack.SetTCPSACKEnabled.
func (s *Stack) SetTCPSACKEnabled(enabled bool) error {
- // To keep all the supported stacks consistent we don't allow changing this
- // value even though it would be possible via an RPC.
- return syserror.EACCES
+ panic("rpcinet handles procfs directly this method should not be called")
}