Skip to content

Commit b71c6a4

Browse files
committed
Fix portability of SCM_RIGHTS
1 parent 09ad245 commit b71c6a4

1 file changed

Lines changed: 35 additions & 8 deletions

File tree

toolbelt/sockets.cc

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -573,16 +573,43 @@ absl::Status UnixSocket::ReceiveFds(std::vector<FileDescriptor> &fds,
573573
absl::StrFormat("EOF from socket while reading fds\n"));
574574
}
575575

576-
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
577-
if (cmsg == nullptr) {
578-
// This can happen, apparently.
579-
return absl::OkStatus();
576+
if ((msg.msg_flags & MSG_CTRUNC) != 0) {
577+
return absl::InternalError(
578+
"Control data was truncated while reading fds from unix socket");
580579
}
581-
int *fdptr = reinterpret_cast<int *>(CMSG_DATA(cmsg));
582-
int num_fds = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
583-
for (int i = 0; i < num_fds; i++) {
584-
fds.emplace_back(fdptr[i]);
580+
581+
bool saw_rights = false;
582+
int num_fds = 0;
583+
for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr;
584+
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
585+
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
586+
continue;
587+
}
588+
saw_rights = true;
589+
if (cmsg->cmsg_len < CMSG_LEN(0)) {
590+
return absl::InternalError(absl::StrFormat(
591+
"Invalid SCM_RIGHTS control length %zu while reading fds",
592+
static_cast<size_t>(cmsg->cmsg_len)));
593+
}
594+
size_t data_len = cmsg->cmsg_len - CMSG_LEN(0);
595+
if (data_len % sizeof(int) != 0) {
596+
return absl::InternalError(absl::StrFormat(
597+
"Misaligned SCM_RIGHTS control length %zu while reading fds",
598+
static_cast<size_t>(cmsg->cmsg_len)));
599+
}
600+
int *fdptr = reinterpret_cast<int *>(CMSG_DATA(cmsg));
601+
int fds_in_message = static_cast<int>(data_len / sizeof(int));
602+
for (int i = 0; i < fds_in_message; i++) {
603+
fds.emplace_back(fdptr[i]);
604+
}
605+
num_fds += fds_in_message;
585606
}
607+
if (!saw_rights && total_fds > 0) {
608+
return absl::InternalError(absl::StrFormat(
609+
"Expected %d fds from unix socket but received no SCM_RIGHTS message",
610+
total_fds));
611+
}
612+
586613
// Add the number we received in this message to the total.
587614
num_fds_received += num_fds;
588615

0 commit comments

Comments
 (0)