[release-branch.go1.17] syscall: avoid writing to p when Pipe(p) fails

Generally speaking Go functions make no guarantees
about what has happened to result parameters on error,
and Pipe is no exception: callers should avoid looking at
p if Pipe returns an error.

However, we had a bug in which ForkExec was using the
content of p after a failed Pipe, and others may too.
As a robustness fix, make Pipe avoid writing to p on failure.

Updates #50057

Change-Id: Ie8955025dbd20702fabadc9bbe1d1a5ac0f36305
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1291271
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/370535
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Alex Rakoczy <alex@golang.org>
diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go
index 9c6afba..db289fd 100644
--- a/src/syscall/syscall_aix.go
+++ b/src/syscall/syscall_aix.go
@@ -64,8 +64,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe(&pp)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go
index a4fe4f1..ce69464 100644
--- a/src/syscall/syscall_darwin.go
+++ b/src/syscall/syscall_darwin.go
@@ -96,8 +96,10 @@
 	}
 	var q [2]int32
 	err = pipe(&q)
-	p[0] = int(q[0])
-	p[1] = int(q[1])
+	if err == nil {
+		p[0] = int(q[0])
+		p[1] = int(q[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_dragonfly.go b/src/syscall/syscall_dragonfly.go
index b01a4ad..5ff7f99 100644
--- a/src/syscall/syscall_dragonfly.go
+++ b/src/syscall/syscall_dragonfly.go
@@ -96,8 +96,11 @@
 	if len(p) != 2 {
 		return EINVAL
 	}
-	p[0], p[1], err = pipe()
-	return
+	r, w, err := pipe()
+	if err == nil {
+		p[0], p[1] = r, w
+	}
+	return err
 }
 
 //sysnb	pipe2(p *[2]_C_int, flags int) (r int, w int, err error)
@@ -109,7 +112,10 @@
 	var pp [2]_C_int
 	// pipe2 on dragonfly takes an fds array as an argument, but still
 	// returns the file descriptors.
-	p[0], p[1], err = pipe2(&pp, flags)
+	r, w, err := pipe2(&pp, flags)
+	if err == nil {
+		p[0], p[1] = r, w
+	}
 	return err
 }
 
diff --git a/src/syscall/syscall_freebsd.go b/src/syscall/syscall_freebsd.go
index 7c7b89a..ad904d6 100644
--- a/src/syscall/syscall_freebsd.go
+++ b/src/syscall/syscall_freebsd.go
@@ -105,8 +105,10 @@
 	}
 	var pp [2]_C_int
 	err := pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return err
 }
 
diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go
index 0db0374..26bdb9b 100644
--- a/src/syscall/syscall_linux_386.go
+++ b/src/syscall/syscall_linux_386.go
@@ -30,8 +30,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe(&pp)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -43,8 +45,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go
index 5df3f79..896117a 100644
--- a/src/syscall/syscall_linux_amd64.go
+++ b/src/syscall/syscall_linux_amd64.go
@@ -118,8 +118,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe(&pp)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -131,8 +133,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go
index e887cf7..79c201a 100644
--- a/src/syscall/syscall_linux_arm.go
+++ b/src/syscall/syscall_linux_arm.go
@@ -34,8 +34,10 @@
 	if err == ENOSYS {
 		err = pipe(&pp)
 	}
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -47,8 +49,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go
index f575c84..bfa7be9 100644
--- a/src/syscall/syscall_linux_arm64.go
+++ b/src/syscall/syscall_linux_arm64.go
@@ -152,8 +152,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, 0)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -165,8 +167,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go
index 5feb03e..43f9411 100644
--- a/src/syscall/syscall_linux_mips64x.go
+++ b/src/syscall/syscall_linux_mips64x.go
@@ -109,8 +109,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, 0)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -122,8 +124,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_linux_mipsx.go b/src/syscall/syscall_linux_mipsx.go
index 39104d7..1ab452e 100644
--- a/src/syscall/syscall_linux_mipsx.go
+++ b/src/syscall/syscall_linux_mipsx.go
@@ -120,8 +120,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -131,8 +133,11 @@
 	if len(p) != 2 {
 		return EINVAL
 	}
-	p[0], p[1], err = pipe()
-	return
+	r, w, err := pipe()
+	if err == nil {
+		p[0], p[1] = r, w
+	}
+	return err
 }
 
 //sys	mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go
index 495ae29..8a69eb5 100644
--- a/src/syscall/syscall_linux_ppc64x.go
+++ b/src/syscall/syscall_linux_ppc64x.go
@@ -88,8 +88,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, 0)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -101,8 +103,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_linux_riscv64.go b/src/syscall/syscall_linux_riscv64.go
index 2a0fe64..dd48f7c 100644
--- a/src/syscall/syscall_linux_riscv64.go
+++ b/src/syscall/syscall_linux_riscv64.go
@@ -155,8 +155,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, 0)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -168,8 +170,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_linux_s390x.go b/src/syscall/syscall_linux_s390x.go
index 0f6f627..08e6613 100644
--- a/src/syscall/syscall_linux_s390x.go
+++ b/src/syscall/syscall_linux_s390x.go
@@ -80,8 +80,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, 0)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
@@ -93,8 +95,10 @@
 	}
 	var pp [2]_C_int
 	err = pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_netbsd.go b/src/syscall/syscall_netbsd.go
index fc13b70..0754bad 100644
--- a/src/syscall/syscall_netbsd.go
+++ b/src/syscall/syscall_netbsd.go
@@ -112,8 +112,10 @@
 	}
 	var pp [2]_C_int
 	err := pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return err
 }
 
diff --git a/src/syscall/syscall_openbsd.go b/src/syscall/syscall_openbsd.go
index 5a5ba5a..18eafe3 100644
--- a/src/syscall/syscall_openbsd.go
+++ b/src/syscall/syscall_openbsd.go
@@ -72,8 +72,10 @@
 	}
 	var pp [2]_C_int
 	err := pipe2(&pp, flags)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return err
 }
 
diff --git a/src/syscall/syscall_plan9.go b/src/syscall/syscall_plan9.go
index d16cad4..6a8ab97 100644
--- a/src/syscall/syscall_plan9.go
+++ b/src/syscall/syscall_plan9.go
@@ -198,8 +198,10 @@
 	}
 	var pp [2]int32
 	err = pipe(&pp)
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return
 }
 
diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go
index daa4b88..7640aac 100644
--- a/src/syscall/syscall_solaris.go
+++ b/src/syscall/syscall_solaris.go
@@ -55,7 +55,9 @@
 	if e1 != 0 {
 		err = Errno(e1)
 	}
-	p[0], p[1] = int(r0), int(w0)
+	if err == nil {
+		p[0], p[1] = int(r0), int(w0)
+	}
 	return
 }