A tiny library to send file descriptors across processes
github.com
github.com
int send_fd(int conn, int fd_to_send)
{
struct msghdr msg = { 0 };
struct cmsghdr * hdr;
char buf[CMSG_SPACE(sizeof(int))];
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
hdr = CMSG_FIRSTHDR(&msg);
hdr->cmsg_len = CMSG_LEN(sizeof(int));
hdr->cmsg_level = SOL_SOCKET;
hdr->cmsg_type = SCM_RIGHTS;
*(int*)CMSG_DATA(hdr) = fd_to_send;
return sendmsg(conn, &msg, 0);
}
To those wondering why and when this is needed - it is useful for cases when your primary process lacks rights required to open a file or a device (!). So another, privileged process does the open on its behalf and sends the resulting file descriptor to the primary process for processing.But be careful with who can connect to that socket and grab that fd. If you just name that socket and then tell another process to open it, there's a race. In a traditional privsep scenario the socket between the privileged and unprivileged process is created prior to and shared between them with fork(). Other scenarios (e.g. daemon serving fds to local clients that weren't initially there), you'll need some way to communicate with that client before you can tell it to grab the fd; why not use that ipc socket?
EDIT: Just to clarify, I'm commenting on the approach used by the linked library on github.
I must be misunderstanding something. I assume that the unprivileged process still cannot actually read the file, otherwise you could access unauthorized open files by going through every possible file descriptor. What processing can the unprivileged process do? Keep track processes that have open files?
Receiving the fd via this mechanism is very different that just getting the number of the fd. Nothing is really passed over the socket, rather behind the scenes the kernel is remapping memory within the calling process. It's very similar to what happens when a process 'forks' and its file descriptors are duplicated, but with individual fd granularity.
[1] There are exceptions to this in certain device handlers that use file interfaces, but it holds for regular files.
[1] I'm not sure about security frameworks, it may be e.g. SELinux provides more granular checks.
qmail-1.03:
fd.h fd_copy.c fd_copy.3 fd_move.c fd_move.3
You could find similar functions in other programs by the same author, e.g., ucspi-tcp, daemontools, etc.
I prefer time-tested, secure code from 1995 to the things you tend to find on Github because this 1990's code is highly portable. It still compiles cleanly 18 years later and is not just tested on one or two systems, e.g., Linux and OSX.
But I'm glad this made the front page. No web browser needed. No installed scripting languages necessary. A single .c file. If only there were more like this on Github.
Also there's a few places where ERRNO is going to get clobbered, eg. by closing the socket before reporting the error back to the caller. A more careful implementation would save errno before calling close.
Otherwise though, good simple abstraction of a relatively obscure feature.
You can then DoS the process by sending it huge numbers of fds instead of just one, which it will omit to close, and thus run out of file descriptors. So to be safe you need to iterate over all the fds and close them.
Some older UNIX variants only supported the BSD4.3-style msg_accrights style fd passing, although those are probably nearly extinct at this point.
as far as i remember, chrome also uses this method.
alternatively you can use libancillary.
v1 or v2?