diff options
author | Brian Geffon <bgeffon@google.com> | 2018-06-05 15:43:55 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-06-05 15:45:35 -0700 |
commit | ff7b4a156f95a587b5df4de89a22c200fceabb96 (patch) | |
tree | dbf2206d66db40f71c1d92784cbc60126a59e1d3 /pkg/sentry/socket | |
parent | 343020ca275298fe9ea3320628454cad5f0052aa (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')
-rw-r--r-- | pkg/sentry/socket/rpcinet/conn/conn.go | 20 | ||||
-rw-r--r-- | pkg/sentry/socket/rpcinet/stack.go | 90 |
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") } |