go: runtime: GOOS=ios fails Apple's app validation due to use of private API

What version of Go are you using (go version)?

$ go version
go version go1.20rc3-ts178d6bc darwin/amd64

This is Tailscale’s Go toolchain from https://github.com/tailscale/go. It has some minor changes, but for the purposes of this bug it’s identical to the final Go 1.20 release. You can see our very minor additional commits at https://github.com/tailscale/go/commits/tailscale.go1.20 , prefixed [tailscale1.20].

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/tsbuild/Library/Caches/go-build"
GOENV="/Users/tsbuild/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/tsbuild/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/tsbuild/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/tsbuild/.cache/tailscale-go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/tsbuild/.cache/tailscale-go/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.20rc3-ts178d6bc"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
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/h6/n1fmcdqs5z765682qxt8sr7w0000gn/T/go-build460345883=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Built a test release of Tailscale’s iOS app, which unfortunately is not open-source. It’s a mixed swift+Go application built through xcode.

What did you expect to see?

A working app that passes Apple’s app store validation.

What did you see instead?

Apple rejected the app bundle, on the grounds that it failed “SPI validation”. This is apparently the process where Apple checks for unauthorized use of private APIs by the app.

*** Error: ERROR: Asset validation failed (11) The app references non-public symbols in Payload/Tailscale.app/PlugIns/IPNExtension.appex/IPNExtension: _xpc_date_create_from_current (ID: e6cd0a76-b3c5-4ce4-8a35-600308487c8c)

AFAICT, this is due to https://github.com/golang/go/commit/76d39ae3499238ac7efb731f4f4cd47b1b3288ab , which added a call to xpc_date_create_from_current in an attempt to fix atfork problems on darwin.

The same app builds and validates successfully when targeting macOS, so it appears that xpc_date_create_from_current is marked private only on iOS, not macOS.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 2
  • Comments: 17 (14 by maintainers)

Commits related to this issue

Most upvoted comments

@bradfitz suggested just removing the osinit_hack on iOS as a test, on the principle that apparently fork+exec is forbidden in non-jailbroken iOS anyway.

Patch is at https://github.com/tailscale/go/commit/d0f872e9946e410036e5411f2a7a3ff968e3d1cf, which through dead code elimination removes the offending call from the binary. With this patch applied to the toolchain, Apple is once again happy with the Tailscale iOS app.

We haven’t dug very deeply into whether disabling osinit_hack is safe, we’re just going off internet claims that fork+exec is not permitted in the iOS runtime environment. If y’all have a direct line to Apple, it’d be good to get verification from them.

Change https://go.dev/cl/467316 mentions this issue: [release-branch.go1.20] runtime: skip darwin osinit_hack on ios

Thank you!

We patched https://go.dev/cl/466516 into our toolchain and built an unstable iOS app release. It worked fine, Apple was happy with the resulting binaries. LGTM!