[release-branch.go1.17] syscall: do not use handle lists on windows when NoInheritHandles is true

If NoInheritHandles is passed, then we shouldn't attempt to do anything
with handle lists. Otherwise CreateProcess fails with invalid param,
because it's being told both to not inherit handles and to inherit
certain handles.

This commit fixes that by using the same logic for handle lists as it
does for enabling or disabling handle inheritance. It also adds a test
to make sure this doesn't regress again.

Updates #48040
Fixes #48075

Change-Id: I507261baeec263091738ab90157a991d917dc92f
Reviewed-on: https://go-review.googlesource.com/c/go/+/350416
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Patrik Nyblom <pnyb@google.com>
diff --git a/src/os/exec/exec_windows_test.go b/src/os/exec/exec_windows_test.go
index fbccffe..bd4dfb3 100644
--- a/src/os/exec/exec_windows_test.go
+++ b/src/os/exec/exec_windows_test.go
@@ -10,6 +10,7 @@
 import (
 	"io"
 	"os"
+	"os/exec"
 	"strconv"
 	"syscall"
 	"testing"
@@ -41,3 +42,16 @@
 		t.Error(err)
 	}
 }
+
+func TestNoInheritHandles(t *testing.T) {
+	cmd := exec.Command("cmd", "/c exit 88")
+	cmd.SysProcAttr = &syscall.SysProcAttr{NoInheritHandles: true}
+	err := cmd.Run()
+	exitError, ok := err.(*exec.ExitError)
+	if !ok {
+		t.Fatalf("got error %v; want ExitError", err)
+	}
+	if exitError.ExitCode() != 88 {
+		t.Fatalf("got exit code %d; want 88", exitError.ExitCode())
+	}
+}
diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go
index 18d1502..9d10d6a 100644
--- a/src/syscall/exec_windows.go
+++ b/src/syscall/exec_windows.go
@@ -390,8 +390,10 @@
 	}
 	fd = fd[:j]
 
+	willInheritHandles := len(fd) > 0 && !sys.NoInheritHandles
+
 	// Do not accidentally inherit more than these handles.
-	if len(fd) > 0 {
+	if willInheritHandles {
 		err = updateProcThreadAttribute(si.ProcThreadAttributeList, 0, _PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&fd[0]), uintptr(len(fd))*unsafe.Sizeof(fd[0]), nil, nil)
 		if err != nil {
 			return 0, 0, err
@@ -401,9 +403,9 @@
 	pi := new(ProcessInformation)
 	flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT | _EXTENDED_STARTUPINFO_PRESENT
 	if sys.Token != 0 {
-		err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, len(fd) > 0 && !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi)
+		err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi)
 	} else {
-		err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, len(fd) > 0 && !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi)
+		err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, willInheritHandles, flags, createEnvBlock(attr.Env), dirp, &si.StartupInfo, pi)
 	}
 	if err != nil {
 		return 0, 0, err