github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/syscalls/linux/sys_signal.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 "math" 19 "time" 20 21 "github.com/SagerNet/gvisor/pkg/abi/linux" 22 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 23 "github.com/SagerNet/gvisor/pkg/hostarch" 24 "github.com/SagerNet/gvisor/pkg/sentry/arch" 25 "github.com/SagerNet/gvisor/pkg/sentry/fs" 26 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 27 "github.com/SagerNet/gvisor/pkg/sentry/kernel/signalfd" 28 "github.com/SagerNet/gvisor/pkg/syserror" 29 ) 30 31 // "For a process to have permission to send a signal it must 32 // - either be privileged (CAP_KILL), or 33 // - the real or effective user ID of the sending process must be equal to the 34 // real or saved set-user-ID of the target process. 35 // 36 // In the case of SIGCONT it suffices when the sending and receiving processes 37 // belong to the same session." - kill(2) 38 // 39 // Equivalent to kernel/signal.c:check_kill_permission. 40 func mayKill(t *kernel.Task, target *kernel.Task, sig linux.Signal) bool { 41 // kernel/signal.c:check_kill_permission also allows a signal if the 42 // sending and receiving tasks share a thread group, which is not 43 // mentioned in kill(2) since kill does not allow task-level 44 // granularity in signal sending. 45 if t.ThreadGroup() == target.ThreadGroup() { 46 return true 47 } 48 49 if t.HasCapabilityIn(linux.CAP_KILL, target.UserNamespace()) { 50 return true 51 } 52 53 creds := t.Credentials() 54 tcreds := target.Credentials() 55 if creds.EffectiveKUID == tcreds.SavedKUID || 56 creds.EffectiveKUID == tcreds.RealKUID || 57 creds.RealKUID == tcreds.SavedKUID || 58 creds.RealKUID == tcreds.RealKUID { 59 return true 60 } 61 62 if sig == linux.SIGCONT && target.ThreadGroup().Session() == t.ThreadGroup().Session() { 63 return true 64 } 65 return false 66 } 67 68 // Kill implements linux syscall kill(2). 69 func Kill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 70 pid := kernel.ThreadID(args[0].Int()) 71 sig := linux.Signal(args[1].Int()) 72 73 switch { 74 case pid > 0: 75 // "If pid is positive, then signal sig is sent to the process with the 76 // ID specified by pid." - kill(2) 77 // This loops to handle races with execve where target dies between 78 // TaskWithID and SendGroupSignal. Compare Linux's 79 // kernel/signal.c:kill_pid_info(). 80 for { 81 target := t.PIDNamespace().TaskWithID(pid) 82 if target == nil { 83 return 0, nil, syserror.ESRCH 84 } 85 if !mayKill(t, target, sig) { 86 return 0, nil, linuxerr.EPERM 87 } 88 info := &linux.SignalInfo{ 89 Signo: int32(sig), 90 Code: linux.SI_USER, 91 } 92 info.SetPID(int32(target.PIDNamespace().IDOfTask(t))) 93 info.SetUID(int32(t.Credentials().RealKUID.In(target.UserNamespace()).OrOverflow())) 94 if err := target.SendGroupSignal(info); !linuxerr.Equals(linuxerr.ESRCH, err) { 95 return 0, nil, err 96 } 97 } 98 case pid == -1: 99 // "If pid equals -1, then sig is sent to every process for which the 100 // calling process has permission to send signals, except for process 1 101 // (init), but see below. ... POSIX.1-2001 requires that kill(-1,sig) 102 // send sig to all processes that the calling process may send signals 103 // to, except possibly for some implementation-defined system 104 // processes. Linux allows a process to signal itself, but on Linux the 105 // call kill(-1,sig) does not signal the calling process." 106 var ( 107 lastErr error 108 delivered int 109 ) 110 for _, tg := range t.PIDNamespace().ThreadGroups() { 111 if tg == t.ThreadGroup() { 112 continue 113 } 114 if t.PIDNamespace().IDOfThreadGroup(tg) == kernel.InitTID { 115 continue 116 } 117 118 // If pid == -1, the returned error is the last non-EPERM error 119 // from any call to group_send_sig_info. 120 if !mayKill(t, tg.Leader(), sig) { 121 continue 122 } 123 // Here and below, whether or not kill returns an error may 124 // depend on the iteration order. We at least implement the 125 // semantics documented by the man page: "On success (at least 126 // one signal was sent), zero is returned." 127 info := &linux.SignalInfo{ 128 Signo: int32(sig), 129 Code: linux.SI_USER, 130 } 131 info.SetPID(int32(tg.PIDNamespace().IDOfTask(t))) 132 info.SetUID(int32(t.Credentials().RealKUID.In(tg.Leader().UserNamespace()).OrOverflow())) 133 err := tg.SendSignal(info) 134 if linuxerr.Equals(linuxerr.ESRCH, err) { 135 // ESRCH is ignored because it means the task 136 // exited while we were iterating. This is a 137 // race which would not normally exist on 138 // Linux, so we suppress it. 139 continue 140 } 141 delivered++ 142 if err != nil { 143 lastErr = err 144 } 145 } 146 if delivered > 0 { 147 return 0, nil, lastErr 148 } 149 return 0, nil, syserror.ESRCH 150 default: 151 // "If pid equals 0, then sig is sent to every process in the process 152 // group of the calling process." 153 // 154 // "If pid is less than -1, then sig is sent to every process 155 // in the process group whose ID is -pid." 156 pgid := kernel.ProcessGroupID(-pid) 157 if pgid == 0 { 158 pgid = t.PIDNamespace().IDOfProcessGroup(t.ThreadGroup().ProcessGroup()) 159 } 160 161 // If pid != -1 (i.e. signalling a process group), the returned error 162 // is the last error from any call to group_send_sig_info. 163 lastErr := syserror.ESRCH 164 for _, tg := range t.PIDNamespace().ThreadGroups() { 165 if t.PIDNamespace().IDOfProcessGroup(tg.ProcessGroup()) == pgid { 166 if !mayKill(t, tg.Leader(), sig) { 167 lastErr = linuxerr.EPERM 168 continue 169 } 170 171 info := &linux.SignalInfo{ 172 Signo: int32(sig), 173 Code: linux.SI_USER, 174 } 175 info.SetPID(int32(tg.PIDNamespace().IDOfTask(t))) 176 info.SetUID(int32(t.Credentials().RealKUID.In(tg.Leader().UserNamespace()).OrOverflow())) 177 // See note above regarding ESRCH race above. 178 if err := tg.SendSignal(info); !linuxerr.Equals(linuxerr.ESRCH, err) { 179 lastErr = err 180 } 181 } 182 } 183 184 return 0, nil, lastErr 185 } 186 } 187 188 func tkillSigInfo(sender, receiver *kernel.Task, sig linux.Signal) *linux.SignalInfo { 189 info := &linux.SignalInfo{ 190 Signo: int32(sig), 191 Code: linux.SI_TKILL, 192 } 193 info.SetPID(int32(receiver.PIDNamespace().IDOfThreadGroup(sender.ThreadGroup()))) 194 info.SetUID(int32(sender.Credentials().RealKUID.In(receiver.UserNamespace()).OrOverflow())) 195 return info 196 } 197 198 // Tkill implements linux syscall tkill(2). 199 func Tkill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 200 tid := kernel.ThreadID(args[0].Int()) 201 sig := linux.Signal(args[1].Int()) 202 203 // N.B. Inconsistent with man page, linux actually rejects calls with 204 // tid <=0 by EINVAL. This isn't the same for all signal calls. 205 if tid <= 0 { 206 return 0, nil, linuxerr.EINVAL 207 } 208 209 target := t.PIDNamespace().TaskWithID(tid) 210 if target == nil { 211 return 0, nil, syserror.ESRCH 212 } 213 214 if !mayKill(t, target, sig) { 215 return 0, nil, linuxerr.EPERM 216 } 217 return 0, nil, target.SendSignal(tkillSigInfo(t, target, sig)) 218 } 219 220 // Tgkill implements linux syscall tgkill(2). 221 func Tgkill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 222 tgid := kernel.ThreadID(args[0].Int()) 223 tid := kernel.ThreadID(args[1].Int()) 224 sig := linux.Signal(args[2].Int()) 225 226 // N.B. Inconsistent with man page, linux actually rejects calls with 227 // tgid/tid <=0 by EINVAL. This isn't the same for all signal calls. 228 if tgid <= 0 || tid <= 0 { 229 return 0, nil, linuxerr.EINVAL 230 } 231 232 targetTG := t.PIDNamespace().ThreadGroupWithID(tgid) 233 target := t.PIDNamespace().TaskWithID(tid) 234 if targetTG == nil || target == nil || target.ThreadGroup() != targetTG { 235 return 0, nil, syserror.ESRCH 236 } 237 238 if !mayKill(t, target, sig) { 239 return 0, nil, linuxerr.EPERM 240 } 241 return 0, nil, target.SendSignal(tkillSigInfo(t, target, sig)) 242 } 243 244 // RtSigaction implements linux syscall rt_sigaction(2). 245 func RtSigaction(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 246 sig := linux.Signal(args[0].Int()) 247 newactarg := args[1].Pointer() 248 oldactarg := args[2].Pointer() 249 sigsetsize := args[3].SizeT() 250 251 if sigsetsize != linux.SignalSetSize { 252 return 0, nil, linuxerr.EINVAL 253 } 254 255 var newactptr *linux.SigAction 256 if newactarg != 0 { 257 var newact linux.SigAction 258 if _, err := newact.CopyIn(t, newactarg); err != nil { 259 return 0, nil, err 260 } 261 newactptr = &newact 262 } 263 oldact, err := t.ThreadGroup().SetSigAction(sig, newactptr) 264 if err != nil { 265 return 0, nil, err 266 } 267 if oldactarg != 0 { 268 if _, err := oldact.CopyOut(t, oldactarg); err != nil { 269 return 0, nil, err 270 } 271 } 272 return 0, nil, nil 273 } 274 275 // Sigreturn implements linux syscall sigreturn(2). 276 func Sigreturn(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 277 ctrl, err := t.SignalReturn(false) 278 return 0, ctrl, err 279 } 280 281 // RtSigreturn implements linux syscall rt_sigreturn(2). 282 func RtSigreturn(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 283 ctrl, err := t.SignalReturn(true) 284 return 0, ctrl, err 285 } 286 287 // RtSigprocmask implements linux syscall rt_sigprocmask(2). 288 func RtSigprocmask(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 289 how := args[0].Int() 290 setaddr := args[1].Pointer() 291 oldaddr := args[2].Pointer() 292 sigsetsize := args[3].SizeT() 293 294 if sigsetsize != linux.SignalSetSize { 295 return 0, nil, linuxerr.EINVAL 296 } 297 oldmask := t.SignalMask() 298 if setaddr != 0 { 299 mask, err := CopyInSigSet(t, setaddr, sigsetsize) 300 if err != nil { 301 return 0, nil, err 302 } 303 304 switch how { 305 case linux.SIG_BLOCK: 306 t.SetSignalMask(oldmask | mask) 307 case linux.SIG_UNBLOCK: 308 t.SetSignalMask(oldmask &^ mask) 309 case linux.SIG_SETMASK: 310 t.SetSignalMask(mask) 311 default: 312 return 0, nil, linuxerr.EINVAL 313 } 314 } 315 if oldaddr != 0 { 316 return 0, nil, copyOutSigSet(t, oldaddr, oldmask) 317 } 318 319 return 0, nil, nil 320 } 321 322 // Sigaltstack implements linux syscall sigaltstack(2). 323 func Sigaltstack(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 324 setaddr := args[0].Pointer() 325 oldaddr := args[1].Pointer() 326 327 alt := t.SignalStack() 328 if oldaddr != 0 { 329 if _, err := alt.CopyOut(t, oldaddr); err != nil { 330 return 0, nil, err 331 } 332 } 333 if setaddr != 0 { 334 if _, err := alt.CopyIn(t, setaddr); err != nil { 335 return 0, nil, err 336 } 337 // The signal stack cannot be changed if the task is currently 338 // on the stack. This is enforced at the lowest level because 339 // these semantics apply to changing the signal stack via a 340 // ucontext during a signal handler. 341 if !t.SetSignalStack(alt) { 342 return 0, nil, linuxerr.EPERM 343 } 344 } 345 346 return 0, nil, nil 347 } 348 349 // Pause implements linux syscall pause(2). 350 func Pause(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 351 return 0, nil, syserror.ConvertIntr(t.Block(nil), syserror.ERESTARTNOHAND) 352 } 353 354 // RtSigpending implements linux syscall rt_sigpending(2). 355 func RtSigpending(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 356 addr := args[0].Pointer() 357 pending := t.PendingSignals() 358 _, err := pending.CopyOut(t, addr) 359 return 0, nil, err 360 } 361 362 // RtSigtimedwait implements linux syscall rt_sigtimedwait(2). 363 func RtSigtimedwait(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 364 sigset := args[0].Pointer() 365 siginfo := args[1].Pointer() 366 timespec := args[2].Pointer() 367 sigsetsize := args[3].SizeT() 368 369 mask, err := CopyInSigSet(t, sigset, sigsetsize) 370 if err != nil { 371 return 0, nil, err 372 } 373 374 var timeout time.Duration 375 if timespec != 0 { 376 d, err := copyTimespecIn(t, timespec) 377 if err != nil { 378 return 0, nil, err 379 } 380 if !d.Valid() { 381 return 0, nil, linuxerr.EINVAL 382 } 383 timeout = time.Duration(d.ToNsecCapped()) 384 } else { 385 timeout = time.Duration(math.MaxInt64) 386 } 387 388 si, err := t.Sigtimedwait(mask, timeout) 389 if err != nil { 390 return 0, nil, err 391 } 392 393 if siginfo != 0 { 394 si.FixSignalCodeForUser() 395 if _, err := si.CopyOut(t, siginfo); err != nil { 396 return 0, nil, err 397 } 398 } 399 return uintptr(si.Signo), nil, nil 400 } 401 402 // RtSigqueueinfo implements linux syscall rt_sigqueueinfo(2). 403 func RtSigqueueinfo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 404 pid := kernel.ThreadID(args[0].Int()) 405 sig := linux.Signal(args[1].Int()) 406 infoAddr := args[2].Pointer() 407 408 // Copy in the info. 409 // 410 // We must ensure that the Signo is set (Linux overrides this in the 411 // same way), and that the code is in the allowed set. This same logic 412 // appears below in RtSigtgqueueinfo and should be kept in sync. 413 var info linux.SignalInfo 414 if _, err := info.CopyIn(t, infoAddr); err != nil { 415 return 0, nil, err 416 } 417 info.Signo = int32(sig) 418 419 // This must loop to handle the race with execve described in Kill. 420 for { 421 // Deliver to the given task's thread group. 422 target := t.PIDNamespace().TaskWithID(pid) 423 if target == nil { 424 return 0, nil, syserror.ESRCH 425 } 426 427 // If the sender is not the receiver, it can't use si_codes used by the 428 // kernel or SI_TKILL. 429 if (info.Code >= 0 || info.Code == linux.SI_TKILL) && target != t { 430 return 0, nil, linuxerr.EPERM 431 } 432 433 if !mayKill(t, target, sig) { 434 return 0, nil, linuxerr.EPERM 435 } 436 437 if err := target.SendGroupSignal(&info); !linuxerr.Equals(linuxerr.ESRCH, err) { 438 return 0, nil, err 439 } 440 } 441 } 442 443 // RtTgsigqueueinfo implements linux syscall rt_tgsigqueueinfo(2). 444 func RtTgsigqueueinfo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 445 tgid := kernel.ThreadID(args[0].Int()) 446 tid := kernel.ThreadID(args[1].Int()) 447 sig := linux.Signal(args[2].Int()) 448 infoAddr := args[3].Pointer() 449 450 // N.B. Inconsistent with man page, linux actually rejects calls with 451 // tgid/tid <=0 by EINVAL. This isn't the same for all signal calls. 452 if tgid <= 0 || tid <= 0 { 453 return 0, nil, linuxerr.EINVAL 454 } 455 456 // Copy in the info. See RtSigqueueinfo above. 457 var info linux.SignalInfo 458 if _, err := info.CopyIn(t, infoAddr); err != nil { 459 return 0, nil, err 460 } 461 info.Signo = int32(sig) 462 463 // Deliver to the given task. 464 targetTG := t.PIDNamespace().ThreadGroupWithID(tgid) 465 target := t.PIDNamespace().TaskWithID(tid) 466 if targetTG == nil || target == nil || target.ThreadGroup() != targetTG { 467 return 0, nil, syserror.ESRCH 468 } 469 470 // If the sender is not the receiver, it can't use si_codes used by the 471 // kernel or SI_TKILL. 472 if (info.Code >= 0 || info.Code == linux.SI_TKILL) && target != t { 473 return 0, nil, linuxerr.EPERM 474 } 475 476 if !mayKill(t, target, sig) { 477 return 0, nil, linuxerr.EPERM 478 } 479 return 0, nil, target.SendSignal(&info) 480 } 481 482 // RtSigsuspend implements linux syscall rt_sigsuspend(2). 483 func RtSigsuspend(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 484 sigset := args[0].Pointer() 485 486 // Copy in the signal mask. 487 var mask linux.SignalSet 488 if _, err := mask.CopyIn(t, sigset); err != nil { 489 return 0, nil, err 490 } 491 mask &^= kernel.UnblockableSignals 492 493 // Swap the mask. 494 oldmask := t.SignalMask() 495 t.SetSignalMask(mask) 496 t.SetSavedSignalMask(oldmask) 497 498 // Perform the wait. 499 return 0, nil, syserror.ConvertIntr(t.Block(nil), syserror.ERESTARTNOHAND) 500 } 501 502 // RestartSyscall implements the linux syscall restart_syscall(2). 503 func RestartSyscall(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 504 if r := t.SyscallRestartBlock(); r != nil { 505 n, err := r.Restart(t) 506 return n, nil, err 507 } 508 // The restart block should never be nil here, but it's possible 509 // ERESTART_RESTARTBLOCK was set by ptrace without the current syscall 510 // setting up a restart block. If ptrace didn't manipulate the return value, 511 // finding a nil restart block is a bug. Linux ensures that the restart 512 // function is never null by (re)initializing it with one that translates 513 // the restart into EINTR. We'll emulate that behaviour. 514 t.Debugf("Restart block missing in restart_syscall(2). Did ptrace inject a return value of ERESTART_RESTARTBLOCK?") 515 return 0, nil, syserror.EINTR 516 } 517 518 // sharedSignalfd is shared between the two calls. 519 func sharedSignalfd(t *kernel.Task, fd int32, sigset hostarch.Addr, sigsetsize uint, flags int32) (uintptr, *kernel.SyscallControl, error) { 520 // Copy in the signal mask. 521 mask, err := CopyInSigSet(t, sigset, sigsetsize) 522 if err != nil { 523 return 0, nil, err 524 } 525 526 // Always check for valid flags, even if not creating. 527 if flags&^(linux.SFD_NONBLOCK|linux.SFD_CLOEXEC) != 0 { 528 return 0, nil, linuxerr.EINVAL 529 } 530 531 // Is this a change to an existing signalfd? 532 // 533 // The spec indicates that this should adjust the mask. 534 if fd != -1 { 535 file := t.GetFile(fd) 536 if file == nil { 537 return 0, nil, linuxerr.EBADF 538 } 539 defer file.DecRef(t) 540 541 // Is this a signalfd? 542 if s, ok := file.FileOperations.(*signalfd.SignalOperations); ok { 543 s.SetMask(mask) 544 return 0, nil, nil 545 } 546 547 // Not a signalfd. 548 return 0, nil, linuxerr.EINVAL 549 } 550 551 // Create a new file. 552 file, err := signalfd.New(t, mask) 553 if err != nil { 554 return 0, nil, err 555 } 556 defer file.DecRef(t) 557 558 // Set appropriate flags. 559 file.SetFlags(fs.SettableFileFlags{ 560 NonBlocking: flags&linux.SFD_NONBLOCK != 0, 561 }) 562 563 // Create a new descriptor. 564 fd, err = t.NewFDFrom(0, file, kernel.FDFlags{ 565 CloseOnExec: flags&linux.SFD_CLOEXEC != 0, 566 }) 567 if err != nil { 568 return 0, nil, err 569 } 570 571 // Done. 572 return uintptr(fd), nil, nil 573 } 574 575 // Signalfd implements the linux syscall signalfd(2). 576 func Signalfd(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 577 fd := args[0].Int() 578 sigset := args[1].Pointer() 579 sigsetsize := args[2].SizeT() 580 return sharedSignalfd(t, fd, sigset, sigsetsize, 0) 581 } 582 583 // Signalfd4 implements the linux syscall signalfd4(2). 584 func Signalfd4(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 585 fd := args[0].Int() 586 sigset := args[1].Pointer() 587 sigsetsize := args[2].SizeT() 588 flags := args[3].Int() 589 return sharedSignalfd(t, fd, sigset, sigsetsize, flags) 590 }