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

READ/DOWNLOAD=? Kotlin Programming: The Big Nerd Ranch Guide FULL BOOK PDF & FULL AUDIOBOOK

a column must appear in the GROUP BY clause or be used in an aggregate function, When I don't to…

10 useful CSS properties you can start using today

The changes I missed in the latest versions of Ruby

Building A Python Slackbot That Actually Works

Part 2— Data Structures and Algorithms in Plain English

AMA with NetVRK

Clyde: Discord Bot Commands

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

Functional Programming as a Competitive Advantage — A Real-World Use-Case

Incident resolution procedure at Audiense

How to Design a Better Command Line Interface

Making Unplanned Interrupts Self-Service with Argo Workflows