unix, plan9: 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.

windows.Pipe already avoided writing to p on failure.

For golang/go#50057.

Change-Id: I93ed06b06a9981793c119c1d7df689fbe79b4116
Reviewed-on: https://go-review.googlesource.com/c/sys/+/370614
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/plan9/syscall_plan9.go b/plan9/syscall_plan9.go
index 84e1471..723b1f4 100644
--- a/plan9/syscall_plan9.go
+++ b/plan9/syscall_plan9.go
@@ -132,8 +132,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/unix/syscall_aix.go b/unix/syscall_aix.go
index 6192750..4f55c8d 100644
--- a/unix/syscall_aix.go
+++ b/unix/syscall_aix.go
@@ -519,8 +519,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/unix/syscall_darwin.go b/unix/syscall_darwin.go
index 8826f41..0eaab91 100644
--- a/unix/syscall_darwin.go
+++ b/unix/syscall_darwin.go
@@ -159,8 +159,10 @@
 	}
 	var x [2]int32
 	err = pipe(&x)
-	p[0] = int(x[0])
-	p[1] = int(x[1])
+	if err == nil {
+		p[0] = int(x[0])
+		p[1] = int(x[1])
+	}
 	return
 }
 
diff --git a/unix/syscall_dragonfly.go b/unix/syscall_dragonfly.go
index 5af108a..2e37c31 100644
--- a/unix/syscall_dragonfly.go
+++ b/unix/syscall_dragonfly.go
@@ -101,7 +101,10 @@
 	if len(p) != 2 {
 		return EINVAL
 	}
-	p[0], p[1], err = pipe()
+	r, w, err := pipe()
+	if err == nil {
+		p[0], p[1] = r, w
+	}
 	return
 }
 
@@ -114,7 +117,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/unix/syscall_freebsd.go b/unix/syscall_freebsd.go
index 18c392c..2f650ae 100644
--- a/unix/syscall_freebsd.go
+++ b/unix/syscall_freebsd.go
@@ -110,8 +110,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/unix/syscall_linux.go b/unix/syscall_linux.go
index 4bc5baf..f432b06 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -131,8 +131,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/unix/syscall_netbsd.go b/unix/syscall_netbsd.go
index 853d5f0..4e06c0b 100644
--- a/unix/syscall_netbsd.go
+++ b/unix/syscall_netbsd.go
@@ -128,8 +128,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/unix/syscall_openbsd.go b/unix/syscall_openbsd.go
index 22b5503..11b1d41 100644
--- a/unix/syscall_openbsd.go
+++ b/unix/syscall_openbsd.go
@@ -87,8 +87,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/unix/syscall_solaris.go b/unix/syscall_solaris.go
index 8b88ac2..5c81392 100644
--- a/unix/syscall_solaris.go
+++ b/unix/syscall_solaris.go
@@ -66,8 +66,10 @@
 	if n != 0 {
 		return err
 	}
-	p[0] = int(pp[0])
-	p[1] = int(pp[1])
+	if err == nil {
+		p[0] = int(pp[0])
+		p[1] = int(pp[1])
+	}
 	return nil
 }
 
@@ -79,8 +81,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/unix/syscall_zos_s390x.go b/unix/syscall_zos_s390x.go
index 5fb76a1..f8616f4 100644
--- a/unix/syscall_zos_s390x.go
+++ b/unix/syscall_zos_s390x.go
@@ -579,8 +579,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
 }