From adafc08d7cee594ea94abefbedf67ea315922550 Mon Sep 17 00:00:00 2001 From: Zhaozhong Ni Date: Tue, 4 Dec 2018 14:29:56 -0800 Subject: sentry: save / restore netstack procfs configuration. PiperOrigin-RevId: 224047120 Change-Id: Ia6cb17fa978595cd73857b6178c4bdba401e185e --- pkg/sentry/fs/proc/BUILD | 1 + pkg/sentry/fs/proc/net.go | 4 ++++ pkg/sentry/fs/proc/sys_net.go | 40 +++++++++++++++++++++++-------------- pkg/sentry/fs/proc/sys_net_state.go | 33 ++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 pkg/sentry/fs/proc/sys_net_state.go (limited to 'pkg/sentry') diff --git a/pkg/sentry/fs/proc/BUILD b/pkg/sentry/fs/proc/BUILD index 2d9f07f2f..aff3c3c01 100644 --- a/pkg/sentry/fs/proc/BUILD +++ b/pkg/sentry/fs/proc/BUILD @@ -20,6 +20,7 @@ go_library( "stat.go", "sys.go", "sys_net.go", + "sys_net_state.go", "task.go", "uid_gid_map.go", "uptime.go", diff --git a/pkg/sentry/fs/proc/net.go b/pkg/sentry/fs/proc/net.go index 45f2a1211..3ff60aa5b 100644 --- a/pkg/sentry/fs/proc/net.go +++ b/pkg/sentry/fs/proc/net.go @@ -54,6 +54,8 @@ func (p *proc) newNetDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode { } // ifinet6 implements seqfile.SeqSource for /proc/net/if_inet6. +// +// +stateify savable type ifinet6 struct { s inet.Stack } @@ -108,6 +110,8 @@ func (n *ifinet6) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]s } // netDev implements seqfile.SeqSource for /proc/net/dev. +// +// +stateify savable type netDev struct { s inet.Stack } diff --git a/pkg/sentry/fs/proc/sys_net.go b/pkg/sentry/fs/proc/sys_net.go index 801eb6a1e..b50d43d70 100644 --- a/pkg/sentry/fs/proc/sys_net.go +++ b/pkg/sentry/fs/proc/sys_net.go @@ -36,7 +36,7 @@ const ( // +stateify savable type tcpMem struct { ramfs.Entry - s inet.Stack + s inet.Stack `state:"wait"` size inet.TCPBufferSize dir tcpMemDir } @@ -81,30 +81,33 @@ func (m *tcpMem) DeprecatedPwritev(ctx context.Context, src usermem.IOSequence, buf := []int32{int32(m.size.Min), int32(m.size.Default), int32(m.size.Max)} n, cperr := usermem.CopyInt32StringsInVec(ctx, src.IO, src.Addrs, buf, src.Opts) - size := inet.TCPBufferSize{ + m.size = inet.TCPBufferSize{ Min: int(buf[0]), Default: int(buf[1]), Max: int(buf[2]), } - var err error + if err := m.writeSize(); err != nil { + return n, err + } + return n, cperr +} + +func (m *tcpMem) writeSize() error { switch m.dir { case tcpRMem: - err = m.s.SetTCPReceiveBufferSize(size) + return m.s.SetTCPReceiveBufferSize(m.size) case tcpWMem: - err = m.s.SetTCPSendBufferSize(size) + return m.s.SetTCPSendBufferSize(m.size) default: panic(fmt.Sprintf("unknown tcpMem.dir: %v", m.dir)) } - if err != nil { - return n, err - } - return n, cperr } // +stateify savable type tcpSack struct { ramfs.Entry - s inet.Stack + s inet.Stack `state:"wait"` + enabled *bool } func newTCPSackInode(ctx context.Context, msrc *fs.MountSource, s inet.Stack) *fs.Inode { @@ -124,13 +127,16 @@ func (s *tcpSack) DeprecatedPreadv(ctx context.Context, dst usermem.IOSequence, return 0, io.EOF } - sack, err := s.s.TCPSACKEnabled() - if err != nil { - return 0, err + if s.enabled == nil { + sack, err := s.s.TCPSACKEnabled() + if err != nil { + return 0, err + } + s.enabled = &sack } val := "0\n" - if sack { + if *s.enabled { // Technically, this is not quite compatible with Linux. Linux // stores these as an integer, so if you write "2" into // tcp_sack, you should get 2 back. Tough luck. @@ -157,7 +163,11 @@ func (s *tcpSack) DeprecatedPwritev(ctx context.Context, src usermem.IOSequence, if err != nil { return n, err } - return n, s.s.SetTCPSACKEnabled(v != 0) + if s.enabled == nil { + s.enabled = new(bool) + } + *s.enabled = v != 0 + return n, s.s.SetTCPSACKEnabled(*s.enabled) } func (p *proc) newSysNetCore(ctx context.Context, msrc *fs.MountSource, s inet.Stack) *fs.Inode { diff --git a/pkg/sentry/fs/proc/sys_net_state.go b/pkg/sentry/fs/proc/sys_net_state.go new file mode 100644 index 000000000..7f46776c0 --- /dev/null +++ b/pkg/sentry/fs/proc/sys_net_state.go @@ -0,0 +1,33 @@ +// Copyright 2018 Google LLC +// +// 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 proc + +import "fmt" + +// afterLoad is invoked by stateify. +func (m *tcpMem) afterLoad() { + if err := m.writeSize(); err != nil { + panic(fmt.Sprintf("failed to write previous TCP send / receive buffer sizes [%v]: %v", m.size, err)) + } +} + +// afterLoad is invoked by stateify. +func (s *tcpSack) afterLoad() { + if s.enabled != nil { + if err := s.s.SetTCPSACKEnabled(*s.enabled); err != nil { + panic(fmt.Sprintf("failed to set previous TCP sack configuration [%v]: %v", *s.enabled, err)) + } + } +} -- cgit v1.2.3