github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/limits/linux.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 limits 16 17 import ( 18 "fmt" 19 20 "github.com/SagerNet/gvisor/pkg/abi/linux" 21 ) 22 23 // FromLinuxResource maps linux resources to sentry LimitTypes. 24 var FromLinuxResource = map[int]LimitType{ 25 linux.RLIMIT_CPU: CPU, 26 linux.RLIMIT_FSIZE: FileSize, 27 linux.RLIMIT_DATA: Data, 28 linux.RLIMIT_STACK: Stack, 29 linux.RLIMIT_CORE: Core, 30 linux.RLIMIT_RSS: Rss, 31 linux.RLIMIT_NPROC: ProcessCount, 32 linux.RLIMIT_NOFILE: NumberOfFiles, 33 linux.RLIMIT_MEMLOCK: MemoryLocked, 34 linux.RLIMIT_AS: AS, 35 linux.RLIMIT_LOCKS: Locks, 36 linux.RLIMIT_SIGPENDING: SignalsPending, 37 linux.RLIMIT_MSGQUEUE: MessageQueueBytes, 38 linux.RLIMIT_NICE: Nice, 39 linux.RLIMIT_RTPRIO: RealTimePriority, 40 linux.RLIMIT_RTTIME: Rttime, 41 } 42 43 // FromLinux maps linux rlimit values to sentry Limits, being careful to handle 44 // infinities. 45 func FromLinux(rl uint64) uint64 { 46 if rl == linux.RLimInfinity { 47 return Infinity 48 } 49 return rl 50 } 51 52 // ToLinux maps sentry Limits to linux rlimit values, being careful to handle 53 // infinities. 54 func ToLinux(l uint64) uint64 { 55 if l == Infinity { 56 return linux.RLimInfinity 57 } 58 return l 59 } 60 61 // NewLinuxLimitSet returns a LimitSet whose values match the default rlimits 62 // in Linux. 63 func NewLinuxLimitSet() (*LimitSet, error) { 64 ls := NewLimitSet() 65 for rlt, rl := range linux.InitRLimits { 66 lt, ok := FromLinuxResource[rlt] 67 if !ok { 68 return nil, fmt.Errorf("unknown rlimit type %v", rlt) 69 } 70 ls.SetUnchecked(lt, Limit{ 71 Cur: FromLinux(rl.Cur), 72 Max: FromLinux(rl.Max), 73 }) 74 } 75 return ls, nil 76 } 77 78 // NewLinuxDistroLimitSet returns a new LimitSet whose values are typical 79 // for a booted Linux distro. 80 // 81 // Many Linux init systems adjust the default Linux limits to values more 82 // expected by the rest of the userspace. NewLinuxDistroLimitSet returns a 83 // LimitSet with sensible defaults for applications that aren't starting 84 // their own init system. 85 func NewLinuxDistroLimitSet() (*LimitSet, error) { 86 ls, err := NewLinuxLimitSet() 87 if err != nil { 88 return nil, err 89 } 90 91 // Adjust ProcessCount to a lower value because GNU bash allocates 16 92 // bytes per proc and OOMs if this number is set too high. Value was 93 // picked arbitrarily. 94 // 95 // 1,048,576 ought to be enough for anyone. 96 l := ls.Get(ProcessCount) 97 l.Cur = 1 << 20 98 ls.Set(ProcessCount, l, true /* privileged */) 99 return ls, nil 100 }