From da7ee57f40069eda3488b2e51dfa878bdd5816af Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 16 Aug 2023 19:20:54 -0700 Subject: [PATCH] syscall: add support to get pidfd from ForkExec on Linux Add PidFD support, so that if the PidFD pointer in SysProcAttr is not nil, ForkExec (and thus all its users) obtains a pidfd from the kernel during clone(), and writes the result (or -1, if the functionality is not supported by the kernel) into *PidFD. The functionality to get pidfd is implemented for both clone3 and clone. For the latter, an extra argument to rawVforkSyscall is needed, thus the change in asm files. Add a trivial test case checking the obtained pidfd can be used to send a signal to a process, using pidfd_send_signal. To test clone3 code path, add a flag available to tests only. Updates #51246. Change-Id: I2212b69e1a657163c31b4a6245b076bc495777a3 Reviewed-on: https://go-review.googlesource.com/c/go/+/520266 Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Run-TryBot: Kirill Kolyshkin --- api/next/51246.txt | 6 +++ src/syscall/asm_linux_386.s | 14 +++--- src/syscall/asm_linux_amd64.s | 14 +++--- src/syscall/asm_linux_arm.s | 14 +++--- src/syscall/asm_linux_arm64.s | 14 +++--- src/syscall/asm_linux_loong64.s | 14 +++--- src/syscall/asm_linux_mips64x.s | 14 +++--- src/syscall/asm_linux_mipsx.s | 14 +++--- src/syscall/asm_linux_ppc64x.s | 14 +++--- src/syscall/asm_linux_riscv64.s | 14 +++--- src/syscall/asm_linux_s390x.s | 14 +++--- src/syscall/exec_linux.go | 35 ++++++++++---- src/syscall/exec_linux_test.go | 68 ++++++++++++++++++++++++++++ src/syscall/export_linux_test.go | 10 +++- src/syscall/syscall_linux.go | 2 +- src/syscall/syscall_linux_386.go | 7 +-- src/syscall/syscall_linux_amd64.go | 7 +-- src/syscall/syscall_linux_arm.go | 7 +-- src/syscall/syscall_linux_arm64.go | 7 +-- src/syscall/syscall_linux_loong64.go | 7 +-- src/syscall/syscall_linux_mips64x.go | 7 +-- src/syscall/syscall_linux_mipsx.go | 7 +-- src/syscall/syscall_linux_ppc64x.go | 7 +-- src/syscall/syscall_linux_riscv64.go | 7 +-- src/syscall/syscall_linux_s390x.go | 7 +-- 25 files changed, 218 insertions(+), 113 deletions(-) create mode 100644 api/next/51246.txt diff --git a/api/next/51246.txt b/api/next/51246.txt new file mode 100644 index 0000000000..c8806c64a3 --- /dev/null +++ b/api/next/51246.txt @@ -0,0 +1,6 @@ +pkg syscall (linux-386), type SysProcAttr struct, PidFD *int #51246 +pkg syscall (linux-386-cgo), type SysProcAttr struct, PidFD *int #51246 +pkg syscall (linux-amd64), type SysProcAttr struct, PidFD *int #51246 +pkg syscall (linux-amd64-cgo), type SysProcAttr struct, PidFD *int #51246 +pkg syscall (linux-arm), type SysProcAttr struct, PidFD *int #51246 +pkg syscall (linux-arm-cgo), type SysProcAttr struct, PidFD *int #51246 diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s index a8e63f7079..d14df50a0a 100644 --- a/src/syscall/asm_linux_386.s +++ b/src/syscall/asm_linux_386.s @@ -13,24 +13,24 @@ // instead of the glibc-specific "CALL 0x10(GS)". #define INVOKE_SYSCALL INT $0x80 -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-20 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-24 MOVL trap+0(FP), AX // syscall entry MOVL a1+4(FP), BX MOVL a2+8(FP), CX - MOVL $0, DX + MOVL a3+12(FP), DX POPL SI // preserve return address INVOKE_SYSCALL PUSHL SI CMPL AX, $0xfffff001 JLS ok - MOVL $-1, r1+12(FP) + MOVL $-1, r1+16(FP) NEGL AX - MOVL AX, err+16(FP) + MOVL AX, err+20(FP) RET ok: - MOVL AX, r1+12(FP) - MOVL $0, err+16(FP) + MOVL AX, r1+16(FP) + MOVL $0, err+20(FP) RET // func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr); diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s index 00d6fedc62..da170c52ed 100644 --- a/src/syscall/asm_linux_amd64.s +++ b/src/syscall/asm_linux_amd64.s @@ -11,11 +11,11 @@ #define SYS_gettimeofday 96 -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 MOVQ a1+8(FP), DI MOVQ a2+16(FP), SI - MOVQ $0, DX + MOVQ a3+24(FP), DX MOVQ $0, R10 MOVQ $0, R8 MOVQ $0, R9 @@ -25,13 +25,13 @@ TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 PUSHQ R12 CMPQ AX, $0xfffffffffffff001 JLS ok2 - MOVQ $-1, r1+24(FP) + MOVQ $-1, r1+32(FP) NEGQ AX - MOVQ AX, err+32(FP) + MOVQ AX, err+40(FP) RET ok2: - MOVQ AX, r1+24(FP) - MOVQ $0, err+32(FP) + MOVQ AX, r1+32(FP) + MOVQ $0, err+40(FP) RET // func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) diff --git a/src/syscall/asm_linux_arm.s b/src/syscall/asm_linux_arm.s index d3995416c2..06a35b55cb 100644 --- a/src/syscall/asm_linux_arm.s +++ b/src/syscall/asm_linux_arm.s @@ -41,25 +41,25 @@ okseek: BL runtime·exitsyscall(SB) RET -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-20 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-24 MOVW trap+0(FP), R7 // syscall entry MOVW a1+4(FP), R0 MOVW a2+8(FP), R1 - MOVW $0, R2 + MOVW a3+12(FP), R2 SWI $0 MOVW $0xfffff001, R1 CMP R1, R0 BLS ok MOVW $-1, R1 - MOVW R1, r1+12(FP) + MOVW R1, r1+16(FP) RSB $0, R0, R0 - MOVW R0, err+16(FP) + MOVW R0, err+20(FP) RET ok: - MOVW R0, r1+12(FP) + MOVW R0, r1+16(FP) MOVW $0, R0 - MOVW R0, err+16(FP) + MOVW R0, err+20(FP) RET // func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr); diff --git a/src/syscall/asm_linux_arm64.s b/src/syscall/asm_linux_arm64.s index 7fa789a349..883645f975 100644 --- a/src/syscall/asm_linux_arm64.s +++ b/src/syscall/asm_linux_arm64.s @@ -4,11 +4,11 @@ #include "textflag.h" -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-40 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-48 MOVD a1+8(FP), R0 MOVD a2+16(FP), R1 - MOVD $0, R2 + MOVD a3+24(FP), R2 MOVD $0, R3 MOVD $0, R4 MOVD $0, R5 @@ -17,13 +17,13 @@ TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-40 CMN $4095, R0 BCC ok MOVD $-1, R4 - MOVD R4, r1+24(FP) // r1 + MOVD R4, r1+32(FP) // r1 NEG R0, R0 - MOVD R0, err+32(FP) // errno + MOVD R0, err+40(FP) // errno RET ok: - MOVD R0, r1+24(FP) // r1 - MOVD ZR, err+32(FP) // errno + MOVD R0, r1+32(FP) // r1 + MOVD ZR, err+40(FP) // errno RET // func rawSyscallNoError(trap uintptr, a1, a2, a3 uintptr) (r1, r2 uintptr); diff --git a/src/syscall/asm_linux_loong64.s b/src/syscall/asm_linux_loong64.s index 1a7457c7ea..2bbf0f1df1 100644 --- a/src/syscall/asm_linux_loong64.s +++ b/src/syscall/asm_linux_loong64.s @@ -8,11 +8,11 @@ // System calls for loong64, Linux // -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-40 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-48 MOVV a1+8(FP), R4 MOVV a2+16(FP), R5 - MOVV $0, R6 + MOVV a3+24(FP), R6 MOVV $0, R7 MOVV $0, R8 MOVV $0, R9 @@ -21,13 +21,13 @@ TEXT ·rawVforkSyscall(SB),NOSPLIT,$0-40 MOVW $-4096, R12 BGEU R12, R4, ok MOVV $-1, R12 - MOVV R12, r1+24(FP) // r1 + MOVV R12, r1+32(FP) // r1 SUBVU R4, R0, R4 - MOVV R4, err+32(FP) // errno + MOVV R4, err+40(FP) // errno RET ok: - MOVV R4, r1+24(FP) // r1 - MOVV R0, err+32(FP) // errno + MOVV R4, r1+32(FP) // r1 + MOVV R0, err+40(FP) // errno RET TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48 diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s index 6c7a6bc16f..1784e3a57a 100644 --- a/src/syscall/asm_linux_mips64x.s +++ b/src/syscall/asm_linux_mips64x.s @@ -10,11 +10,11 @@ // System calls for mips64, Linux // -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 MOVV a1+8(FP), R4 MOVV a2+16(FP), R5 - MOVV R0, R6 + MOVV a3+24(FP), R6 MOVV R0, R7 MOVV R0, R8 MOVV R0, R9 @@ -22,12 +22,12 @@ TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 SYSCALL BEQ R7, ok MOVV $-1, R1 - MOVV R1, r1+24(FP) // r1 - MOVV R2, err+32(FP) // errno + MOVV R1, r1+32(FP) // r1 + MOVV R2, err+40(FP) // errno RET ok: - MOVV R2, r1+24(FP) // r1 - MOVV R0, err+32(FP) // errno + MOVV R2, r1+32(FP) // r1 + MOVV R0, err+40(FP) // errno RET TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48 diff --git a/src/syscall/asm_linux_mipsx.s b/src/syscall/asm_linux_mipsx.s index 99f0154d1b..7544abbd48 100644 --- a/src/syscall/asm_linux_mipsx.s +++ b/src/syscall/asm_linux_mipsx.s @@ -45,21 +45,21 @@ ok9: JAL runtime·exitsyscall(SB) RET -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-20 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-24 MOVW a1+4(FP), R4 MOVW a2+8(FP), R5 - MOVW R0, R6 + MOVW a3+12(FP), R6 MOVW trap+0(FP), R2 // syscall entry SYSCALL BEQ R7, ok MOVW $-1, R1 - MOVW R1, r1+12(FP) // r1 - MOVW R2, err+16(FP) // errno + MOVW R1, r1+16(FP) // r1 + MOVW R2, err+20(FP) // errno RET ok: - MOVW R2, r1+12(FP) // r1 - MOVW R0, err+16(FP) // errno + MOVW R2, r1+16(FP) // r1 + MOVW R0, err+20(FP) // errno RET TEXT ·rawSyscallNoError(SB),NOSPLIT,$20-24 diff --git a/src/syscall/asm_linux_ppc64x.s b/src/syscall/asm_linux_ppc64x.s index b9412fec1d..6c29868f29 100644 --- a/src/syscall/asm_linux_ppc64x.s +++ b/src/syscall/asm_linux_ppc64x.s @@ -10,11 +10,11 @@ // System calls for ppc64, Linux // -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 MOVD a1+8(FP), R3 MOVD a2+16(FP), R4 - MOVD R0, R5 + MOVD a3+24(FP), R5 MOVD R0, R6 MOVD R0, R7 MOVD R0, R8 @@ -22,12 +22,12 @@ TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 SYSCALL R9 BVC ok MOVD $-1, R4 - MOVD R4, r1+24(FP) // r1 - MOVD R3, err+32(FP) // errno + MOVD R4, r1+32(FP) // r1 + MOVD R3, err+40(FP) // errno RET ok: - MOVD R3, r1+24(FP) // r1 - MOVD R0, err+32(FP) // errno + MOVD R3, r1+32(FP) // r1 + MOVD R0, err+40(FP) // errno RET TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48 diff --git a/src/syscall/asm_linux_riscv64.s b/src/syscall/asm_linux_riscv64.s index 6fd09ec422..0386b36384 100644 --- a/src/syscall/asm_linux_riscv64.s +++ b/src/syscall/asm_linux_riscv64.s @@ -8,11 +8,11 @@ // System calls for riscv64, Linux // -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 MOV a1+8(FP), A0 MOV a2+16(FP), A1 - MOV ZERO, A2 + MOV a3+24(FP), A2 MOV ZERO, A3 MOV ZERO, A4 MOV ZERO, A5 @@ -20,14 +20,14 @@ TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 ECALL MOV $-4096, T0 BLTU T0, A0, err - MOV A0, r1+24(FP) // r1 - MOV ZERO, err+32(FP) // errno + MOV A0, r1+32(FP) // r1 + MOV ZERO, err+40(FP) // errno RET err: MOV $-1, T0 - MOV T0, r1+24(FP) // r1 + MOV T0, r1+32(FP) // r1 SUB A0, ZERO, A0 - MOV A0, err+32(FP) // errno + MOV A0, err+40(FP) // errno RET TEXT ·rawSyscallNoError(SB),NOSPLIT,$0-48 diff --git a/src/syscall/asm_linux_s390x.s b/src/syscall/asm_linux_s390x.s index 41c34b1e17..e76b1e3082 100644 --- a/src/syscall/asm_linux_s390x.s +++ b/src/syscall/asm_linux_s390x.s @@ -8,11 +8,11 @@ // System calls for s390x, Linux // -// func rawVforkSyscall(trap, a1, a2 uintptr) (r1, err uintptr) -TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 +// func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1, err uintptr) +TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-48 MOVD a1+8(FP), R2 MOVD a2+16(FP), R3 - MOVD $0, R4 + MOVD a3+24(FP), R4 MOVD $0, R5 MOVD $0, R6 MOVD $0, R7 @@ -20,13 +20,13 @@ TEXT ·rawVforkSyscall(SB),NOSPLIT|NOFRAME,$0-40 SYSCALL MOVD $0xfffffffffffff001, R8 CMPUBLT R2, R8, ok2 - MOVD $-1, r1+24(FP) + MOVD $-1, r1+32(FP) NEG R2, R2 - MOVD R2, err+32(FP) // errno + MOVD R2, err+40(FP) // errno RET ok2: - MOVD R2, r1+24(FP) - MOVD $0, err+32(FP) // errno + MOVD R2, r1+32(FP) + MOVD $0, err+40(FP) // errno RET // func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go index dfbb38ac16..791b263b2a 100644 --- a/src/syscall/exec_linux.go +++ b/src/syscall/exec_linux.go @@ -101,11 +101,17 @@ type SysProcAttr struct { AmbientCaps []uintptr // Ambient capabilities (Linux only) UseCgroupFD bool // Whether to make use of the CgroupFD field. CgroupFD int // File descriptor of a cgroup to put the new process into. + // PidFD, if not nil, is used to store the pidfd of a child, if the + // functionality is supported by the kernel, or -1. Note *PidFD is + // changed only if the process starts successfully. + PidFD *int } var ( none = [...]byte{'n', 'o', 'n', 'e', 0} slash = [...]byte{'/', 0} + + forceClone3 = false // Used by unit tests only. ) // Implemented in runtime package. @@ -235,6 +241,7 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att uidmap, setgroups, gidmap []byte clone3 *cloneArgs pgrp int32 + pidfd _C_int = -1 dirfd int cred *Credential ngroups, groups uintptr @@ -289,18 +296,22 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att if sys.Cloneflags&CLONE_NEWUSER == 0 && sys.Unshareflags&CLONE_NEWUSER == 0 { flags |= CLONE_VFORK | CLONE_VM } + if sys.PidFD != nil { + flags |= CLONE_PIDFD + } // Whether to use clone3. - if sys.UseCgroupFD { - clone3 = &cloneArgs{ - flags: uint64(flags) | CLONE_INTO_CGROUP, - exitSignal: uint64(SIGCHLD), - cgroup: uint64(sys.CgroupFD), - } - } else if flags&CLONE_NEWTIME != 0 { + if sys.UseCgroupFD || flags&CLONE_NEWTIME != 0 || forceClone3 { clone3 = &cloneArgs{ flags: uint64(flags), exitSignal: uint64(SIGCHLD), } + if sys.UseCgroupFD { + clone3.flags |= CLONE_INTO_CGROUP + clone3.cgroup = uint64(sys.CgroupFD) + } + if sys.PidFD != nil { + clone3.pidFD = uint64(uintptr(unsafe.Pointer(&pidfd))) + } } // About to call fork. @@ -308,14 +319,14 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att runtime_BeforeFork() locked = true if clone3 != nil { - pid, err1 = rawVforkSyscall(_SYS_clone3, uintptr(unsafe.Pointer(clone3)), unsafe.Sizeof(*clone3)) + pid, err1 = rawVforkSyscall(_SYS_clone3, uintptr(unsafe.Pointer(clone3)), unsafe.Sizeof(*clone3), 0) } else { flags |= uintptr(SIGCHLD) if runtime.GOARCH == "s390x" { // On Linux/s390, the first two arguments of clone(2) are swapped. - pid, err1 = rawVforkSyscall(SYS_CLONE, 0, flags) + pid, err1 = rawVforkSyscall(SYS_CLONE, 0, flags, uintptr(unsafe.Pointer(&pidfd))) } else { - pid, err1 = rawVforkSyscall(SYS_CLONE, flags, 0) + pid, err1 = rawVforkSyscall(SYS_CLONE, flags, 0, uintptr(unsafe.Pointer(&pidfd))) } } if err1 != 0 || pid != 0 { @@ -330,6 +341,10 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att // Fork succeeded, now in child. + if sys.PidFD != nil { + *sys.PidFD = int(pidfd) + } + // Enable the "keep capabilities" flag to set ambient capabilities later. if len(sys.AmbientCaps) > 0 { _, _, err1 = RawSyscall6(SYS_PRCTL, PR_SET_KEEPCAPS, 1, 0, 0, 0, 0) diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go index ca92a153f8..7883096b88 100644 --- a/src/syscall/exec_linux_test.go +++ b/src/syscall/exec_linux_test.go @@ -24,6 +24,7 @@ import ( "strings" "syscall" "testing" + "time" "unsafe" ) @@ -522,6 +523,73 @@ func TestCloneTimeNamespace(t *testing.T) { } } +func testPidFD(t *testing.T) error { + testenv.MustHaveExec(t) + + if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { + // Child: wait for a signal. + time.Sleep(time.Hour) + } + + exe, err := os.Executable() + if err != nil { + t.Fatal(err) + } + + var pidfd int + cmd := testenv.Command(t, exe, "-test.run=^TestPidFD$") + cmd.Env = append(cmd.Environ(), "GO_WANT_HELPER_PROCESS=1") + cmd.SysProcAttr = &syscall.SysProcAttr{ + PidFD: &pidfd, + } + if err := cmd.Start(); err != nil { + return err + } + defer func() { + cmd.Process.Kill() + cmd.Wait() + }() + t.Log("got pidfd:", pidfd) + // If pidfd is not supported by the kernel, -1 is returned. + if pidfd == -1 { + t.Skip("pidfd not supported") + } + defer syscall.Close(pidfd) + + // Use pidfd to send a signal to the child. + sig := syscall.SIGINT + if _, _, e := syscall.Syscall(syscall.Sys_pidfd_send_signal, uintptr(pidfd), uintptr(sig), 0); e != 0 { + if e != syscall.EINVAL && testenv.SyscallIsNotSupported(e) { + t.Skip("pidfd_send_signal syscall not supported:", e) + } + t.Fatal("pidfd_send_signal syscall failed:", e) + } + // Check if the child received our signal. + err = cmd.Wait() + if cmd.ProcessState == nil || cmd.ProcessState.Sys().(syscall.WaitStatus).Signal() != sig { + t.Fatal("unexpected child error:", err) + } + return nil +} + +func TestPidFD(t *testing.T) { + if err := testPidFD(t); err != nil { + t.Fatal("can't start a process:", err) + } +} + +func TestPidFDClone3(t *testing.T) { + *syscall.ForceClone3 = true + defer func() { *syscall.ForceClone3 = false }() + + if err := testPidFD(t); err != nil { + if testenv.SyscallIsNotSupported(err) { + t.Skip("clone3 not supported:", err) + } + t.Fatal("can't start a process:", err) + } +} + type capHeader struct { version uint32 pid int32 diff --git a/src/syscall/export_linux_test.go b/src/syscall/export_linux_test.go index 274849e2ea..a09db60753 100644 --- a/src/syscall/export_linux_test.go +++ b/src/syscall/export_linux_test.go @@ -4,6 +4,12 @@ package syscall -var RawSyscallNoError = rawSyscallNoError +var ( + RawSyscallNoError = rawSyscallNoError + ForceClone3 = &forceClone3 +) -const Sys_GETEUID = sys_GETEUID +const ( + Sys_GETEUID = sys_GETEUID + Sys_pidfd_send_signal = _SYS_pidfd_send_signal +) diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go index 8b0a57b502..e012c1b943 100644 --- a/src/syscall/syscall_linux.go +++ b/src/syscall/syscall_linux.go @@ -95,7 +95,7 @@ func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) } func rawSyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) -func rawVforkSyscall(trap, a1, a2 uintptr) (r1 uintptr, err Errno) +func rawVforkSyscall(trap, a1, a2, a3 uintptr) (r1 uintptr, err Errno) /* * Wrapped diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go index 9cbd9ac9f0..f9d47236e5 100644 --- a/src/syscall/syscall_linux_386.go +++ b/src/syscall/syscall_linux_386.go @@ -7,9 +7,10 @@ package syscall import "unsafe" const ( - _SYS_setgroups = SYS_SETGROUPS32 - _SYS_clone3 = 435 - _SYS_faccessat2 = 439 + _SYS_setgroups = SYS_SETGROUPS32 + _SYS_clone3 = 435 + _SYS_faccessat2 = 439 + _SYS_pidfd_send_signal = 424 ) func setTimespec(sec, nsec int64) Timespec { diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go index aa85a523b2..0652590cfe 100644 --- a/src/syscall/syscall_linux_amd64.go +++ b/src/syscall/syscall_linux_amd64.go @@ -9,9 +9,10 @@ import ( ) const ( - _SYS_setgroups = SYS_SETGROUPS - _SYS_clone3 = 435 - _SYS_faccessat2 = 439 + _SYS_setgroups = SYS_SETGROUPS + _SYS_clone3 = 435 + _SYS_faccessat2 = 439 + _SYS_pidfd_send_signal = 424 ) //sys Dup2(oldfd int, newfd int) (err error) diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go index 600ec3552d..15c53d64b6 100644 --- a/src/syscall/syscall_linux_arm.go +++ b/src/syscall/syscall_linux_arm.go @@ -7,9 +7,10 @@ package syscall import "unsafe" const ( - _SYS_setgroups = SYS_SETGROUPS32 - _SYS_clone3 = 435 - _SYS_faccessat2 = 439 + _SYS_setgroups = SYS_SETGROUPS32 + _SYS_clone3 = 435 + _SYS_faccessat2 = 439 + _SYS_pidfd_send_signal = 424 ) func setTimespec(sec, nsec int64) Timespec { diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go index 42984ba2ed..56b492e810 100644 --- a/src/syscall/syscall_linux_arm64.go +++ b/src/syscall/syscall_linux_arm64.go @@ -7,9 +7,10 @@ package syscall import "unsafe" const ( - _SYS_setgroups = SYS_SETGROUPS - _SYS_clone3 = 435 - _SYS_faccessat2 = 439 + _SYS_setgroups = SYS_SETGROUPS + _SYS_clone3 = 435 + _SYS_faccessat2 = 439 + _SYS_pidfd_send_signal = 424 ) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT diff --git a/src/syscall/syscall_linux_loong64.go b/src/syscall/syscall_linux_loong64.go index f8f01c2d22..62533e8011 100644 --- a/src/syscall/syscall_linux_loong64.go +++ b/src/syscall/syscall_linux_loong64.go @@ -7,9 +7,10 @@ package syscall import "unsafe" const ( - _SYS_setgroups = SYS_SETGROUPS - _SYS_clone3 = 435 - _SYS_faccessat2 = 439 + _SYS_setgroups = SYS_SETGROUPS + _SYS_clone3 = 435 + _SYS_faccessat2 = 439 + _SYS_pidfd_send_signal = 424 ) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go index 47410d4260..061585a1bf 100644 --- a/src/syscall/syscall_linux_mips64x.go +++ b/src/syscall/syscall_linux_mips64x.go @@ -11,9 +11,10 @@ import ( ) const ( - _SYS_setgroups = SYS_SETGROUPS - _SYS_clone3 = 5435 - _SYS_faccessat2 = 5439 + _SYS_setgroups = SYS_SETGROUPS + _SYS_clone3 = 5435 + _SYS_faccessat2 = 5439 + _SYS_pidfd_send_signal = 5424 ) //sys Dup2(oldfd int, newfd int) (err error) diff --git a/src/syscall/syscall_linux_mipsx.go b/src/syscall/syscall_linux_mipsx.go index d8d5044b81..168148ab24 100644 --- a/src/syscall/syscall_linux_mipsx.go +++ b/src/syscall/syscall_linux_mipsx.go @@ -9,9 +9,10 @@ package syscall import "unsafe" const ( - _SYS_setgroups = SYS_SETGROUPS - _SYS_clone3 = 4435 - _SYS_faccessat2 = 4439 + _SYS_setgroups = SYS_SETGROUPS + _SYS_clone3 = 4435 + _SYS_faccessat2 = 4439 + _SYS_pidfd_send_signal = 4424 ) func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go index 36f7711dfa..91cd9838c3 100644 --- a/src/syscall/syscall_linux_ppc64x.go +++ b/src/syscall/syscall_linux_ppc64x.go @@ -11,9 +11,10 @@ import ( ) const ( - _SYS_setgroups = SYS_SETGROUPS - _SYS_clone3 = 435 - _SYS_faccessat2 = 439 + _SYS_setgroups = SYS_SETGROUPS + _SYS_clone3 = 435 + _SYS_faccessat2 = 439 + _SYS_pidfd_send_signal = 424 ) //sys Dup2(oldfd int, newfd int) (err error) diff --git a/src/syscall/syscall_linux_riscv64.go b/src/syscall/syscall_linux_riscv64.go index 44ff1d733e..50c3988e82 100644 --- a/src/syscall/syscall_linux_riscv64.go +++ b/src/syscall/syscall_linux_riscv64.go @@ -7,9 +7,10 @@ package syscall import "unsafe" const ( - _SYS_setgroups = SYS_SETGROUPS - _SYS_clone3 = 435 - _SYS_faccessat2 = 439 + _SYS_setgroups = SYS_SETGROUPS + _SYS_clone3 = 435 + _SYS_faccessat2 = 439 + _SYS_pidfd_send_signal = 424 ) //sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT diff --git a/src/syscall/syscall_linux_s390x.go b/src/syscall/syscall_linux_s390x.go index 44990f2b1b..ecdabbf98f 100644 --- a/src/syscall/syscall_linux_s390x.go +++ b/src/syscall/syscall_linux_s390x.go @@ -7,9 +7,10 @@ package syscall import "unsafe" const ( - _SYS_setgroups = SYS_SETGROUPS - _SYS_clone3 = 435 - _SYS_faccessat2 = 439 + _SYS_setgroups = SYS_SETGROUPS + _SYS_clone3 = 435 + _SYS_faccessat2 = 439 + _SYS_pidfd_send_signal = 424 ) //sys Dup2(oldfd int, newfd int) (err error) -- 2.44.0