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)