Skip to content

Commit 7bc7501

Browse files
committed
[DFSan] Add custom wrapper for recvmmsg.
Uses the recvmsg wrapper logic in a loop. Reviewed By: stephan.yichao.zhao Differential Revision: https://reviews.llvm.org/D93059
1 parent 4f25e53 commit 7bc7501

File tree

3 files changed

+90
-12
lines changed

3 files changed

+90
-12
lines changed

compiler-rt/lib/dfsan/dfsan_custom.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -916,22 +916,40 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
916916
return ret;
917917
}
918918

919+
static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) {
920+
dfsan_set_label(0, msg, sizeof(*msg));
921+
dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
922+
dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
923+
for (size_t i = 0; bytes_written > 0; ++i) {
924+
assert(i < msg->msg_iovlen);
925+
struct iovec *iov = &msg->msg_iov[i];
926+
size_t iov_written =
927+
bytes_written < iov->iov_len ? bytes_written : iov->iov_len;
928+
dfsan_set_label(0, iov->iov_base, iov_written);
929+
bytes_written -= iov_written;
930+
}
931+
}
932+
933+
SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_recvmmsg(
934+
int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
935+
struct timespec *timeout, dfsan_label sockfd_label,
936+
dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
937+
dfsan_label timeout_label, dfsan_label *ret_label) {
938+
int ret = recvmmsg(sockfd, msgvec, vlen, flags, timeout);
939+
for (int i = 0; i < ret; ++i) {
940+
dfsan_set_label(0, &msgvec[i].msg_len, sizeof(msgvec[i].msg_len));
941+
clear_msghdr_labels(msgvec[i].msg_len, &msgvec[i].msg_hdr);
942+
}
943+
*ret_label = 0;
944+
return ret;
945+
}
946+
919947
SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
920948
int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
921949
dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
922950
ssize_t ret = recvmsg(sockfd, msg, flags);
923-
if (ret >= 0) {
924-
dfsan_set_label(0, msg, sizeof(*msg));
925-
dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
926-
dfsan_set_label(0, msg->msg_control, msg->msg_controllen);
927-
for (size_t remaining = ret, i = 0; remaining > 0; ++i) {
928-
assert(i < msg->msg_iovlen);
929-
struct iovec *iov = &msg->msg_iov[i];
930-
size_t written = remaining < iov->iov_len ? remaining : iov->iov_len;
931-
dfsan_set_label(0, iov->iov_base, written);
932-
remaining -= written;
933-
}
934-
}
951+
if (ret >= 0)
952+
clear_msghdr_labels(ret, msg);
935953
*ret_label = 0;
936954
return ret;
937955
}

compiler-rt/lib/dfsan/done_abilist.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ fun:getsockopt=custom
201201
fun:nanosleep=custom
202202
fun:pread=custom
203203
fun:read=custom
204+
fun:recvmmsg=custom
204205
fun:recvmsg=custom
205206
fun:sigaltstack=custom
206207
fun:socketpair=custom

compiler-rt/test/dfsan/custom.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,64 @@ void test_calloc() {
337337
free(crv);
338338
}
339339

340+
void test_recvmmsg() {
341+
int sockfds[2];
342+
int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds);
343+
assert(ret != -1);
344+
345+
// Setup messages to send.
346+
struct mmsghdr smmsg[2] = {};
347+
char sbuf0[] = "abcdefghijkl";
348+
struct iovec siov0[2] = {{&sbuf0[0], 4}, {&sbuf0[4], 4}};
349+
smmsg[0].msg_hdr.msg_iov = siov0;
350+
smmsg[0].msg_hdr.msg_iovlen = 2;
351+
char sbuf1[] = "1234567890";
352+
struct iovec siov1[1] = {{&sbuf1[0], 7}};
353+
smmsg[1].msg_hdr.msg_iov = siov1;
354+
smmsg[1].msg_hdr.msg_iovlen = 1;
355+
356+
// Send messages.
357+
int sent_msgs = sendmmsg(sockfds[0], smmsg, 2, 0);
358+
assert(sent_msgs == 2);
359+
360+
// Setup receive buffers.
361+
struct mmsghdr rmmsg[2] = {};
362+
char rbuf0[128];
363+
struct iovec riov0[2] = {{&rbuf0[0], 4}, {&rbuf0[4], 4}};
364+
rmmsg[0].msg_hdr.msg_iov = riov0;
365+
rmmsg[0].msg_hdr.msg_iovlen = 2;
366+
char rbuf1[128];
367+
struct iovec riov1[1] = {{&rbuf1[0], 16}};
368+
rmmsg[1].msg_hdr.msg_iov = riov1;
369+
rmmsg[1].msg_hdr.msg_iovlen = 1;
370+
struct timespec timeout = {1, 1};
371+
dfsan_set_label(i_label, rbuf0, sizeof(rbuf0));
372+
dfsan_set_label(i_label, rbuf1, sizeof(rbuf1));
373+
dfsan_set_label(i_label, &rmmsg[0].msg_len, sizeof(rmmsg[0].msg_len));
374+
dfsan_set_label(i_label, &rmmsg[1].msg_len, sizeof(rmmsg[1].msg_len));
375+
dfsan_set_label(i_label, &timeout, sizeof(timeout));
376+
377+
// Receive messages and check labels.
378+
int received_msgs = recvmmsg(sockfds[1], rmmsg, 2, 0, &timeout);
379+
assert(received_msgs == sent_msgs);
380+
assert(rmmsg[0].msg_len == smmsg[0].msg_len);
381+
assert(rmmsg[1].msg_len == smmsg[1].msg_len);
382+
assert(memcmp(sbuf0, rbuf0, 8) == 0);
383+
assert(memcmp(sbuf1, rbuf1, 7) == 0);
384+
ASSERT_ZERO_LABEL(received_msgs);
385+
ASSERT_ZERO_LABEL(rmmsg[0].msg_len);
386+
ASSERT_ZERO_LABEL(rmmsg[1].msg_len);
387+
ASSERT_READ_ZERO_LABEL(&rbuf0[0], 8);
388+
ASSERT_READ_LABEL(&rbuf0[8], 1, i_label);
389+
ASSERT_READ_ZERO_LABEL(&rbuf1[0], 7);
390+
ASSERT_READ_LABEL(&rbuf1[7], 1, i_label);
391+
ASSERT_LABEL(timeout.tv_sec, i_label);
392+
ASSERT_LABEL(timeout.tv_nsec, i_label);
393+
394+
close(sockfds[0]);
395+
close(sockfds[1]);
396+
}
397+
340398
void test_recvmsg() {
341399
int sockfds[2];
342400
int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds);
@@ -1226,6 +1284,7 @@ int main(void) {
12261284
test_pthread_create();
12271285
test_pthread_join();
12281286
test_read();
1287+
test_recvmmsg();
12291288
test_recvmsg();
12301289
test_sched_getaffinity();
12311290
test_select();

0 commit comments

Comments
 (0)