Can Not Connect to Linux "Abstract" Unix Socket

Can not connect to Linux abstract unix socket

While I was posting this question, and re-reading unix(7) man page, this wording caught my attention:

an abstract socket address is distinguished by the fact
that sun_path[0] is a null byte (’\0’). All of the remaining bytes
in sun_path define the "name" of the socket

So, if I bzero'ed the sun_path before filling in my name into it, things started to work. I figured that's not necessarily straight-forward. Additionally, as rightfully pointed out by @davmac and @StoneThrow, the number of those "remaining bytes" can be reduced by specifying only enough length of the socket address structure to cover the bytes you want to consider as your address. One way to do that is to use SUN_LEN macro, however, the first byte of the sun_path will have to be set to !0, as SUN_LEN uses strlen.

elaboration

If sun_path[0] is \0, The kernel uses the entirety of the remainder of sun_path as the name of the socket, whether it's \0-terminated or not, so all of that remainder counts. In my original code I would zero the first byte, and then strcpy() the socket name into the sun_path at position 1. Whatever gibberish that was in sun_path when the structure was allocated (especially likely to contain gibberish since it's allocated on the stack), and was included in the length of the socket structure (as passed to the syscalls), counted as the name of the socket, and was different in bind() and connect().

IMHO, strace should fix the way it displays abstract socket names, and display all the sun_path bytes from 1 to whatever the structure length that was supplied, if sun_path[0] is 0

Can not connect to an abstract unix socket in python

Your C++ doesn't do quite what you think it does. This line:

strncpy(addr.sun_path, UD_SOCKET_PATH, sizeof(addr.sun_path)-1);

Copies a single null character '\0' into addr.sun_path. Note this line in the manpage for strncpy():

If the length of src is less than n, strncpy() writes additional null
bytes to dest to ensure that a total of n bytes are written.

As a result your C++ actually connects to an abstract domain socket at "\0". Python does the right thing here and connects to an abstract domain socket at "\0hidden".

Bash: connect to Linux abstract UNIX socket

Modern versions of socat have an ABSTRACT namespace for just this purpose.

Quoting from the manual:

ABSTRACT-CONNECT:<string>

ABSTRACT-LISTEN:<string>

ABSTRACT-SENDTO:<string>

ABSTRACT-RECVFROM:<string>

ABSTRACT-RECV:<string>

ABSTRACT-CLIENT:<string>

The ABSTRACT addresses are almost identical to the related UNIX addresses except that they do not address file system based sockets but an alternate UNIX domain address space. To archieve this the socket address strings are prefixed with "\0" internally. This feature is available (only?) on Linux. Option groups are the same as with the related UNIX addresses, except that the ABSTRACT addresses are not member of the NAMED group.

‘Permission denied’ while connecting to abstract unix socket

Okay, here is the scoop it changed on L by a bug introduced..the bug fix is the pipeline:

https://android.googlesource.com/device/moto/shamu/+/b2db40f

Until than do java pipes or native pipes instead

How can one connect to an abstract namespace unix family address in nodejs?

It seems that special module should be used for:
https://www.npmjs.org/package/abstractsocket

Abstract Unix socket between C and Go

The Go program is connecting to the wrong abstract socket (or, equivalently, the C program is binding to the wrong abstract socket).

Your bind() is made against an abstract namespace UNIX socket address of length sizeof(struct sockaddr_un). If I am reading the Go implementation correctly, however, your connect() is performed against a socket address of length nine: two bytes for sa_family, and seven bytes, in this case, for len(name).

Those are different sockets.

In the abstract namespace, NULLs aren't special, so "\0uds-js" is one valid socket address, and "\0uds-js\0\0\0\0\0\0\0\0..." is a different valid address.

strace both processes looking at the C program's bind() and the Go program's connect(). I expect you will see that they call those functions with different socklen_t arguments.

Unix domain socket client won't connect

You are missing a parenthesis around this code in your client

if(sfd = socket(AF_UNIX, SOCK_STREAM, 0) > 0){

change it to

if((sfd = socket(AF_UNIX, SOCK_STREAM, 0)) > 0){

I also changed the server code to read as follows:

.
.
.

socklen_t csize;

while(1){

cfd = accept(sfd, (struct sockaddr *)&addr,&csize);

if (cfd < 0) {
printf("accept failed: %s\n", strerror(errno));
}
else{
printf("accept succeeded: %d\n", cfd);
}

.
.
.

And now it should work :)

Always be mindful of precedence of operators!

Why Connection refused got when connecting to LocalServerSocket from native program in Android

The problem is about the address length. From the offical reference example https://man7.org/linux/man-pages/man7/unix.7.html, the address length parament of connect() is sizeof(struct sockaddr_un).

It can work in normal Linux system (such as Ubuntu). But it can not work in android. From the source of libcutils:

https://android-opengrok.bangnimang.net/android-9.0.0_r61/xref/system/core/libcutils/socket_local_client_unix.cpp?r=db87e6d1#111

We can see the address length is set at the ending null character, not include the padding zeros.

*alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;

After changing the code as:

#define SOKET_NAME "@myaudsocket"
void connect() {
char* name = SOKET_NAME;
struct sockaddr_un addr;

// add this variant
int alen;

int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("failed to create socket");
return -1;
}

memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOKET_NAME, sizeof(addr.sun_path)-1);
if (name[0] == '@')
addr.sun_path[0] = '\0';

// Added this line
alen = offsetof(struct sockaddr_un, sun_path) + strlen(name);

// change sizeof(addr) to alen
if (connect(sock, (struct sockaddr *)&addr, alen) < 0) {
perror("failed to connect");
close(sock);
return -1;
}
}

It works.



Related Topics



Leave a reply



Submit