github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/syscalls/linux/sys_prctl.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 linux 16 17 import ( 18 "fmt" 19 20 "github.com/SagerNet/gvisor/pkg/abi/linux" 21 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 22 "github.com/SagerNet/gvisor/pkg/marshal/primitive" 23 "github.com/SagerNet/gvisor/pkg/sentry/arch" 24 "github.com/SagerNet/gvisor/pkg/sentry/fs" 25 "github.com/SagerNet/gvisor/pkg/sentry/fsbridge" 26 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 27 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 28 "github.com/SagerNet/gvisor/pkg/sentry/mm" 29 ) 30 31 // Prctl implements linux syscall prctl(2). 32 // It has a list of subfunctions which operate on the process. The arguments are 33 // all based on each subfunction. 34 func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 35 option := args[0].Int() 36 37 switch option { 38 case linux.PR_SET_PDEATHSIG: 39 sig := linux.Signal(args[1].Int()) 40 if sig != 0 && !sig.IsValid() { 41 return 0, nil, linuxerr.EINVAL 42 } 43 t.SetParentDeathSignal(sig) 44 return 0, nil, nil 45 46 case linux.PR_GET_PDEATHSIG: 47 _, err := primitive.CopyInt32Out(t, args[1].Pointer(), int32(t.ParentDeathSignal())) 48 return 0, nil, err 49 50 case linux.PR_GET_DUMPABLE: 51 d := t.MemoryManager().Dumpability() 52 switch d { 53 case mm.NotDumpable: 54 return linux.SUID_DUMP_DISABLE, nil, nil 55 case mm.UserDumpable: 56 return linux.SUID_DUMP_USER, nil, nil 57 case mm.RootDumpable: 58 return linux.SUID_DUMP_ROOT, nil, nil 59 default: 60 panic(fmt.Sprintf("Unknown dumpability %v", d)) 61 } 62 63 case linux.PR_SET_DUMPABLE: 64 var d mm.Dumpability 65 switch args[1].Int() { 66 case linux.SUID_DUMP_DISABLE: 67 d = mm.NotDumpable 68 case linux.SUID_DUMP_USER: 69 d = mm.UserDumpable 70 default: 71 // N.B. Userspace may not pass SUID_DUMP_ROOT. 72 return 0, nil, linuxerr.EINVAL 73 } 74 t.MemoryManager().SetDumpability(d) 75 return 0, nil, nil 76 77 case linux.PR_GET_KEEPCAPS: 78 if t.Credentials().KeepCaps { 79 return 1, nil, nil 80 } 81 82 return 0, nil, nil 83 84 case linux.PR_SET_KEEPCAPS: 85 val := args[1].Int() 86 // prctl(2): arg2 must be either 0 (permitted capabilities are cleared) 87 // or 1 (permitted capabilities are kept). 88 if val == 0 { 89 t.SetKeepCaps(false) 90 } else if val == 1 { 91 t.SetKeepCaps(true) 92 } else { 93 return 0, nil, linuxerr.EINVAL 94 } 95 96 return 0, nil, nil 97 98 case linux.PR_SET_NAME: 99 addr := args[1].Pointer() 100 name, err := t.CopyInString(addr, linux.TASK_COMM_LEN-1) 101 if err != nil && !linuxerr.Equals(linuxerr.ENAMETOOLONG, err) { 102 return 0, nil, err 103 } 104 t.SetName(name) 105 106 case linux.PR_GET_NAME: 107 addr := args[1].Pointer() 108 buf := t.CopyScratchBuffer(linux.TASK_COMM_LEN) 109 len := copy(buf, t.Name()) 110 if len < linux.TASK_COMM_LEN { 111 buf[len] = 0 112 len++ 113 } 114 _, err := t.CopyOutBytes(addr, buf[:len]) 115 if err != nil { 116 return 0, nil, err 117 } 118 119 case linux.PR_SET_MM: 120 if !t.HasCapability(linux.CAP_SYS_RESOURCE) { 121 return 0, nil, linuxerr.EPERM 122 } 123 124 switch args[1].Int() { 125 case linux.PR_SET_MM_EXE_FILE: 126 fd := args[2].Int() 127 128 file := t.GetFile(fd) 129 if file == nil { 130 return 0, nil, linuxerr.EBADF 131 } 132 defer file.DecRef(t) 133 134 // They trying to set exe to a non-file? 135 if !fs.IsFile(file.Dirent.Inode.StableAttr) { 136 return 0, nil, linuxerr.EBADF 137 } 138 139 // Set the underlying executable. 140 t.MemoryManager().SetExecutable(t, fsbridge.NewFSFile(file)) 141 142 case linux.PR_SET_MM_AUXV, 143 linux.PR_SET_MM_START_CODE, 144 linux.PR_SET_MM_END_CODE, 145 linux.PR_SET_MM_START_DATA, 146 linux.PR_SET_MM_END_DATA, 147 linux.PR_SET_MM_START_STACK, 148 linux.PR_SET_MM_START_BRK, 149 linux.PR_SET_MM_BRK, 150 linux.PR_SET_MM_ARG_START, 151 linux.PR_SET_MM_ARG_END, 152 linux.PR_SET_MM_ENV_START, 153 linux.PR_SET_MM_ENV_END: 154 155 t.Kernel().EmitUnimplementedEvent(t) 156 fallthrough 157 default: 158 return 0, nil, linuxerr.EINVAL 159 } 160 161 case linux.PR_SET_NO_NEW_PRIVS: 162 if args[1].Int() != 1 || args[2].Int() != 0 || args[3].Int() != 0 || args[4].Int() != 0 { 163 return 0, nil, linuxerr.EINVAL 164 } 165 // PR_SET_NO_NEW_PRIVS is assumed to always be set. 166 // See kernel.Task.updateCredsForExecLocked. 167 return 0, nil, nil 168 169 case linux.PR_GET_NO_NEW_PRIVS: 170 if args[1].Int() != 0 || args[2].Int() != 0 || args[3].Int() != 0 || args[4].Int() != 0 { 171 return 0, nil, linuxerr.EINVAL 172 } 173 return 1, nil, nil 174 175 case linux.PR_SET_PTRACER: 176 pid := args[1].Int() 177 switch pid { 178 case 0: 179 t.ClearYAMAException() 180 return 0, nil, nil 181 case linux.PR_SET_PTRACER_ANY: 182 t.SetYAMAException(nil) 183 return 0, nil, nil 184 default: 185 tracer := t.PIDNamespace().TaskWithID(kernel.ThreadID(pid)) 186 if tracer == nil { 187 return 0, nil, linuxerr.EINVAL 188 } 189 t.SetYAMAException(tracer) 190 return 0, nil, nil 191 } 192 193 case linux.PR_SET_SECCOMP: 194 if args[1].Int() != linux.SECCOMP_MODE_FILTER { 195 // Unsupported mode. 196 return 0, nil, linuxerr.EINVAL 197 } 198 199 return 0, nil, seccomp(t, linux.SECCOMP_SET_MODE_FILTER, 0, args[2].Pointer()) 200 201 case linux.PR_GET_SECCOMP: 202 return uintptr(t.SeccompMode()), nil, nil 203 204 case linux.PR_CAPBSET_READ: 205 cp := linux.Capability(args[1].Uint64()) 206 if !cp.Ok() { 207 return 0, nil, linuxerr.EINVAL 208 } 209 var rv uintptr 210 if auth.CapabilitySetOf(cp)&t.Credentials().BoundingCaps != 0 { 211 rv = 1 212 } 213 return rv, nil, nil 214 215 case linux.PR_CAPBSET_DROP: 216 cp := linux.Capability(args[1].Uint64()) 217 if !cp.Ok() { 218 return 0, nil, linuxerr.EINVAL 219 } 220 return 0, nil, t.DropBoundingCapability(cp) 221 222 case linux.PR_GET_TIMING, 223 linux.PR_SET_TIMING, 224 linux.PR_GET_TSC, 225 linux.PR_SET_TSC, 226 linux.PR_TASK_PERF_EVENTS_DISABLE, 227 linux.PR_TASK_PERF_EVENTS_ENABLE, 228 linux.PR_GET_TIMERSLACK, 229 linux.PR_SET_TIMERSLACK, 230 linux.PR_MCE_KILL, 231 linux.PR_MCE_KILL_GET, 232 linux.PR_GET_TID_ADDRESS, 233 linux.PR_SET_CHILD_SUBREAPER, 234 linux.PR_GET_CHILD_SUBREAPER, 235 linux.PR_GET_THP_DISABLE, 236 linux.PR_SET_THP_DISABLE, 237 linux.PR_MPX_ENABLE_MANAGEMENT, 238 linux.PR_MPX_DISABLE_MANAGEMENT: 239 240 t.Kernel().EmitUnimplementedEvent(t) 241 fallthrough 242 default: 243 return 0, nil, linuxerr.EINVAL 244 } 245 246 return 0, nil, nil 247 }