Skip to content

x/sys: trimmed string socket opt on linux #63217

Closed
@KSDaemon

Description

@KSDaemon

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions