Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syscall: Peername() does not work on socketpair sockets on Illumos #53739

Open
problame opened this issue Jul 7, 2022 · 7 comments
Open

syscall: Peername() does not work on socketpair sockets on Illumos #53739

problame opened this issue Jul 7, 2022 · 7 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-illumos OS-Solaris
Milestone

Comments

@problame
Copy link

problame commented Jul 7, 2022

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

$ go version
go version go1.17.5 linux/amd64

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
O111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/cs/.cache/go-build"
GOENV="/home/cs/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/cs/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/cs/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/cs/go1.17.5"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/cs/go1.17.5/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.17.5"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/cs/zrepl/zrepl/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1505417924=/tmp/go-build -gno-record-gcc-switches"

What did you do?

(This is the presumed root cause for zrepl/zrepl#598 )

Take the following code snippet:

package main

import (
	"log"
	"syscall"
)

func main() {
	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
	if err != nil {
		panic(err)
	}

	sockname, err := syscall.Getsockname(fds[0])
	if err != nil {
		panic(err)
	}

	peername, err := syscall.Getpeername(fds[0])
	if err != nil {
		panic(err)
	}

	log.Printf("socketname=%T %#v", sockname, sockname)
	log.Printf("peername=%T %#v", peername, peername)
}

What did you expect to see?

On Linux, it prints

2022/07/08 00:30:11 socketname=*syscall.SockaddrUnix &syscall.SockaddrUnix{Name:"@", raw:syscall.RawSockaddrUnix{Family:0x0, Path:[108]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}
2022/07/08 00:30:11 peername=*syscall.SockaddrUnix &syscall.SockaddrUnix{Name:"@", raw:syscall.RawSockaddrUnix{Family:0x0, Path:[108]int8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}}

On Illumos (SunOS openindiana 5.11 illumos-e302d6af52 i86pc i386 i86pc), Getpeername appears to not work

root@openindiana:~# /opt/iss-589-repro 
panic: address family not supported by protocol family

goroutine 1 [running]:
main.main()
        /home/cs/zrepl/zrepl/iss-589/iss-589-repro.go:21 +0x237

Ccompiled with

GOARCH=amd64 GOOS=illumos go build -o iss-589-repro ./iss-589
scp iss-589-repro root@192.168.122.33:/opt/

However, a corresponding C program works fine on both platforms, i.e., the getpeername libc call returns no error.

#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <aio.h>

int main() {

    int fds[2];
    int err = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
    if (err != 0)
        abort();

    struct sockaddr_un name;
    socklen_t len = sizeof(name);
    err = getpeername(fds[0], (struct sockaddr *)&name, &len);
    if (err != 0)
        abort();

    printf("sun_path=%s\n", name.sun_path);

    return 0;
}

Compiled with:

gcc -lsocket test.c

Relevant truss of the Go program:

/1:     so_socket(PF_UNIX, SOCK_STREAM, 0, 0x00000000, SOV_XPG4_2) = 3
/1:     so_socket(PF_UNIX, SOCK_STREAM, 0, 0x00000000, SOV_XPG4_2) = 4
/1:     so_socketpair(0xC00004EEC8)                     = 0
/1:     close(3)                                        = 0
/1:     getsockname(5, 0xC00004EDD4, 0xC00004EDD0, SOV_DEFAULT) = 0
/1:     getpeername(5, 0xC00004EDD4, 0xC00004EDD0, SOV_DEFAULT) = 0

Relevant truss of the C program:

so_socket(PF_UNIX, SOCK_STREAM, 0, 0x00000000, SOV_DEFAULT) = 3
so_socket(PF_UNIX, SOCK_STREAM, 0, 0x00000000, SOV_DEFAULT) = 4
so_socketpair(0x7FFFBFFFD4D4)                   = 0
close(3)                                        = 0
getpeername(5, 0x7FFFBFFFD460, 0x7FFFBFFFD45C, SOV_DEFAULT) = 0
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Jul 7, 2022
@ianlancetaylor ianlancetaylor added OS-Solaris NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Jul 7, 2022
@ianlancetaylor ianlancetaylor added this to the Backlog milestone Jul 7, 2022
@ianlancetaylor
Copy link
Contributor

ianlancetaylor commented Jul 7, 2022

CC @golang/solaris

@nshalman
Copy link

nshalman commented Jul 13, 2022

Have you tried switching from using syscall to using x/sys/unix (if that's an option)?

@problame
Copy link
Author

problame commented Jul 13, 2022

zrepl actually uses golang.org/x/sys/unix - that's where the bug is from. See zrepl/zrepl#598. Could be that the version was outdated, though. @nshalman can you repro this issue?

@nshalman
Copy link

nshalman commented Jul 13, 2022

I think the culprit is https://github.com/golang/sys/blob/master/unix/syscall_solaris.go#L432

which means that the switch at https://github.com/golang/sys/blob/master/unix/syscall_solaris.go#L398 isn't finding AF_UNIX as we would expect. I'm not sure yet what the solution is.

EDIT: When you're using syscall, obviously the culprit is the code in the syscall implementation which would suffer from the same problem. The line is probably https://github.com/golang/go/blob/master/src/syscall/syscall_solaris.go#L345

If you add another debug line to the C program

printf("sun_family=%d\n", name.sun_family);

I get

sun_family=0

So it seems to me that on my illumos host, getpeername doesn't populate sun_family which I think is what that switch statement is examining and not happy about.

And for completeness, on my linux host, I get

sun_family=1

@jclulow
Copy link
Contributor

jclulow commented Jul 13, 2022

CC @golang/solaris

It would be cool if we could also CC @golang/illumos for illumos OS issues, rather than the Solaris folks, otherwise we'll miss them until someone points them out to us.

@alanc
Copy link

alanc commented Jul 14, 2022

On Solaris 11.4, the provided C program does indeed return no error for the getpeername() call, but it also sets the returned address length to 0, which appears to be how it indicates you've hit this case specified in both the Solaris man page and the Unix/POSIX standard:

If the protocol permits connections by unbound clients, and the peer is not bound, then the value stored in the object pointed to by address is unspecified.

Since there is no address associated with a socket from socketpair(), it's not clear what else it could do here, or what a program could expect it to return.

@problame
Copy link
Author

problame commented Jul 18, 2022

So it seems to me that on my illumos host, getpeername doesn't populate sun_family which I think is what that switch statement is examining and not happy about.

Yep, that seems about right. I looked at that code before, but it didn't occur to me to check sun_family.


FWIW I added a workaround in zrepl for this now. So, it's not exactly high priority for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-illumos OS-Solaris
Projects
Status: Triage Backlog
Development

No branches or pull requests

6 participants