summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fsimpl/proc
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fsimpl/proc')
-rw-r--r--pkg/sentry/fsimpl/proc/proc_state_autogen.go27
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_sys.go49
2 files changed, 75 insertions, 1 deletions
diff --git a/pkg/sentry/fsimpl/proc/proc_state_autogen.go b/pkg/sentry/fsimpl/proc/proc_state_autogen.go
index e297a6257..eca33249c 100644
--- a/pkg/sentry/fsimpl/proc/proc_state_autogen.go
+++ b/pkg/sentry/fsimpl/proc/proc_state_autogen.go
@@ -1173,6 +1173,32 @@ func (x *tcpSackData) StateLoad(m state.Source) {
m.Load(2, &x.enabled)
}
+func (x *tcpRecoveryData) StateTypeName() string {
+ return "pkg/sentry/fsimpl/proc.tcpRecoveryData"
+}
+
+func (x *tcpRecoveryData) StateFields() []string {
+ return []string{
+ "DynamicBytesFile",
+ "stack",
+ }
+}
+
+func (x *tcpRecoveryData) beforeSave() {}
+
+func (x *tcpRecoveryData) StateSave(m state.Sink) {
+ x.beforeSave()
+ m.Save(0, &x.DynamicBytesFile)
+ m.Save(1, &x.stack)
+}
+
+func (x *tcpRecoveryData) afterLoad() {}
+
+func (x *tcpRecoveryData) StateLoad(m state.Source) {
+ m.Load(0, &x.DynamicBytesFile)
+ m.LoadWait(1, &x.stack)
+}
+
func init() {
state.Register((*FilesystemType)(nil))
state.Register((*subtasksInode)(nil))
@@ -1215,4 +1241,5 @@ func init() {
state.Register((*mmapMinAddrData)(nil))
state.Register((*hostnameData)(nil))
state.Register((*tcpSackData)(nil))
+ state.Register((*tcpRecoveryData)(nil))
}
diff --git a/pkg/sentry/fsimpl/proc/tasks_sys.go b/pkg/sentry/fsimpl/proc/tasks_sys.go
index 6dac2afa4..b71778128 100644
--- a/pkg/sentry/fsimpl/proc/tasks_sys.go
+++ b/pkg/sentry/fsimpl/proc/tasks_sys.go
@@ -55,7 +55,8 @@ func (fs *filesystem) newSysNetDir(root *auth.Credentials, k *kernel.Kernel) *ke
if stack := k.RootNetworkNamespace().Stack(); stack != nil {
contents = map[string]*kernfs.Dentry{
"ipv4": kernfs.NewStaticDir(root, linux.UNNAMED_MAJOR, fs.devMinor, fs.NextIno(), 0555, map[string]*kernfs.Dentry{
- "tcp_sack": fs.newDentry(root, fs.NextIno(), 0644, &tcpSackData{stack: stack}),
+ "tcp_recovery": fs.newDentry(root, fs.NextIno(), 0644, &tcpRecoveryData{stack: stack}),
+ "tcp_sack": fs.newDentry(root, fs.NextIno(), 0644, &tcpSackData{stack: stack}),
// The following files are simple stubs until they are implemented in
// netstack, most of these files are configuration related. We use the
@@ -207,3 +208,49 @@ func (d *tcpSackData) Write(ctx context.Context, src usermem.IOSequence, offset
*d.enabled = v != 0
return n, d.stack.SetTCPSACKEnabled(*d.enabled)
}
+
+// tcpRecoveryData implements vfs.WritableDynamicBytesSource for
+// /proc/sys/net/ipv4/tcp_recovery.
+//
+// +stateify savable
+type tcpRecoveryData struct {
+ kernfs.DynamicBytesFile
+
+ stack inet.Stack `state:"wait"`
+}
+
+var _ vfs.WritableDynamicBytesSource = (*tcpRecoveryData)(nil)
+
+// Generate implements vfs.DynamicBytesSource.
+func (d *tcpRecoveryData) Generate(ctx context.Context, buf *bytes.Buffer) error {
+ recovery, err := d.stack.TCPRecovery()
+ if err != nil {
+ return err
+ }
+
+ buf.WriteString(fmt.Sprintf("%d\n", recovery))
+ return nil
+}
+
+func (d *tcpRecoveryData) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
+ if offset != 0 {
+ // No need to handle partial writes thus far.
+ return 0, syserror.EINVAL
+ }
+ if src.NumBytes() == 0 {
+ return 0, nil
+ }
+
+ // Limit the amount of memory allocated.
+ src = src.TakeFirst(usermem.PageSize - 1)
+
+ var v int32
+ n, err := usermem.CopyInt32StringInVec(ctx, src.IO, src.Addrs, &v, src.Opts)
+ if err != nil {
+ return 0, err
+ }
+ if err := d.stack.SetTCPRecovery(inet.TCPLossRecovery(v)); err != nil {
+ return 0, err
+ }
+ return n, nil
+}