msg253981 - (view) |
Author: PrzemeK (soutys) |
Date: 2015-11-03 11:15 |
Case: http://stackoverflow.com/questions/33465094/connection-refused-when-using-abstract-namespace-unix-sockets The code that does not work (python3 example): ... sock_path = b"/var/tmp/sock.tmp" server.bind(b"\0" + sock_path) ... and strace shows: connect(3, {sa_family=AF_LOCAL, sun_path=@"/var/tmp/sock.tmp"}, 20) = -1 ECONNREFUSED (Connection refused) For C-written client strace shows: connect(3, {sa_family=AF_LOCAL, sun_path=@"/var/tmp/sock.tmp"}, 110) = 0 The code that actually works (python3 example): ... sun_path_len = 108 sock_path = b"/var/tmp/sock.tmp" server.bind(b"\0" + sock_path + (b"\0" * (sun_path_len - len(sock_path) - 1))) ... and strace shows: bind(3, {sa_family=AF_LOCAL, sun_path=@"/var/tmp/sock.tmp"}, 110) = 0 110 it's the correst size of a struct. There's no hint at https://docs.python.org/3/library/socket.html#socket-families for that. Test files (servers and clients): https://gist.github.com/soutys/ffbe2e76a86835a9cc6b |
|
|
msg253982 - (view) |
Author: PrzemeK (soutys) |
Date: 2015-11-03 11:23 |
Errata - 1st paragraph should be: The code that does not work (python3 example): ... sock_path = b"/var/tmp/sock.tmp" server.bind(b"\0" + sock_path) ... and strace shows: bind(3, {sa_family=AF_LOCAL, sun_path=@"/var/tmp/sock.tmp"...}, 20) = 0 |
|
|
msg341637 - (view) |
Author: anthony shaw (anthonypjshaw) *  |
Date: 2019-05-06 20:15 |
hi, which version of Python were you using to do this? Please could you provide the full code snippet to reproduce the issue. The following example binds to the correct namespace from socket import * sock = socket(AF_UNIX, SOCK_STREAM) sock.bind("\0/var/tmp/sock.tmp") |
|
|
msg341641 - (view) |
Author: Stefan Behnel (scoder) *  |
Date: 2019-05-06 20:32 |
Looks like the issue was originally reported against Python 3.4. |
|
|
msg341686 - (view) |
Author: PrzemeK (soutys) |
Date: 2019-05-07 06:49 |
Yep, it was 3.4 then... but I think problem still exists tl;dr: For abstract sockets (only?) filling struct with zeros is meaningful. long: * Python (cli) -> Python (srv) = works * C (cli) -> C (srv) = works * C (cli) -> Python (srv) = does NOT work * Python (cli) -> C (srv) = does NOT work (strace dumps below) $ gcc --version gcc (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0 $ uname -a Linux ajzus 4.15.0-48-generic #51-Ubuntu SMP Wed Apr 3 08:28:49 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux $ python3.7 --version Python 3.7.1 // 1st console $ gcc -g -Wall -Wextra -pedantic -o abs_srv abs_srv.c $ strace ./abs_srv ... socket(AF_UNIX, SOCK_STREAM, 0) = 3 bind(3, {sa_family=AF_UNIX, sun_path=@"/var/tmp/sock.tmp\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"}, 110) = 0 listen(3, 5) = 0 accept(3, NULL, NULL // waiting // 2nd console $ ls /var/tmp/*.sock ls: cannot access '/var/tmp/*.sock': No such file or directory $ strace python3.7 abs_cli.py ... socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 3 connect(3, {sa_family=AF_UNIX, sun_path=@"/var/tmp/sock.tmp"}, 20) = -1 ECONNREFUSED (Connection refused) |
|
|
msg341688 - (view) |
Author: PrzemeK (soutys) |
Date: 2019-05-07 06:59 |
Gist: https://gist.github.com/soutys/ffbe2e76a86835a9cc6b More: Padding `sun_path` with zeros for python cli code: ... client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) client.connect("\0/var/tmp/sock.tmp" + "\0" * 90) ... gives strace like: ... socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 3 connect(3, {sa_family=AF_UNIX, sun_path=@"/var/tmp/sock.tmp\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"}, 110) = 0 write(1, "Ready.\n", 7Ready. ) = 7 ... = works |
|
|
msg341971 - (view) |
Author: anthony shaw (anthonypjshaw) *  |
Date: 2019-05-09 07:49 |
thanks, your code example zero-pads the socket address, and looking at the socketmodule.c code it does some padding under certain circumstances. https://github.com/python/cpython/blob/master/Modules/socketmodule.c#L1318-L1330 The Unix man page specify the same requirement you've noticed: When binding a socket to a pathname, a few rules should be observed for maximum portability and ease of coding: * The pathname in sun_path should be null-terminated. * The length of the pathname, including the terminating null byte, should not exceed the size of sun_path. * The addrlen argument that describes the enclosing sockaddr_un structure should have a value of at least: offsetof(struct sockaddr_un, sun_path)+strlen(addr.sun_path)+1 or, more simply, addrlen can be specified as sizeof(struct sock‐ addr_un). |
|
|
msg341972 - (view) |
Author: anthony shaw (anthonypjshaw) *  |
Date: 2019-05-09 08:04 |
The existing tests in place add the null-termination bytes in the test string: def testLinuxAbstractNamespace(self): address = b"\x00python-test-hello\x00\xff" with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s1: s1.bind(address) s1.listen() with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s2: s2.connect(s1.getsockname()) with s1.accept()[0] as s3: self.assertEqual(s1.getsockname(), address) self.assertEqual(s2.getpeername(), address) So that answers your initial question, it does work, but you have to add the null termination bytes in the address string. This isn't documented, so the documentation needs fixing. |
|
|