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:

@copyconstruct on Twitter. views expressed on this blog are solely mine, not those of present or past employers.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

CS50-第三課notes-part 3

Login to Satoshi App

Top 3 signs that you need modern AWS cloud operations (CloudOps)

Logarithms?

Open Hardware Distribution and Documentation Working Group: The importance of a name

What Is Nim?

How To Start A DevOps Career Even Without Prior Experience In Technology

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
Cindy Sridharan

Cindy Sridharan

@copyconstruct on Twitter. views expressed on this blog are solely mine, not those of present or past employers.

More from Medium

Deploy Socket.io to Kubernetes - Part 0: Overview

Deploy and Configure Kustomize and MongoDB in Kubernetes Stateful Applications

Couple of tips for K8s operator beginner developer

The SRE series: add a worker node to Kubernetes