Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Unix domain sockets have a severe limitation that the path must be a maximum 108 characters.


Sure, but all these services listening on ports, sometimes not even bound to localhost is just shitty. There's no authentication. and it's actually a huge contributor to database dumped online. Besides the security, ease of selecting a path vs a free port, it's also faster


Agreed. It's just that UDS are hard to work with due to this limitation.


This limitation only applies to the file name, as you can chdir to the directory before bind/connect. Unfortunate but not a deal breaker


> you can chdir to the directory before bind/connect

Since working directory is per-process not per-thread, this seems a great way to introduce race condition bugs. It also basically rules it out for anything meant to be used as a library or framework.


Working directory can be changed on a per-thread basis on Mac with pthread_chdir_np, and on Linux you can create a thread with the clone syscall and without the CLONE_FS flag to avoid sharing working directory with the rest of the process. I don't know about Windows.


I think the answer on Windows is "No".

One could fork a subprocess, chdir()+socket() there, then pass the socket back to parent over another socket (opened maybe with socketpair().) Should work on any Unix-like which supports SCM_RIGHTS (which is almost everybody, apparently even obscure platforms like AIX, IBM i, z/OS). But not Windows, which doesn't (at least not yet, they may add it at some point.)

Makes one really wish there was a bindat() call:

  int bindat(int sockfd, const struct sockaddr *addr, socklen_t addrlen, int dirfd);
or maybe funixsockat:

  int funixsockat(int type, int dirfd, const char * name);
which would combine socket() and bind() in a single call


In Windows we actually have a way to set the parent directory for a UDS bind or connect, via a socket ioctl. It’s not documented yet, but it’s in the header.


Cool, did not know that. Indeed I see this in shared/afunix.h:

    #define SIO_AF_UNIX_GETPEERPID _WSAIOR(IOC_VENDOR, 256) // Returns ULONG PID of the connected peer process
    #define SIO_AF_UNIX_SETBINDPARENTPATH _WSAIOW(IOC_VENDOR, 257) // Set the parent path for bind calls
    #define SIO_AF_UNIX_SETCONNPARENTPATH _WSAIOW(IOC_VENDOR, 258) // Set the parent path for connect calls
    // NOTE: setting the parent path is not thread safe.
SIO_AF_UNIX_GETPEERPID is something I did not know about either, although apparently a bit buggy – https://github.com/microsoft/WSL/issues/4676

What does the "NOTE: setting the parent path is not thread safe" comment mean? Not thread safe if multiple threads are sharing the same socket? (Which seems like an acceptable limitation.) Or something worse than that?


Is anybody trying to lift that limitation? It seems like an obvious target for kernel devs to tackle.

If Linux and *BSD did it (especially if they adopted a mutually compatible implementation), the POSIX standardisation team (Austin Group) would likely be interested in adding it to POSIX, and Windows/macOS/AIX/etc will likely follow their example sooner or later.


Linux has an extension that allows an arbitrary string that is not tied to the filesystem. This makes it easier to stay within the limit or you can crypto hash an arbitrarily long string down to 108 chars.


This can be pretty dangerous because it is basically the same as using a TCP socket on localhost (assuming you are speaking of abstract sockets).


Even though you lose the filesystem-based security, you can still use SO_PEERCRED or getpeereid and validate the caller's UID is what you expect, something which Linux doesn't support on localhost TCP sockets. Requiring the client's UID (and maybe GID too) to be the same as your own is a sane default for services intended for per-user usage.


Yeah, abstract sockets, good points about security.


That’s plenty for most applications, no? /var/run/*.sock isn’t that many characters.


For many applications it is enough. For others, such as placing a UDS in a user's home directory or temp folder, it may not be. Often times you don't know ahead of time what the path may be.


Unix sockets should definitely not be in any non-tmpfs filesystem, subdirectories of /run are the sole place they should be.


Care to justify your advice?


They are ephemeral, they hold no data after being closed and backups of them aren't useful. Only the name is needed, therefore a tmpfs is the place to store them.


The name of the socket file/the fact that it exists contains data.

As a result, it's useful to keep them in non-tmpfs paths that can survive a reboot. That way, very simple programs can use them as sort of a config file: `$XDG_HOME/myprogram/do_xyz.sock`.

Additionally, persistent sockets created once at program install time can help coordinate multiple launches of whatever uses them (e.g. by having servers flock(2) the socket or fight over binding to it as a mutex). For programs whose "server" component isn't managed by a service manager, but can instead be launched many times in response to some user action, that can simplify things.


And if I want to run a daemon as a user where should the socket go?


For example the OpenSSH agent uses this path:

/run/user/$UID/openssh_agent

Several things place sockets there, some other stuff places the socket in a subdirectory.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: