File Descriptor Transfer over Unix Domain Sockets

Unix Domain Sockets

UDS: A Brief Primer

Socket Files != Normal Files

root@1fd53621847b:~/uds# ./uds
^C
root@1fd53621847b:~/uds# ls -ls /tmp
total 0
0 srwxr-xr-x 1 root root 0 Aug 5 01:45 uds.sock
root@1fd53621847b:~/uds# stat /tmp/uds.sock
File: /tmp/uds.sock
Size: 0 Blocks: 0 IO Block: 4096 socket
Device: 71h/113d Inode: 1835567 Links: 1
Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-08-05 01:45:41.650709000 +0000
Modify: 2020-08-05 01:45:41.650709000 +0000
Change: 2020-08-05 01:45:41.650709000 +0000
Birth: -root@5247072fc542:~/uds# ls -F /tmp
uds.sock=
root@5247072fc542:~/uds#
struct sockaddr_un {
sa_family_t sun_family; /* Always AF_UNIX */
char sun_path[108]; /* Pathname */
};
struct sockaddr_un {
u_char sun_len;
u_char sun_family;
char sun_path[104];
};

bind(2) will fail when trying to bind to an existing path

int fd = socket(domain, socktype, 0);int optval = 1;
setsockopt(sfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
bind(sfd, (struct sockaddr *) &addr, addrlen);

SOCKETPAIR(2)

Data Transfer over UDS

File Descriptors vs File Description

sendmsg and recvmsg

ssize_t sendmsg(
int socket,
const struct msghdr *message,
int flags
);
ssize_t recvmsg(
int sockfd,
const struct msghdr *msg,
int flags
);
struct msghdr {
void *msg_name; /* optional address */
socklen_t msg_namelen; /* size of address */
struct iovec *msg_iov; /* scatter/gather array */
int msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, see below */
socklen_t msg_controllen; /* ancillary data buffer len */
int msg_flags; /* flags on received message */
};
struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including header */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by */
unsigned char cmsg_data[];
};

Ancillary Data Transfer

struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *msgh);
struct cmsghdr *CMSG_NXTHDR(struct msghdr *
msgh, struct cmsghdr *cmsg);
size_t CMSG_ALIGN(size_t
length);
size_t CMSG_SPACE(size_t
length);
size_t CMSG_LEN(size_t
length);
unsigned char *CMSG_DATA(struct cmsghdr *
cmsg);

SCM_RIGHTS

struct cmsghdr {
socklen_t cmsg_len; /* data byte count, including header */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
/* followed by */
unsigned char cmsg_data[];
};

SCM_RIGHTS Gotchas

Need to send some “real” data along with the ancillary message

File Descriptors can be dropped

recvmsg quirks

Limit on the number of File Descriptions

When is it useful to transfer file descriptors?

Conclusion

References:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store