socket: add support for sending and receiving descriptors

Add support for the SCM_RIGHTS control message used in communication
with the privops helper.
This commit is contained in:
Miroslav Lichvar 2019-11-18 18:04:43 +01:00
parent c4d6f98bed
commit f231efb811
2 changed files with 30 additions and 4 deletions

View file

@ -630,12 +630,15 @@ init_message_nonaddress(SCK_Message *message)
message->timestamp.if_index = INVALID_IF_INDEX; message->timestamp.if_index = INVALID_IF_INDEX;
message->timestamp.l2_length = 0; message->timestamp.l2_length = 0;
message->timestamp.tx_flags = 0; message->timestamp.tx_flags = 0;
message->descriptor = INVALID_SOCK_FD;
} }
/* ================================================== */ /* ================================================== */
static int static int
process_header(struct msghdr *msg, unsigned int msg_length, int sock_fd, SCK_Message *message) process_header(struct msghdr *msg, unsigned int msg_length, int sock_fd, int flags,
SCK_Message *message)
{ {
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
@ -773,6 +776,18 @@ process_header(struct msghdr *msg, unsigned int msg_length, int sock_fd, SCK_Mes
} }
} }
#endif #endif
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
if (!(flags & SCK_FLAG_MSG_DESCRIPTOR) || cmsg->cmsg_len != CMSG_LEN(sizeof (int))) {
unsigned int i;
DEBUG_LOG("Unexpected SCM_RIGHTS");
for (i = 0; CMSG_LEN((i + 1) * sizeof (int)) <= cmsg->cmsg_len; i++)
close(((int *)CMSG_DATA(cmsg))[i]);
return 0;
}
message->descriptor = *(int *)CMSG_DATA(cmsg);
}
} }
return 1; return 1;
@ -823,7 +838,7 @@ receive_messages(int sock_fd, SCK_Message *messages, int max_messages, int flags
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
hdr = ARR_GetElement(recv_headers, i); hdr = ARR_GetElement(recv_headers, i);
if (!process_header(&hdr->msg_hdr, hdr->msg_len, sock_fd, &messages[i])) if (!process_header(&hdr->msg_hdr, hdr->msg_len, sock_fd, flags, &messages[i]))
return 0; return 0;
log_message(sock_fd, 1, &messages[i], log_message(sock_fd, 1, &messages[i],
@ -876,8 +891,6 @@ send_message(int sock_fd, SCK_Message *message, int flags)
struct msghdr msg; struct msghdr msg;
struct iovec iov; struct iovec iov;
assert(flags == 0);
switch (message->addr_type) { switch (message->addr_type) {
case SCK_ADDR_UNSPEC: case SCK_ADDR_UNSPEC:
saddr_len = 0; saddr_len = 0;
@ -974,6 +987,16 @@ send_message(int sock_fd, SCK_Message *message, int flags)
} }
#endif #endif
if (flags & SCK_FLAG_MSG_DESCRIPTOR) {
int *fd;
fd = add_control_message(&msg, SOL_SOCKET, SCM_RIGHTS, sizeof (*fd), sizeof (cmsg_buf));
if (!fd)
return 0;
*fd = message->descriptor;
}
/* This is apparently required on some systems */ /* This is apparently required on some systems */
if (msg.msg_controllen == 0) if (msg.msg_controllen == 0)
msg.msg_control = NULL; msg.msg_control = NULL;

View file

@ -38,6 +38,7 @@
/* Flags for receiving and sending messages */ /* Flags for receiving and sending messages */
#define SCK_FLAG_MSG_ERRQUEUE 1 #define SCK_FLAG_MSG_ERRQUEUE 1
#define SCK_FLAG_MSG_DESCRIPTOR 2
/* Maximum number of received messages */ /* Maximum number of received messages */
#define SCK_MAX_RECV_MESSAGES 4 #define SCK_MAX_RECV_MESSAGES 4
@ -70,6 +71,8 @@ typedef struct {
int l2_length; int l2_length;
int tx_flags; int tx_flags;
} timestamp; } timestamp;
int descriptor;
} SCK_Message; } SCK_Message;
/* Initialisation function */ /* Initialisation function */