4

As I understand it, a unix domain socket is a file (with its own FS inode) that internally points to a socket inode (namespaced internally by the kernel). This is evident by inspecting the file descriptors of the binding process, returning a value such as socket:[345678].

Typically, unix domain sockets can be mv/rm'd, etc. within the same filesystem, as their own file inodes do not change in such instances (as mv is just a hard link + unlink, conceptually).

However, if I wanted to move a socket file to a new filesystem, such that a new filesystem inode would have to be allocated to the socket file, I'd need to somehow register that new socket file with the underlying socket descriptor in the kernel.

Is there a way to do this, transparently and without affecting the running, bound server process?

Particularly interested in doing this in C, but conceptually understanding this is also helpful. It's probably worth mentioning that, I assume, mknod() will be involved, and that's OK in this case. I just have no idea how to go about invoking it correctly.

Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
  • 1
    For Linux, you could use an "abstract" socket instead of a "pathname" socket. – Ian Abbott Jun 14 '22 at 15:46
  • Yes of course, but that would require having the ability to control binding application. – Qix - MONICA WAS MISTREATED Jun 14 '22 at 16:01
  • Since filesystems and file descriptors are both controlled inside kernel space, you'd have to do the bulk of the work there. You'd pretty much have to create a new "move Unix socket between different filesystems" system call. – Andrew Henle Jun 14 '22 at 16:13
  • I note that the `mv` command evidently *can* move device files and named pipes across filesystems — presumably it knows how to recreate them. Have you tried moving a Unix-domain socket in this way? Does the `mv` command succeed, or throw an error? – Steve Summit Jun 14 '22 at 16:45
  • I think that it is more likely to affect clients than the server — the server will continue to run, but new clients will (probably) be unable to connect to the server because the old name no longer exists and the new name isn't the one bound by the server. But, I should emphasize, I have not tested this. – Jonathan Leffler Jun 14 '22 at 16:48
  • The socket gets copied but the few tests I made resulted in the client being unable to connect (connection refused). It has nothing to do with names, just the underlying inodes as far as I'm aware. Moving it from within the same filesystem and then connecting to it works fine. – Qix - MONICA WAS MISTREATED Jun 14 '22 at 16:58
  • I guess moving a named pipe (FIFO) to another filesystem would have exactly the same problem as moving a named socket. – Ian Abbott Jun 14 '22 at 17:24

1 Answers1

0

At least under Linux, no.

Unix domain socket endpoints are identified internally via the unique tuple consisting of their st_dev value and st_ino value, as described in this libfuse ticket.

Even under a FUSE filesystem, the kernel enforces that st_dev always accurately reflects that of the underlying filesystem entry. Thus, unless the kernel were to be patched to allow faking of st_dev, or to edit the socket device/inode numbers, this is not possible - even with something like FUSE.

Further, starting in Linux kernel 5.3, SYS_pidfd_getfd could theoretically be used to clone a file descriptor from the target process to the current process (assuming you have PTRACE caps set), but you're stuck there as you cannot re-bind() the socket to a new location after the original bind was already created.

This is, quite simply, not possible.

Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145