Closed
Description
Bug description
Func GetsockoptString
from x/sys/unix package always removes the last byte from the buffer, which in some cases leads to a truncated option value.
From unix
man page:
The security context string may include a terminating null
character in the returned length, but is not guaranteed to
do so: a security context "foo" might be represented as
either {'f','o','o'} of length 3 or {'f','o','o','\0'} of
length 4, which are considered to be interchangeable. The
string is printable, does not contain non-terminating null
characters, and is in an unspecified encoding (in
particular, it is not guaranteed to be ASCII or UTF-8).
But the implementation (this patch) always cuts the last byte without checking it for the null character.
What version of Go are you using (go version
)?
$ go version go version go1.21.1
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env
)?
I'm using intel mac, but building for arm linux (GOARCH=arm64 GOOS=linux)
go env
Output
$ go env go env GO111MODULE='' GOARCH='amd64' GOBIN='' GOCACHE='/Users/kostik/Library/Caches/go-build' GOENV='/Users/kostik/Library/Application Support/go/env' GOEXE='' GOEXPERIMENT='' GOFLAGS='' GOHOSTARCH='amd64' GOHOSTOS='darwin' GOINSECURE='' GOMODCACHE='/Users/kostik/go/pkg/mod' GOOS='darwin' GOPATH='/Users/kostik/go' GOPROXY='https://proxy.golang.org,direct' GOROOT='/usr/local/Cellar/go/1.21.1/libexec' GOSUMDB='sum.golang.org' GOTMPDIR='' GOTOOLCHAIN='auto' GOTOOLDIR='/usr/local/Cellar/go/1.21.1/libexec/pkg/tool/darwin_amd64' GOVCS='' GOVERSION='go1.21.1' GCCGO='gccgo' GOAMD64='v1' AR='ar' CC='cc' CXX='c++' 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 -ffile-prefix-map=/var/folders/3p/1hh1wbcx7hjgl_79qxfdbqtr0000gq/T/go-build2506492106=/tmp/go-build -gno-record-gcc-switches -fno-common'
What did you do?
The service code is running on the linux with apparmor enabled. It just reads the app armor label from the Unix socket connection by calling:
var getSocketSecurityLabel = func(rc syscall.RawConn) (string, error) {
var label string
var readLabelError error
err := rc.Control(func(fd uintptr) {
// Read the apparmor label from the socket option SO_PEERSEC
label, readLabelError = unix.GetsockoptString(int(fd), syscall.SOL_SOCKET, unix.SO_PEERSEC)
})
if err != nil {
return "", err
}
if readLabelError != nil {
return "", readLabelError
}
return label, nil
}
What did you expect to see?
- For unconfined application the expected output is
unconfined
- For snap running in development mode the expected output is
appname (complain)
- For a labeled app the expected output is full app name
What did you see instead?
- For unconfined application the real output is
unconfine
- For snap running in development mode the real output is
appname (complain
- For a labeled app the real output miss the last char of the name