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: support unix-domain socket pathname longer than system defined value #6895

Closed
gopherbot opened this issue Dec 5, 2013 · 14 comments
Closed
Milestone

Comments

@gopherbot
Copy link
Contributor

by joshpoimboeuf:

Several of the net functions return EINVAL for UNIX sockets with path names >= 108
characters, including net.Listen, net.Dial, and rpc.Dial.  The error seems to be related
to the full path length including leading directories, not just the length of the file
name itself.

~ $ cat test.go
package main

import (
    "log"
    "net"
    "os"
)

func socketTest(name string) {
    log.Printf("%s: %d characters\n", name, len(name))
    os.Remove(name)
    addr := &net.UnixAddr{Net: "unix", Name: name}
    if _, err := net.ListenUnix("unix", addr); err != nil {
        log.Fatal(err)
    }
    log.Printf("%s: success\n", name)
}

func main() {
    shortSocketName := "/tmp/0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999.sock"
    longSocketName := "/tmp/00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999.sock"
    socketTest(shortSocketName)
    socketTest(longSocketName)
}
~ $ go run test.go
2013/12/04 23:33:06
/tmp/0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999.sock:
107 characters
2013/12/04 23:33:06
/tmp/0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999.sock:
success
2013/12/04 23:33:06
/tmp/00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999.sock:
108 characters
2013/12/04 23:33:06 listen unix
/tmp/00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999.sock:
bind: invalid argument
exit status 1


What steps will reproduce the problem?
See above reproducer

What is the expected output?
2 success messages

What do you see instead?
1 success message and 1 error message

Which compiler are you using (5g, 6g, 8g, gccgo)?
6g

Which operating system are you using?
Linux

Which version are you using?  (run 'go version')
go version go1.2 linux/amd64

Please provide any additional information below.
@minux
Copy link
Member

minux commented Dec 5, 2013

Comment 1:

Labels changed: added repo-main.

@mikioh
Copy link
Contributor

mikioh commented Dec 5, 2013

Comment 2:

I'm a bit confused. Does bind syscall on Linux accept a sockaddr_un which contains non
NUL-terminated filepath? Can you elaborate a bit more about the detail of issue,
especially,
> not just the length of the file name itself.
What's your expectation?

Status changed to WaitingForReply.

@gopherbot
Copy link
Contributor Author

Comment 3 by joshpoimboeuf:

> Does bind syscall on Linux accept a sockaddr_un which contains non NUL-terminated
filepath?
I'm not sure what you mean by this and how this is related to the reproducer.  I didn't
mention anything about a NUL-terminated filepath and I don't understand why the summary
was changed to indicate that.  Don't the Go libraries convert the Go string to a C
string before calling bind?
>> not just the length of the file name itself.
>What's your expectation?
My expectation is that net.Listen returns successfully for a socket path name string
that is >= 108 characters.

@mikioh
Copy link
Contributor

mikioh commented Dec 5, 2013

Comment 4:

> Don't the Go libraries convert the Go string to a C string before calling bind?
https://code.google.com/p/go/source/browse/src/pkg/syscall/syscall_linux.go#262
> My expectation is that net.Listen returns successfully for a socket path name string
that is >= 108 characters.
Now I see, for now it's impossible. Please let us know your use case If you really need
that feature: platform-independent filepath namespace for PF_LOCAL/PF_UNIX domain
sockets.

@gopherbot
Copy link
Contributor Author

Comment 6 by joshpoimboeuf:

Ok.  So if I understand correctly, the 108-character socket path limitation is for
compatibility with other platforms:
https://code.google.com/p/go/source/browse/src/pkg/syscall/types_linux.go#84
Here's some information on the use case.  I'm using UNIX sockets in docker
(http://docker.io).  Each docker container has a rootfs in
"/var/lib/containers/<container id>/rootfs.  For example:
/var/lib/docker/containers/7eacdaeaf3d67dfa8e3585c73689a6f40945326bbe2c4fda5f152ea4fdc5ee97/rootfs
We want there to be a socket connection between each individual container and the docker
daemon.  So the full socket path is:
/var/lib/docker/containers/7eacdaeaf3d67dfa8e3585c73689a6f40945326bbe2c4fda5f152ea4fdc5ee97/rootfs/.docker-shared/rpc.sock
which is 122 characters.  That's an unusually long path name for a socket, but it's
supported by Linux at least.
I do have a workaround, which is to simply create a symlink to the socket in /tmp.

@ianlancetaylor
Copy link
Contributor

Comment 7:

Labels changed: added release-go1.3maybe.

Status changed to Accepted.

@davecheney
Copy link
Contributor

Comment 8:

@joshpoimboeuf, docker is linux only, why not use unix sockets in the
abstract namespace ?
@/docket/7eacdaeaf3d67dfa8e3585c73689a6f40945326bbe2c4fda5f152ea4fdc5ee97
Should fit easily.

@gopherbot
Copy link
Contributor Author

Comment 9 by joshpoimboeuf:

Each docker container runs in its own network namespace, so abstract socket addresses
won't work.

@mikioh
Copy link
Contributor

mikioh commented Dec 6, 2013

Comment 10:

> the 108-character socket path limitation is for compatibility with other platforms
Actually not. It comes from sockaddr_un of Linux,  on some BSDs it's 104.
Well, looks like we need to introduce some indirection layer, (layering is harmful,
yay!), in between "filesystem namespace" and "unix domain socket path namespace" to fill
the gap. On Linux using proc filesystem for shortening and bridging namespaces is a most
popular (really?) way but it doesn't work on other Unix system and it might break Go API
compatibility. But sooner or later we'll face this sort of issues on software container
environment such as LXC on Linux or Jail on FreeBSD because they isolate some resource
namespaces but don't provide bridging stuff unlike Plan 9, PlanetLab blah blah blah.
Thoughts?
@joshpoimboeuf: As you mentioned above, making your own docker's IPC pathname shortener
library on Linux might be a fast and robust solution, for now.

@gopherbot
Copy link
Contributor Author

Comment 11 by joshpoimboeuf:

I don't follow the points about namespaces or how this would be a worse problem with
LXC.  In fact docker uses LXC, but I don't see how it's relevant.
But, as you pointed out, the 108 character limit comes from Linux, not Go.  So this
doesn't seem like a Go issue to me.  So it's fine with me if you reject this issue.  I
apologize for not realizing earlier that the limitation comes from Linux.

@mikioh
Copy link
Contributor

mikioh commented Dec 6, 2013

Comment 12:

> how it's relevant.
It's not related to container stuff directly, sorry for the confusion. The root cause
would be unix-domain socket. It uses filesystem namespace as an endpoint identifier but
it doesn't support maximum length of filepath (if it exists). And on virtual environment
like LXC, choosing unix domain sockets for its IPC is pretty reasonable because it's
easy (we can use well-known, simple filesystem namespace instead of ephemeral IP
namespace) and faster than other domain sockets such as TCP, but TANSTAAFL.

@gopherbot
Copy link
Contributor Author

Comment 13 by joshpoimboeuf:

That makes sense, thanks for the explanation.  It's ok with me if you want to close the
issue.

@ianlancetaylor
Copy link
Contributor

Comment 14:

Status changed to WorkingAsIntended.

@rsc rsc added this to the Go1.3 milestone Apr 14, 2015
@gabriel
Copy link

gabriel commented May 1, 2015

I'm hitting this bug on go1.4 darwin/amd64 (os x 10.10).... Maybe go should return an error thats more descriptive than "bind: invalid argument"?

@golang golang locked and limited conversation to collaborators Jun 25, 2016
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants