github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fs/proc/sys.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package proc
    16  
    17  import (
    18  	"fmt"
    19  	"io"
    20  	"strconv"
    21  
    22  	"github.com/SagerNet/gvisor/pkg/abi/linux"
    23  	"github.com/SagerNet/gvisor/pkg/context"
    24  	"github.com/SagerNet/gvisor/pkg/sentry/fs"
    25  	"github.com/SagerNet/gvisor/pkg/sentry/fs/fsutil"
    26  	"github.com/SagerNet/gvisor/pkg/sentry/fs/proc/seqfile"
    27  	"github.com/SagerNet/gvisor/pkg/sentry/fs/ramfs"
    28  	"github.com/SagerNet/gvisor/pkg/sentry/kernel"
    29  	"github.com/SagerNet/gvisor/pkg/usermem"
    30  	"github.com/SagerNet/gvisor/pkg/waiter"
    31  )
    32  
    33  // LINT.IfChange
    34  
    35  // mmapMinAddrData backs /proc/sys/vm/mmap_min_addr.
    36  //
    37  // +stateify savable
    38  type mmapMinAddrData struct {
    39  	k *kernel.Kernel
    40  }
    41  
    42  // NeedsUpdate implements seqfile.SeqSource.NeedsUpdate.
    43  func (*mmapMinAddrData) NeedsUpdate(generation int64) bool {
    44  	return true
    45  }
    46  
    47  // ReadSeqFileData implements seqfile.SeqSource.ReadSeqFileData.
    48  func (d *mmapMinAddrData) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]seqfile.SeqData, int64) {
    49  	if h != nil {
    50  		return nil, 0
    51  	}
    52  	return []seqfile.SeqData{
    53  		{
    54  			Buf:    []byte(fmt.Sprintf("%d\n", d.k.Platform.MinUserAddress())),
    55  			Handle: (*mmapMinAddrData)(nil),
    56  		},
    57  	}, 0
    58  }
    59  
    60  // +stateify savable
    61  type overcommitMemory struct{}
    62  
    63  func (*overcommitMemory) NeedsUpdate(generation int64) bool {
    64  	return true
    65  }
    66  
    67  // ReadSeqFileData implements seqfile.SeqSource.
    68  func (*overcommitMemory) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]seqfile.SeqData, int64) {
    69  	if h != nil {
    70  		return nil, 0
    71  	}
    72  	return []seqfile.SeqData{
    73  		{
    74  			Buf:    []byte("0\n"),
    75  			Handle: (*overcommitMemory)(nil),
    76  		},
    77  	}, 0
    78  }
    79  
    80  // +stateify savable
    81  type maxMapCount struct{}
    82  
    83  // NeedsUpdate implements seqfile.SeqSource.
    84  func (*maxMapCount) NeedsUpdate(int64) bool {
    85  	return true
    86  }
    87  
    88  // ReadSeqFileData implements seqfile.SeqSource.
    89  func (*maxMapCount) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]seqfile.SeqData, int64) {
    90  	if h != nil {
    91  		return nil, 0
    92  	}
    93  	return []seqfile.SeqData{
    94  		{
    95  			Buf:    []byte("2147483647\n"),
    96  			Handle: (*maxMapCount)(nil),
    97  		},
    98  	}, 0
    99  }
   100  
   101  func (p *proc) newKernelDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
   102  	h := hostname{
   103  		SimpleFileInode: *fsutil.NewSimpleFileInode(ctx, fs.RootOwner, fs.FilePermsFromMode(0444), linux.PROC_SUPER_MAGIC),
   104  	}
   105  
   106  	children := map[string]*fs.Inode{
   107  		"hostname": newProcInode(ctx, &h, msrc, fs.SpecialFile, nil),
   108  		"sem":      newStaticProcInode(ctx, msrc, []byte(fmt.Sprintf("%d\t%d\t%d\t%d\n", linux.SEMMSL, linux.SEMMNS, linux.SEMOPM, linux.SEMMNI))),
   109  		"shmall":   newStaticProcInode(ctx, msrc, []byte(strconv.FormatUint(linux.SHMALL, 10))),
   110  		"shmmax":   newStaticProcInode(ctx, msrc, []byte(strconv.FormatUint(linux.SHMMAX, 10))),
   111  		"shmmni":   newStaticProcInode(ctx, msrc, []byte(strconv.FormatUint(linux.SHMMNI, 10))),
   112  	}
   113  
   114  	d := ramfs.NewDir(ctx, children, fs.RootOwner, fs.FilePermsFromMode(0555))
   115  	return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil)
   116  }
   117  
   118  func (p *proc) newVMDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
   119  	children := map[string]*fs.Inode{
   120  		"max_map_count":     seqfile.NewSeqFileInode(ctx, &maxMapCount{}, msrc),
   121  		"mmap_min_addr":     seqfile.NewSeqFileInode(ctx, &mmapMinAddrData{p.k}, msrc),
   122  		"overcommit_memory": seqfile.NewSeqFileInode(ctx, &overcommitMemory{}, msrc),
   123  	}
   124  	d := ramfs.NewDir(ctx, children, fs.RootOwner, fs.FilePermsFromMode(0555))
   125  	return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil)
   126  }
   127  
   128  func (p *proc) newSysDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
   129  	children := map[string]*fs.Inode{
   130  		"kernel": p.newKernelDir(ctx, msrc),
   131  		"net":    p.newSysNetDir(ctx, msrc),
   132  		"vm":     p.newVMDir(ctx, msrc),
   133  	}
   134  
   135  	d := ramfs.NewDir(ctx, children, fs.RootOwner, fs.FilePermsFromMode(0555))
   136  	return newProcInode(ctx, d, msrc, fs.SpecialDirectory, nil)
   137  }
   138  
   139  // hostname is the inode for a file containing the system hostname.
   140  //
   141  // +stateify savable
   142  type hostname struct {
   143  	fsutil.SimpleFileInode
   144  }
   145  
   146  // GetFile implements fs.InodeOperations.GetFile.
   147  func (h *hostname) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
   148  	return fs.NewFile(ctx, d, flags, &hostnameFile{}), nil
   149  }
   150  
   151  var _ fs.InodeOperations = (*hostname)(nil)
   152  
   153  // +stateify savable
   154  type hostnameFile struct {
   155  	fsutil.FileNoIoctl              `state:"nosave"`
   156  	fsutil.FileNoMMap               `state:"nosave"`
   157  	fsutil.FileNoSeek               `state:"nosave"`
   158  	fsutil.FileNoopFlush            `state:"nosave"`
   159  	fsutil.FileNoopFsync            `state:"nosave"`
   160  	fsutil.FileNoopRelease          `state:"nosave"`
   161  	fsutil.FileNotDirReaddir        `state:"nosave"`
   162  	fsutil.FileNoWrite              `state:"nosave"`
   163  	fsutil.FileNoSplice             `state:"nosave"`
   164  	fsutil.FileUseInodeUnstableAttr `state:"nosave"`
   165  	waiter.AlwaysReady              `state:"nosave"`
   166  }
   167  
   168  // Read implements fs.FileOperations.Read.
   169  func (hf *hostnameFile) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
   170  	utsns := kernel.UTSNamespaceFromContext(ctx)
   171  	contents := []byte(utsns.HostName() + "\n")
   172  	if offset >= int64(len(contents)) {
   173  		return 0, io.EOF
   174  	}
   175  	n, err := dst.CopyOut(ctx, contents[offset:])
   176  	return int64(n), err
   177  
   178  }
   179  
   180  var _ fs.FileOperations = (*hostnameFile)(nil)
   181  
   182  // LINT.ThenChange(../../fsimpl/proc/tasks_sys.go)