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 | |