Repository: go
Issue: x/sys/unix: Workaround `xnu` kernel bug when making `procargs2` syscall using `SysctlRaw`
Labels: OS-Darwin,NeedsInvestigation,compiler/runtime

<!--
Please answer these questions before submitting your issue. Thanks!
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.20.3 darwin/amd64

</pre>

### Does this issue reproduce with the latest release?

Yes, on macOS Catalina



### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/wheeler/Library/Caches/go-build"
GOENV="/Users/wheeler/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/wheeler/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/wheeler/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.20.3"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/v7/4gsbfcxj10190bg9qzr8ys_h0000gw/T/go-build2062273463=/tmp/go-build -gno-record-gcc-switches -fno-common"

</pre></details>

### What did you do?

Called [`unix.SysctlRaw()`][1] to get the args of a process on Catalina (through the use of the [`github.com/elastic/go-sysinfo`](https://github.com/elastic/go-sysinfo) package)

I have created a [small demo](https://github.com/wheelerlaw/go-sysinfo/blob/failing-procargs2-example/system_test.go#L314-L324) test in my fork of `go-sysinfo` that demonstrates the issue. Note: this must be run on macOS Catalina in order to the issue to be reproduced.


### What did you expect to see?

The [`unix.SysctlRaw()`][1] function return the args of a process on Catalina.


### What did you see instead?

I noticed that using [`unix.SysctlRaw()`][1] to call the [`kern.procargs2` syscall](https://github.com/apple-oss-distributions/xnu/blob/xnu-6153.141.1/bsd/kern/kern_sysctl.c#L1302) on macOS Catalina does not return the args for a process due to a couple bugs in `xnu`:

1. In the first syscall, the calculation of the size of the args is done incorrectly, as it does not account for the 17 byte string `executable_path=` that prefixes name of the executable. This size is then used to allocate a buffer which is where the args are copied into. 
2. In the second syscall, it writes zeros in the buffer instead of the executable name and its arguments due to a bug in the handling of a buffer that is too small. 

More details about this issue is [documented](https://github.com/apple-oss-distributions/xnu/blob/xnu-7195.50.7.100.1/bsd/kern/kern_sysctl.c#L1552-#L1592) in the fixed version of `xnu`'s `kern_sysctl.c`. 

These bugs are not going to be fixed in Catalina because Apple has discontinued support for the OS. However, Catalina is still technically a supported platform for the latest version of Go, so I went ahead and created a [patch](https://github.com/wheelerlaw/sys/pull/1) in the `x/sys` package that works around the `xnu` kernel bug. I'm not sure how to submit it but I am looking for feedback on it.

[1]: https://github.com/golang/sys/blob/a6bfb89d2fda1be39bf24b33d59fee29d65bf76f/unix/syscall_bsd.go#L472