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>
This commit is contained in:
Russ Cox
2021-12-09 17:19:07 +00:00
parent 97ca703d54
commit 798191bca9
10 changed files with 48 additions and 22 deletions
+4 -2
View File
@@ -132,8 +132,10 @@ func Pipe(p []int) (err error) {
} }
var pp [2]int32 var pp [2]int32
err = pipe(&pp) err = pipe(&pp)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return return
} }
+4 -2
View File
@@ -519,8 +519,10 @@ func Pipe(p []int) (err error) {
} }
var pp [2]_C_int var pp [2]_C_int
err = pipe(&pp) err = pipe(&pp)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return return
} }
+4 -2
View File
@@ -159,8 +159,10 @@ func Pipe(p []int) (err error) {
} }
var x [2]int32 var x [2]int32
err = pipe(&x) err = pipe(&x)
p[0] = int(x[0]) if err == nil {
p[1] = int(x[1]) p[0] = int(x[0])
p[1] = int(x[1])
}
return return
} }
+8 -2
View File
@@ -101,7 +101,10 @@ func Pipe(p []int) (err error) {
if len(p) != 2 { if len(p) != 2 {
return EINVAL return EINVAL
} }
p[0], p[1], err = pipe() r, w, err := pipe()
if err == nil {
p[0], p[1] = r, w
}
return return
} }
@@ -114,7 +117,10 @@ func Pipe2(p []int, flags int) (err error) {
var pp [2]_C_int var pp [2]_C_int
// pipe2 on dragonfly takes an fds array as an argument, but still // pipe2 on dragonfly takes an fds array as an argument, but still
// returns the file descriptors. // 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 return err
} }
+4 -2
View File
@@ -110,8 +110,10 @@ func Pipe2(p []int, flags int) error {
} }
var pp [2]_C_int var pp [2]_C_int
err := pipe2(&pp, flags) err := pipe2(&pp, flags)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err return err
} }
+4 -2
View File
@@ -131,8 +131,10 @@ func Pipe2(p []int, flags int) error {
} }
var pp [2]_C_int var pp [2]_C_int
err := pipe2(&pp, flags) err := pipe2(&pp, flags)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err return err
} }
+4 -2
View File
@@ -128,8 +128,10 @@ func Pipe2(p []int, flags int) error {
} }
var pp [2]_C_int var pp [2]_C_int
err := pipe2(&pp, flags) err := pipe2(&pp, flags)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err return err
} }
+4 -2
View File
@@ -87,8 +87,10 @@ func Pipe2(p []int, flags int) error {
} }
var pp [2]_C_int var pp [2]_C_int
err := pipe2(&pp, flags) err := pipe2(&pp, flags)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err return err
} }
+8 -4
View File
@@ -66,8 +66,10 @@ func Pipe(p []int) (err error) {
if n != 0 { if n != 0 {
return err return err
} }
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return nil return nil
} }
@@ -79,8 +81,10 @@ func Pipe2(p []int, flags int) error {
} }
var pp [2]_C_int var pp [2]_C_int
err := pipe2(&pp, flags) err := pipe2(&pp, flags)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return err return err
} }
+4 -2
View File
@@ -579,8 +579,10 @@ func Pipe(p []int) (err error) {
} }
var pp [2]_C_int var pp [2]_C_int
err = pipe(&pp) err = pipe(&pp)
p[0] = int(pp[0]) if err == nil {
p[1] = int(pp[1]) p[0] = int(pp[0])
p[1] = int(pp[1])
}
return return
} }