diff --git a/go.mod b/go.mod index 4fdebae..4054d1b 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.18 require ( github.com/elastic/go-seccomp-bpf v1.2.0 - golang.org/x/net v0.0.0-20220225172249-27dd8689420f - golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 + golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 + golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 ) require github.com/pkg/errors v0.9.1 // indirect diff --git a/go.sum b/go.sum index f76d0ba..3727040 100644 --- a/go.sum +++ b/go.sum @@ -13,12 +13,12 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 h1:yssD99+7tqHWO5Gwh81phT+67hg+KttniBr6UnEXOY8= +golang.org/x/net v0.0.0-20220421235706-1d1ef9303861/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/forkexec/fork_child_linux.go b/pkg/forkexec/fork_child_linux.go index 0bb200f..2f295b9 100644 --- a/pkg/forkexec/fork_child_linux.go +++ b/pkg/forkexec/fork_child_linux.go @@ -137,6 +137,10 @@ func forkAndExecInChild1(r *Runner, argv0 *byte, argv, env []*byte, workdir, hos nextfd++ } if r.ExecFile > 0 && int(r.ExecFile) < nextfd { + // Avoid fd rewrite + for nextfd == pipe { + nextfd++ + } _, _, err1 = syscall.RawSyscall(syscall.SYS_DUP3, r.ExecFile, uintptr(nextfd), syscall.O_CLOEXEC) if err1 != 0 { return pipe, LocDup3, 0, err1 diff --git a/pkg/forkexec/fork_linux.go b/pkg/forkexec/fork_linux.go index 2f4089c..35ba596 100644 --- a/pkg/forkexec/fork_linux.go +++ b/pkg/forkexec/fork_linux.go @@ -87,9 +87,9 @@ func syncWithChild(r *Runner, p [2]int, pid int, err1 syscall.Errno) (int, error syscall.RawSyscall(syscall.SYS_WRITE, uintptr(p[0]), uintptr(unsafe.Pointer(&err2)), uintptr(unsafe.Sizeof(err2))) } - r1, _, err1 = syscall.RawSyscall(syscall.SYS_READ, uintptr(p[0]), uintptr(unsafe.Pointer(&childErr)), uintptr(unsafe.Sizeof(childErr))) + n, err := readChildErr(p[0], &childErr) // child returned error code - if (r1 != unsafe.Sizeof(err2) && r1 != unsafe.Sizeof(childErr)) || childErr.Err != 0 || err1 != 0 { + if (n != int(unsafe.Sizeof(err2)) && n != int(unsafe.Sizeof(childErr))) || childErr.Err != 0 || err != nil { childErr.Err = handlePipeError(r1, childErr.Err) goto fail } @@ -107,16 +107,16 @@ func syncWithChild(r *Runner, p [2]int, pid int, err1 syscall.Errno) (int, error if r.Ptrace || r.StopBeforeSeccomp { // let's wait it in another goroutine to avoid SIGPIPE go func() { - syscall.RawSyscall(syscall.SYS_READ, uintptr(p[0]), uintptr(unsafe.Pointer(&childErr)), uintptr(unsafe.Sizeof(childErr))) + readChildErr(p[0], &childErr) unix.Close(p[0]) }() return int(pid), nil } // if read anything mean child failed after sync (close_on_exec so it should not block) - r1, _, err1 = syscall.RawSyscall(syscall.SYS_READ, uintptr(p[0]), uintptr(unsafe.Pointer(&childErr)), uintptr(unsafe.Sizeof(childErr))) + n, err = readChildErr(p[0], &childErr) unix.Close(p[0]) - if r1 != 0 || err1 != 0 { + if n != 0 || err != nil { childErr.Err = handlePipeError(r1, childErr.Err) goto failAfterClose } @@ -133,6 +133,26 @@ failAfterClose: return 0, childErr } +func readChildErr(fd int, childErr *ChildError) (n int, err error) { + for { + n, err = readlen(fd, (*byte)(unsafe.Pointer(childErr)), int(unsafe.Sizeof(*childErr))) + if err != syscall.EINTR { + break + } + } + return +} + +// https://cs.opensource.google/go/go/+/refs/tags/go1.18.1:src/syscall/zsyscall_linux_amd64.go;l=944 +func readlen(fd int, p *byte, np int) (n int, err error) { + r0, _, e1 := syscall.Syscall(syscall.SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np)) + n = int(r0) + if e1 != 0 { + err = syscall.Errno(e1) + } + return +} + // check pipe error func handlePipeError(r1 uintptr, errno syscall.Errno) syscall.Errno { if r1 >= unsafe.Sizeof(errno) {