| 1 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -DPOISONFD -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG |
| 2 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -DPOISONCRED -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG |
| 3 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -DPOISONLEN -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG |
| 4 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -DPOISONLEVEL -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG |
| 5 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -DPOISONTYPE -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG |
| 6 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -DPOISONLEN2 -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG |
| 7 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -DPOISONLEVEL2 -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG |
| 8 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -DPOISONTYPE2 -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG |
| 9 | // RUN: %clangxx_msan %s -std=c++11 -DSENDMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE |
| 10 | |
| 11 | // UNSUPPORTED: android |
| 12 | |
| 13 | #include <assert.h> |
| 14 | #include <stdio.h> |
| 15 | #include <unistd.h> |
| 16 | #include <stdlib.h> |
| 17 | #include <string.h> |
| 18 | #include <errno.h> |
| 19 | #include <netdb.h> |
| 20 | #include <sys/types.h> |
| 21 | #include <sys/socket.h> |
| 22 | #include <sys/un.h> |
| 23 | #include <sanitizer/msan_interface.h> |
| 24 | |
| 25 | const int kBufSize = 10; |
| 26 | |
| 27 | int main() { |
| 28 | int ret; |
| 29 | char buf[kBufSize] = {0}; |
| 30 | pthread_t client_thread; |
| 31 | struct sockaddr_un serveraddr; |
| 32 | |
| 33 | int sock[2]; |
| 34 | ret = socketpair(AF_UNIX, SOCK_STREAM, protocol: 0, fds: sock); |
| 35 | assert(ret == 0); |
| 36 | |
| 37 | int sockfd = sock[0]; |
| 38 | |
| 39 | struct iovec iov[] = {{.iov_base: buf, .iov_len: 10}}; |
| 40 | struct msghdr msg = {.msg_name: 0}; |
| 41 | msg.msg_iov = iov; |
| 42 | msg.msg_iovlen = 1; |
| 43 | msg.msg_flags = 0; |
| 44 | |
| 45 | static const int kNumFds = 3; |
| 46 | char controlbuf[CMSG_SPACE(kNumFds * sizeof(int)) + |
| 47 | CMSG_SPACE(sizeof(struct ucred))]; |
| 48 | msg.msg_control = &controlbuf; |
| 49 | msg.msg_controllen = sizeof(controlbuf); |
| 50 | |
| 51 | struct cmsghdr *cmsg = (struct cmsghdr *)&controlbuf; |
| 52 | assert(cmsg); |
| 53 | int myfds[kNumFds]; |
| 54 | for (int &fd : myfds) |
| 55 | fd = sockfd; |
| 56 | #ifdef POISONFD |
| 57 | __msan_poison(&myfds[1], sizeof(int)); |
| 58 | #endif |
| 59 | cmsg->cmsg_level = SOL_SOCKET; |
| 60 | cmsg->cmsg_type = SCM_RIGHTS; |
| 61 | cmsg->cmsg_len = CMSG_LEN(kNumFds * sizeof(int)); |
| 62 | memcpy(CMSG_DATA(cmsg), src: myfds, n: kNumFds * sizeof(int)); |
| 63 | #ifdef POISONLEVEL |
| 64 | __msan_poison(&cmsg->cmsg_level, sizeof(cmsg->cmsg_level)); |
| 65 | #endif |
| 66 | #ifdef POISONTYPE |
| 67 | __msan_poison(&cmsg->cmsg_type, sizeof(cmsg->cmsg_type)); |
| 68 | #endif |
| 69 | #ifdef POISONLEN |
| 70 | __msan_poison(&cmsg->cmsg_len, sizeof(cmsg->cmsg_len)); |
| 71 | #endif |
| 72 | |
| 73 | cmsg = (struct cmsghdr *)(&controlbuf[CMSG_SPACE(kNumFds * sizeof(int))]); |
| 74 | assert(cmsg); |
| 75 | struct ucred cred = {.pid: getpid(), .uid: getuid(), .gid: getgid()}; |
| 76 | #ifdef POISONCRED |
| 77 | __msan_poison(&cred.uid, sizeof(cred.uid)); |
| 78 | #endif |
| 79 | cmsg->cmsg_level = SOL_SOCKET; |
| 80 | cmsg->cmsg_type = SCM_CREDENTIALS; |
| 81 | cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); |
| 82 | memcpy(CMSG_DATA(cmsg), src: &cred, n: sizeof(struct ucred)); |
| 83 | #ifdef POISONLEVEL2 |
| 84 | __msan_poison(&cmsg->cmsg_level, sizeof(cmsg->cmsg_level)); |
| 85 | #endif |
| 86 | #ifdef POISONTYPE2 |
| 87 | __msan_poison(&cmsg->cmsg_type, sizeof(cmsg->cmsg_type)); |
| 88 | #endif |
| 89 | #ifdef POISONLEN2 |
| 90 | __msan_poison(&cmsg->cmsg_len, sizeof(cmsg->cmsg_len)); |
| 91 | #endif |
| 92 | |
| 93 | ret = sendmsg(fd: sockfd, message: &msg, flags: 0); |
| 94 | // SENDMSG: MemorySanitizer: use-of-uninitialized-value |
| 95 | if (ret == -1) printf(format: "%d: %s\n" , errno, strerror(errno)); |
| 96 | assert(ret > 0); |
| 97 | |
| 98 | fprintf(stderr, format: "== done\n" ); |
| 99 | // NEGATIVE: == done |
| 100 | return 0; |
| 101 | } |
| 102 | |