]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // RUN: %clang_dfsan -m64 %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t |
2 | // RUN: %clang_dfsan -mllvm -dfsan-args-abi -m64 %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t | |
3 | // RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -m64 %s -o %t && %run %t | |
4 | // RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi -m64 %s -o %t && %run %t | |
5 | ||
6 | // Tests custom implementations of various glibc functions. | |
7 | ||
8 | #define _GNU_SOURCE | |
9 | #include <sanitizer/dfsan_interface.h> | |
10 | ||
11 | #include <arpa/inet.h> | |
12 | #include <assert.h> | |
13 | #include <fcntl.h> | |
14 | #include <link.h> | |
15 | #include <poll.h> | |
16 | #include <pthread.h> | |
17 | #include <pwd.h> | |
18 | #include <sched.h> | |
19 | #include <signal.h> | |
20 | #include <stdio.h> | |
21 | #include <stdlib.h> | |
22 | #include <string.h> | |
23 | #include <sys/select.h> | |
24 | #include <sys/resource.h> | |
25 | #include <sys/stat.h> | |
26 | #include <sys/time.h> | |
27 | #include <sys/types.h> | |
28 | #include <time.h> | |
29 | #include <unistd.h> | |
30 | ||
31 | dfsan_label i_label = 0; | |
32 | dfsan_label j_label = 0; | |
33 | dfsan_label k_label = 0; | |
34 | dfsan_label i_j_label = 0; | |
35 | ||
36 | #define ASSERT_ZERO_LABEL(data) \ | |
37 | assert(0 == dfsan_get_label((long) (data))) | |
38 | ||
39 | #define ASSERT_READ_ZERO_LABEL(ptr, size) \ | |
40 | assert(0 == dfsan_read_label(ptr, size)) | |
41 | ||
42 | #define ASSERT_LABEL(data, label) \ | |
43 | assert(label == dfsan_get_label((long) (data))) | |
44 | ||
45 | #define ASSERT_READ_LABEL(ptr, size, label) \ | |
46 | assert(label == dfsan_read_label(ptr, size)) | |
47 | ||
48 | void test_stat() { | |
49 | int i = 1; | |
50 | dfsan_set_label(i_label, &i, sizeof(i)); | |
51 | ||
52 | struct stat s; | |
53 | s.st_dev = i; | |
54 | assert(0 == stat("/", &s)); | |
55 | ASSERT_ZERO_LABEL(s.st_dev); | |
56 | ||
57 | s.st_dev = i; | |
58 | assert(-1 == stat("/nonexistent", &s)); | |
59 | ASSERT_LABEL(s.st_dev, i_label); | |
60 | } | |
61 | ||
62 | void test_fstat() { | |
63 | int i = 1; | |
64 | dfsan_set_label(i_label, &i, sizeof(i)); | |
65 | ||
66 | struct stat s; | |
67 | int fd = open("/dev/zero", O_RDONLY); | |
68 | s.st_dev = i; | |
69 | int rv = fstat(fd, &s); | |
70 | assert(0 == rv); | |
71 | ASSERT_ZERO_LABEL(s.st_dev); | |
72 | } | |
73 | ||
74 | void test_memcmp() { | |
75 | char str1[] = "str1", str2[] = "str2"; | |
76 | dfsan_set_label(i_label, &str1[3], 1); | |
77 | dfsan_set_label(j_label, &str2[3], 1); | |
78 | ||
79 | int rv = memcmp(str1, str2, sizeof(str1)); | |
80 | assert(rv < 0); | |
81 | #ifdef STRICT_DATA_DEPENDENCIES | |
82 | ASSERT_ZERO_LABEL(rv); | |
83 | #else | |
84 | ASSERT_LABEL(rv, i_j_label); | |
85 | #endif | |
86 | } | |
87 | ||
88 | void test_memcpy() { | |
89 | char str1[] = "str1"; | |
90 | char str2[sizeof(str1)]; | |
91 | dfsan_set_label(i_label, &str1[3], 1); | |
92 | ||
93 | ASSERT_ZERO_LABEL(memcpy(str2, str1, sizeof(str1))); | |
94 | assert(0 == memcmp(str2, str1, sizeof(str1))); | |
95 | ASSERT_ZERO_LABEL(str2[0]); | |
96 | ASSERT_LABEL(str2[3], i_label); | |
97 | } | |
98 | ||
99 | void test_memset() { | |
100 | char buf[8]; | |
101 | int j = 'a'; | |
102 | dfsan_set_label(j_label, &j, sizeof(j)); | |
103 | ||
104 | ASSERT_ZERO_LABEL(memset(&buf, j, sizeof(buf))); | |
105 | for (int i = 0; i < 8; ++i) { | |
106 | ASSERT_LABEL(buf[i], j_label); | |
107 | assert(buf[i] == 'a'); | |
108 | } | |
109 | } | |
110 | ||
111 | void test_strcmp() { | |
112 | char str1[] = "str1", str2[] = "str2"; | |
113 | dfsan_set_label(i_label, &str1[3], 1); | |
114 | dfsan_set_label(j_label, &str2[3], 1); | |
115 | ||
116 | int rv = strcmp(str1, str2); | |
117 | assert(rv < 0); | |
118 | #ifdef STRICT_DATA_DEPENDENCIES | |
119 | ASSERT_ZERO_LABEL(rv); | |
120 | #else | |
121 | ASSERT_LABEL(rv, i_j_label); | |
122 | #endif | |
123 | } | |
124 | ||
125 | void test_strlen() { | |
126 | char str1[] = "str1"; | |
127 | dfsan_set_label(i_label, &str1[3], 1); | |
128 | ||
129 | int rv = strlen(str1); | |
130 | assert(rv == 4); | |
131 | #ifdef STRICT_DATA_DEPENDENCIES | |
132 | ASSERT_ZERO_LABEL(rv); | |
133 | #else | |
134 | ASSERT_LABEL(rv, i_label); | |
135 | #endif | |
136 | } | |
137 | ||
138 | void test_strdup() { | |
139 | char str1[] = "str1"; | |
140 | dfsan_set_label(i_label, &str1[3], 1); | |
141 | ||
142 | char *strd = strdup(str1); | |
143 | ASSERT_ZERO_LABEL(strd[0]); | |
144 | ASSERT_LABEL(strd[3], i_label); | |
145 | free(strd); | |
146 | } | |
147 | ||
148 | void test_strncpy() { | |
149 | char str1[] = "str1"; | |
150 | char str2[sizeof(str1)]; | |
151 | dfsan_set_label(i_label, &str1[3], 1); | |
152 | ||
153 | char *strd = strncpy(str2, str1, 5); | |
154 | assert(strd == str2); | |
155 | assert(strcmp(str1, str2) == 0); | |
156 | ASSERT_ZERO_LABEL(strd); | |
157 | ASSERT_ZERO_LABEL(strd[0]); | |
158 | ASSERT_ZERO_LABEL(strd[1]); | |
159 | ASSERT_ZERO_LABEL(strd[2]); | |
160 | ASSERT_LABEL(strd[3], i_label); | |
161 | ||
162 | strd = strncpy(str2, str1, 3); | |
163 | assert(strd == str2); | |
164 | assert(strncmp(str1, str2, 3) == 0); | |
165 | ASSERT_ZERO_LABEL(strd); | |
166 | ASSERT_ZERO_LABEL(strd[0]); | |
167 | ASSERT_ZERO_LABEL(strd[1]); | |
168 | ASSERT_ZERO_LABEL(strd[2]); | |
169 | } | |
170 | ||
171 | void test_strncmp() { | |
172 | char str1[] = "str1", str2[] = "str2"; | |
173 | dfsan_set_label(i_label, &str1[3], 1); | |
174 | dfsan_set_label(j_label, &str2[3], 1); | |
175 | ||
176 | int rv = strncmp(str1, str2, sizeof(str1)); | |
177 | assert(rv < 0); | |
178 | #ifdef STRICT_DATA_DEPENDENCIES | |
179 | ASSERT_ZERO_LABEL(rv); | |
180 | #else | |
181 | ASSERT_LABEL(rv, dfsan_union(i_label, j_label)); | |
182 | #endif | |
183 | ||
184 | rv = strncmp(str1, str2, 3); | |
185 | assert(rv == 0); | |
186 | ASSERT_ZERO_LABEL(rv); | |
187 | } | |
188 | ||
189 | void test_strcasecmp() { | |
190 | char str1[] = "str1", str2[] = "str2", str3[] = "Str1"; | |
191 | dfsan_set_label(i_label, &str1[3], 1); | |
192 | dfsan_set_label(j_label, &str2[3], 1); | |
193 | dfsan_set_label(j_label, &str3[2], 1); | |
194 | ||
195 | int rv = strcasecmp(str1, str2); | |
196 | assert(rv < 0); | |
197 | #ifdef STRICT_DATA_DEPENDENCIES | |
198 | ASSERT_ZERO_LABEL(rv); | |
199 | #else | |
200 | ASSERT_LABEL(rv, dfsan_union(i_label, j_label)); | |
201 | #endif | |
202 | ||
203 | rv = strcasecmp(str1, str3); | |
204 | assert(rv == 0); | |
205 | #ifdef STRICT_DATA_DEPENDENCIES | |
206 | ASSERT_ZERO_LABEL(rv); | |
207 | #else | |
208 | ASSERT_LABEL(rv, dfsan_union(i_label, j_label)); | |
209 | #endif | |
210 | } | |
211 | ||
212 | void test_strncasecmp() { | |
213 | char str1[] = "Str1", str2[] = "str2"; | |
214 | dfsan_set_label(i_label, &str1[3], 1); | |
215 | dfsan_set_label(j_label, &str2[3], 1); | |
216 | ||
217 | int rv = strncasecmp(str1, str2, sizeof(str1)); | |
218 | assert(rv < 0); | |
219 | #ifdef STRICT_DATA_DEPENDENCIES | |
220 | ASSERT_ZERO_LABEL(rv); | |
221 | #else | |
222 | ASSERT_LABEL(rv, dfsan_union(i_label, j_label)); | |
223 | #endif | |
224 | ||
225 | rv = strncasecmp(str1, str2, 3); | |
226 | assert(rv == 0); | |
227 | ASSERT_ZERO_LABEL(rv); | |
228 | } | |
229 | ||
230 | void test_strchr() { | |
231 | char str1[] = "str1"; | |
232 | dfsan_set_label(i_label, &str1[3], 1); | |
233 | ||
234 | char *crv = strchr(str1, 'r'); | |
235 | assert(crv == &str1[2]); | |
236 | ASSERT_ZERO_LABEL(crv); | |
237 | ||
238 | crv = strchr(str1, '1'); | |
239 | assert(crv == &str1[3]); | |
240 | #ifdef STRICT_DATA_DEPENDENCIES | |
241 | ASSERT_ZERO_LABEL(crv); | |
242 | #else | |
243 | ASSERT_LABEL(crv, i_label); | |
244 | #endif | |
245 | ||
246 | crv = strchr(str1, 'x'); | |
247 | assert(!crv); | |
248 | #ifdef STRICT_DATA_DEPENDENCIES | |
249 | ASSERT_ZERO_LABEL(crv); | |
250 | #else | |
251 | ASSERT_LABEL(crv, i_label); | |
252 | #endif | |
253 | } | |
254 | ||
255 | void test_calloc() { | |
256 | // With any luck this sequence of calls will cause calloc to return the same | |
257 | // pointer both times. This is probably the best we can do to test this | |
258 | // function. | |
259 | char *crv = calloc(4096, 1); | |
260 | ASSERT_ZERO_LABEL(crv[0]); | |
261 | dfsan_set_label(i_label, crv, 100); | |
262 | free(crv); | |
263 | ||
264 | crv = calloc(4096, 1); | |
265 | ASSERT_ZERO_LABEL(crv[0]); | |
266 | free(crv); | |
267 | } | |
268 | ||
269 | void test_read() { | |
270 | char buf[16]; | |
271 | dfsan_set_label(i_label, buf, 1); | |
272 | dfsan_set_label(j_label, buf + 15, 1); | |
273 | ||
274 | ASSERT_LABEL(buf[0], i_label); | |
275 | ASSERT_LABEL(buf[15], j_label); | |
276 | ||
277 | int fd = open("/dev/zero", O_RDONLY); | |
278 | int rv = read(fd, buf, sizeof(buf)); | |
279 | assert(rv == sizeof(buf)); | |
280 | ASSERT_ZERO_LABEL(rv); | |
281 | ASSERT_ZERO_LABEL(buf[0]); | |
282 | ASSERT_ZERO_LABEL(buf[15]); | |
283 | close(fd); | |
284 | } | |
285 | ||
286 | void test_pread() { | |
287 | char buf[16]; | |
288 | dfsan_set_label(i_label, buf, 1); | |
289 | dfsan_set_label(j_label, buf + 15, 1); | |
290 | ||
291 | ASSERT_LABEL(buf[0], i_label); | |
292 | ASSERT_LABEL(buf[15], j_label); | |
293 | ||
294 | int fd = open("/bin/sh", O_RDONLY); | |
295 | int rv = pread(fd, buf, sizeof(buf), 0); | |
296 | assert(rv == sizeof(buf)); | |
297 | ASSERT_ZERO_LABEL(rv); | |
298 | ASSERT_ZERO_LABEL(buf[0]); | |
299 | ASSERT_ZERO_LABEL(buf[15]); | |
300 | close(fd); | |
301 | } | |
302 | ||
303 | void test_dlopen() { | |
304 | void *map = dlopen(NULL, RTLD_NOW); | |
305 | assert(map); | |
306 | ASSERT_ZERO_LABEL(map); | |
307 | dlclose(map); | |
308 | map = dlopen("/nonexistent", RTLD_NOW); | |
309 | assert(!map); | |
310 | ASSERT_ZERO_LABEL(map); | |
311 | } | |
312 | ||
313 | void test_clock_gettime() { | |
314 | struct timespec tp; | |
315 | dfsan_set_label(j_label, ((char *)&tp) + 3, 1); | |
316 | int t = clock_gettime(CLOCK_REALTIME, &tp); | |
317 | assert(t == 0); | |
318 | ASSERT_ZERO_LABEL(t); | |
319 | ASSERT_ZERO_LABEL(((char *)&tp)[3]); | |
320 | } | |
321 | ||
322 | void test_ctime_r() { | |
323 | char *buf = (char*) malloc(64); | |
324 | time_t t = 0; | |
325 | ||
326 | char *ret = ctime_r(&t, buf); | |
327 | ASSERT_ZERO_LABEL(ret); | |
328 | assert(buf == ret); | |
329 | ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1); | |
330 | ||
331 | dfsan_set_label(i_label, &t, sizeof(t)); | |
332 | ret = ctime_r(&t, buf); | |
333 | ASSERT_ZERO_LABEL(ret); | |
334 | ASSERT_READ_LABEL(buf, strlen(buf) + 1, i_label); | |
335 | ||
336 | t = 0; | |
337 | dfsan_set_label(j_label, &buf, sizeof(&buf)); | |
338 | ret = ctime_r(&t, buf); | |
339 | ASSERT_LABEL(ret, j_label); | |
340 | ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1); | |
341 | } | |
342 | ||
343 | static int write_callback_count = 0; | |
344 | static int last_fd; | |
345 | static const void *last_buf; | |
346 | static size_t last_count; | |
347 | ||
348 | void write_callback(int fd, const void *buf, size_t count) { | |
349 | write_callback_count++; | |
350 | ||
351 | last_fd = fd; | |
352 | last_buf = buf; | |
353 | last_count = count; | |
354 | } | |
355 | ||
356 | void test_dfsan_set_write_callback() { | |
357 | char buf[] = "Sample chars"; | |
358 | int buf_len = strlen(buf); | |
359 | ||
360 | int fd = open("/dev/null", O_WRONLY); | |
361 | ||
362 | dfsan_set_write_callback(write_callback); | |
363 | ||
364 | write_callback_count = 0; | |
365 | ||
366 | // Callback should be invoked on every call to write(). | |
367 | int res = write(fd, buf, buf_len); | |
368 | assert(write_callback_count == 1); | |
369 | ASSERT_READ_ZERO_LABEL(&res, sizeof(res)); | |
370 | ASSERT_READ_ZERO_LABEL(&last_fd, sizeof(last_fd)); | |
371 | ASSERT_READ_ZERO_LABEL(last_buf, sizeof(last_buf)); | |
372 | ASSERT_READ_ZERO_LABEL(&last_count, sizeof(last_count)); | |
373 | ||
374 | // Add a label to write() arguments. Check that the labels are readable from | |
375 | // the values passed to the callback. | |
376 | dfsan_set_label(i_label, &fd, sizeof(fd)); | |
377 | dfsan_set_label(j_label, &(buf[3]), 1); | |
378 | dfsan_set_label(k_label, &buf_len, sizeof(buf_len)); | |
379 | ||
380 | res = write(fd, buf, buf_len); | |
381 | assert(write_callback_count == 2); | |
382 | ASSERT_READ_ZERO_LABEL(&res, sizeof(res)); | |
383 | ASSERT_READ_LABEL(&last_fd, sizeof(last_fd), i_label); | |
384 | ASSERT_READ_LABEL(&last_buf[3], sizeof(last_buf[3]), j_label); | |
385 | ASSERT_READ_LABEL(last_buf, sizeof(last_buf), j_label); | |
386 | ASSERT_READ_LABEL(&last_count, sizeof(last_count), k_label); | |
387 | ||
388 | dfsan_set_write_callback(NULL); | |
389 | } | |
390 | ||
391 | void test_fgets() { | |
392 | char *buf = (char*) malloc(128); | |
393 | FILE *f = fopen("/etc/passwd", "r"); | |
394 | dfsan_set_label(j_label, buf, 1); | |
395 | char *ret = fgets(buf, sizeof(buf), f); | |
396 | assert(ret == buf); | |
397 | ASSERT_ZERO_LABEL(ret); | |
398 | ASSERT_READ_ZERO_LABEL(buf, 128); | |
399 | dfsan_set_label(j_label, &buf, sizeof(&buf)); | |
400 | ret = fgets(buf, sizeof(buf), f); | |
401 | ASSERT_LABEL(ret, j_label); | |
402 | fclose(f); | |
403 | } | |
404 | ||
405 | void test_getcwd() { | |
406 | char buf[1024]; | |
407 | char *ptr = buf; | |
408 | dfsan_set_label(i_label, buf + 2, 2); | |
409 | char* ret = getcwd(buf, sizeof(buf)); | |
410 | assert(ret == buf); | |
411 | assert(ret[0] == '/'); | |
412 | ASSERT_READ_ZERO_LABEL(buf + 2, 2); | |
413 | dfsan_set_label(i_label, &ptr, sizeof(ptr)); | |
414 | ret = getcwd(ptr, sizeof(buf)); | |
415 | ASSERT_LABEL(ret, i_label); | |
416 | } | |
417 | ||
418 | void test_get_current_dir_name() { | |
419 | char* ret = get_current_dir_name(); | |
420 | assert(ret); | |
421 | assert(ret[0] == '/'); | |
422 | ASSERT_READ_ZERO_LABEL(ret, strlen(ret) + 1); | |
423 | } | |
424 | ||
425 | void test_gethostname() { | |
426 | char buf[1024]; | |
427 | dfsan_set_label(i_label, buf + 2, 2); | |
428 | assert(gethostname(buf, sizeof(buf)) == 0); | |
429 | ASSERT_READ_ZERO_LABEL(buf + 2, 2); | |
430 | } | |
431 | ||
432 | void test_getrlimit() { | |
433 | struct rlimit rlim; | |
434 | dfsan_set_label(i_label, &rlim, sizeof(rlim)); | |
435 | assert(getrlimit(RLIMIT_CPU, &rlim) == 0); | |
436 | ASSERT_READ_ZERO_LABEL(&rlim, sizeof(rlim)); | |
437 | } | |
438 | ||
439 | void test_getrusage() { | |
440 | struct rusage usage; | |
441 | dfsan_set_label(i_label, &usage, sizeof(usage)); | |
442 | assert(getrusage(RUSAGE_SELF, &usage) == 0); | |
443 | ASSERT_READ_ZERO_LABEL(&usage, sizeof(usage)); | |
444 | } | |
445 | ||
446 | void test_strcpy() { | |
447 | char src[] = "hello world"; | |
448 | char dst[sizeof(src) + 2]; | |
449 | dfsan_set_label(0, src, sizeof(src)); | |
450 | dfsan_set_label(0, dst, sizeof(dst)); | |
451 | dfsan_set_label(i_label, src + 2, 1); | |
452 | dfsan_set_label(j_label, src + 3, 1); | |
453 | dfsan_set_label(j_label, dst + 4, 1); | |
454 | dfsan_set_label(i_label, dst + 12, 1); | |
455 | char *ret = strcpy(dst, src); | |
456 | assert(ret == dst); | |
457 | assert(strcmp(src, dst) == 0); | |
458 | for (int i = 0; i < strlen(src) + 1; ++i) { | |
459 | assert(dfsan_get_label(dst[i]) == dfsan_get_label(src[i])); | |
460 | } | |
461 | // Note: if strlen(src) + 1 were used instead to compute the first untouched | |
462 | // byte of dest, the label would be I|J. This is because strlen() might | |
463 | // return a non-zero label, and because by default pointer labels are not | |
464 | // ignored on loads. | |
465 | ASSERT_LABEL(dst[12], i_label); | |
466 | } | |
467 | ||
468 | void test_strtol() { | |
469 | char buf[] = "1234578910"; | |
470 | char *endptr = NULL; | |
471 | dfsan_set_label(i_label, buf + 1, 1); | |
472 | dfsan_set_label(j_label, buf + 10, 1); | |
473 | long int ret = strtol(buf, &endptr, 10); | |
474 | assert(ret == 1234578910); | |
475 | assert(endptr == buf + 10); | |
476 | ASSERT_LABEL(ret, i_j_label); | |
477 | } | |
478 | ||
479 | void test_strtoll() { | |
480 | char buf[] = "1234578910 "; | |
481 | char *endptr = NULL; | |
482 | dfsan_set_label(i_label, buf + 1, 1); | |
483 | dfsan_set_label(j_label, buf + 2, 1); | |
484 | long long int ret = strtoll(buf, &endptr, 10); | |
485 | assert(ret == 1234578910); | |
486 | assert(endptr == buf + 10); | |
487 | ASSERT_LABEL(ret, i_j_label); | |
488 | } | |
489 | ||
490 | void test_strtoul() { | |
491 | char buf[] = "0xffffffffffffaa"; | |
492 | char *endptr = NULL; | |
493 | dfsan_set_label(i_label, buf + 1, 1); | |
494 | dfsan_set_label(j_label, buf + 2, 1); | |
495 | long unsigned int ret = strtol(buf, &endptr, 16); | |
496 | assert(ret == 72057594037927850); | |
497 | assert(endptr == buf + 16); | |
498 | ASSERT_LABEL(ret, i_j_label); | |
499 | } | |
500 | ||
501 | void test_strtoull() { | |
502 | char buf[] = "0xffffffffffffffaa"; | |
503 | char *endptr = NULL; | |
504 | dfsan_set_label(i_label, buf + 1, 1); | |
505 | dfsan_set_label(j_label, buf + 2, 1); | |
506 | long long unsigned int ret = strtoull(buf, &endptr, 16); | |
507 | assert(ret == 0xffffffffffffffaa); | |
508 | assert(endptr == buf + 18); | |
509 | ASSERT_LABEL(ret, i_j_label); | |
510 | } | |
511 | ||
512 | void test_strtod() { | |
513 | char buf[] = "12345.76 foo"; | |
514 | char *endptr = NULL; | |
515 | dfsan_set_label(i_label, buf + 1, 1); | |
516 | dfsan_set_label(j_label, buf + 6, 1); | |
517 | double ret = strtod(buf, &endptr); | |
518 | assert(ret == 12345.76); | |
519 | assert(endptr == buf + 8); | |
520 | ASSERT_LABEL(ret, i_j_label); | |
521 | } | |
522 | ||
523 | void test_time() { | |
524 | time_t t = 0; | |
525 | dfsan_set_label(i_label, &t, 1); | |
526 | time_t ret = time(&t); | |
527 | assert(ret == t); | |
528 | assert(ret > 0); | |
529 | ASSERT_ZERO_LABEL(t); | |
530 | } | |
531 | ||
532 | void test_inet_pton() { | |
533 | char addr4[] = "127.0.0.1"; | |
534 | dfsan_set_label(i_label, addr4 + 3, 1); | |
535 | struct in_addr in4; | |
536 | int ret4 = inet_pton(AF_INET, addr4, &in4); | |
537 | assert(ret4 == 1); | |
538 | ASSERT_READ_LABEL(&in4, sizeof(in4), i_label); | |
539 | assert(in4.s_addr == 0x0100007f); | |
540 | ||
541 | char addr6[] = "::1"; | |
542 | dfsan_set_label(j_label, addr6 + 3, 1); | |
543 | struct in6_addr in6; | |
544 | int ret6 = inet_pton(AF_INET6, addr6, &in6); | |
545 | assert(ret6 == 1); | |
546 | ASSERT_READ_LABEL(((char *) &in6) + sizeof(in6) - 1, 1, j_label); | |
547 | } | |
548 | ||
549 | void test_localtime_r() { | |
550 | time_t t0 = 1384800998; | |
551 | struct tm t1; | |
552 | dfsan_set_label(i_label, &t0, sizeof(t0)); | |
553 | struct tm* ret = localtime_r(&t0, &t1); | |
554 | assert(ret == &t1); | |
555 | assert(t1.tm_min == 56); | |
556 | ASSERT_LABEL(t1.tm_mon, i_label); | |
557 | } | |
558 | ||
559 | void test_getpwuid_r() { | |
560 | struct passwd pwd; | |
561 | char buf[1024]; | |
562 | struct passwd *result; | |
563 | ||
564 | dfsan_set_label(i_label, &pwd, 4); | |
565 | int ret = getpwuid_r(0, &pwd, buf, sizeof(buf), &result); | |
566 | assert(ret == 0); | |
567 | assert(strcmp(pwd.pw_name, "root") == 0); | |
568 | assert(result == &pwd); | |
569 | ASSERT_READ_ZERO_LABEL(&pwd, 4); | |
570 | } | |
571 | ||
572 | void test_poll() { | |
573 | struct pollfd fd; | |
574 | fd.fd = 0; | |
575 | fd.events = POLLIN; | |
576 | dfsan_set_label(i_label, &fd.revents, sizeof(fd.revents)); | |
577 | int ret = poll(&fd, 1, 1); | |
578 | ASSERT_ZERO_LABEL(fd.revents); | |
579 | assert(ret >= 0); | |
580 | } | |
581 | ||
582 | void test_select() { | |
583 | struct timeval t; | |
584 | fd_set fds; | |
585 | t.tv_sec = 2; | |
586 | FD_SET(0, &fds); | |
587 | dfsan_set_label(i_label, &fds, sizeof(fds)); | |
588 | dfsan_set_label(j_label, &t, sizeof(t)); | |
589 | int ret = select(1, &fds, NULL, NULL, &t); | |
590 | assert(ret >= 0); | |
591 | ASSERT_ZERO_LABEL(t.tv_sec); | |
592 | ASSERT_READ_ZERO_LABEL(&fds, sizeof(fds)); | |
593 | } | |
594 | ||
595 | void test_sched_getaffinity() { | |
596 | cpu_set_t mask; | |
597 | dfsan_set_label(j_label, &mask, 1); | |
598 | int ret = sched_getaffinity(0, sizeof(mask), &mask); | |
599 | assert(ret == 0); | |
600 | ASSERT_READ_ZERO_LABEL(&mask, sizeof(mask)); | |
601 | } | |
602 | ||
603 | void test_sigemptyset() { | |
604 | sigset_t set; | |
605 | dfsan_set_label(j_label, &set, 1); | |
606 | int ret = sigemptyset(&set); | |
607 | assert(ret == 0); | |
608 | ASSERT_READ_ZERO_LABEL(&set, sizeof(set)); | |
609 | } | |
610 | ||
611 | void test_sigaction() { | |
612 | struct sigaction oldact; | |
613 | dfsan_set_label(j_label, &oldact, 1); | |
614 | int ret = sigaction(SIGUSR1, NULL, &oldact); | |
615 | assert(ret == 0); | |
616 | ASSERT_READ_ZERO_LABEL(&oldact, sizeof(oldact)); | |
617 | } | |
618 | ||
619 | void test_gettimeofday() { | |
620 | struct timeval tv; | |
621 | struct timezone tz; | |
622 | dfsan_set_label(i_label, &tv, sizeof(tv)); | |
623 | dfsan_set_label(j_label, &tz, sizeof(tz)); | |
624 | int ret = gettimeofday(&tv, &tz); | |
625 | assert(ret == 0); | |
626 | ASSERT_READ_ZERO_LABEL(&tv, sizeof(tv)); | |
627 | ASSERT_READ_ZERO_LABEL(&tz, sizeof(tz)); | |
628 | } | |
629 | ||
630 | void *pthread_create_test_cb(void *p) { | |
631 | assert(p == (void *)1); | |
632 | ASSERT_ZERO_LABEL(p); | |
633 | return (void *)2; | |
634 | } | |
635 | ||
636 | void test_pthread_create() { | |
637 | pthread_t pt; | |
638 | pthread_create(&pt, 0, pthread_create_test_cb, (void *)1); | |
639 | void *cbrv; | |
640 | pthread_join(pt, &cbrv); | |
641 | assert(cbrv == (void *)2); | |
642 | } | |
643 | ||
644 | int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size, | |
645 | void *data) { | |
646 | assert(data == (void *)3); | |
647 | ASSERT_ZERO_LABEL(info); | |
648 | ASSERT_ZERO_LABEL(size); | |
649 | ASSERT_ZERO_LABEL(data); | |
650 | return 0; | |
651 | } | |
652 | ||
653 | void test_dl_iterate_phdr() { | |
654 | dl_iterate_phdr(dl_iterate_phdr_test_cb, (void *)3); | |
655 | } | |
656 | ||
657 | void test_strrchr() { | |
658 | char str1[] = "str1str1"; | |
659 | dfsan_set_label(i_label, &str1[7], 1); | |
660 | ||
661 | char *rv = strrchr(str1, 'r'); | |
662 | assert(rv == &str1[6]); | |
663 | #ifdef STRICT_DATA_DEPENDENCIES | |
664 | ASSERT_ZERO_LABEL(rv); | |
665 | #else | |
666 | ASSERT_LABEL(rv, i_label); | |
667 | #endif | |
668 | } | |
669 | ||
670 | void test_strstr() { | |
671 | char str1[] = "str1str1"; | |
672 | dfsan_set_label(i_label, &str1[3], 1); | |
673 | dfsan_set_label(j_label, &str1[5], 1); | |
674 | ||
675 | char *rv = strstr(str1, "1s"); | |
676 | assert(rv == &str1[3]); | |
677 | #ifdef STRICT_DATA_DEPENDENCIES | |
678 | ASSERT_ZERO_LABEL(rv); | |
679 | #else | |
680 | ASSERT_LABEL(rv, i_label); | |
681 | #endif | |
682 | ||
683 | rv = strstr(str1, "2s"); | |
684 | assert(rv == NULL); | |
685 | #ifdef STRICT_DATA_DEPENDENCIES | |
686 | ASSERT_ZERO_LABEL(rv); | |
687 | #else | |
688 | ASSERT_LABEL(rv, i_j_label); | |
689 | #endif | |
690 | } | |
691 | ||
692 | void test_memchr() { | |
693 | char str1[] = "str1"; | |
694 | dfsan_set_label(i_label, &str1[3], 1); | |
695 | dfsan_set_label(j_label, &str1[4], 1); | |
696 | ||
697 | char *crv = memchr(str1, 'r', sizeof(str1)); | |
698 | assert(crv == &str1[2]); | |
699 | ASSERT_ZERO_LABEL(crv); | |
700 | ||
701 | crv = memchr(str1, '1', sizeof(str1)); | |
702 | assert(crv == &str1[3]); | |
703 | #ifdef STRICT_DATA_DEPENDENCIES | |
704 | ASSERT_ZERO_LABEL(crv); | |
705 | #else | |
706 | ASSERT_LABEL(crv, i_label); | |
707 | #endif | |
708 | ||
709 | crv = memchr(str1, 'x', sizeof(str1)); | |
710 | assert(!crv); | |
711 | #ifdef STRICT_DATA_DEPENDENCIES | |
712 | ASSERT_ZERO_LABEL(crv); | |
713 | #else | |
714 | ASSERT_LABEL(crv, i_j_label); | |
715 | #endif | |
716 | } | |
717 | ||
718 | void alarm_handler(int unused) { | |
719 | ; | |
720 | } | |
721 | ||
722 | void test_nanosleep() { | |
723 | struct timespec req, rem; | |
724 | req.tv_sec = 1; | |
725 | req.tv_nsec = 0; | |
726 | dfsan_set_label(i_label, &rem, sizeof(rem)); | |
727 | ||
728 | // non interrupted | |
729 | int rv = nanosleep(&req, &rem); | |
730 | assert(rv == 0); | |
731 | ASSERT_ZERO_LABEL(rv); | |
732 | ASSERT_READ_LABEL(&rem, 1, i_label); | |
733 | ||
734 | // interrupted by an alarm | |
735 | signal(SIGALRM, alarm_handler); | |
736 | req.tv_sec = 3; | |
737 | alarm(1); | |
738 | rv = nanosleep(&req, &rem); | |
739 | assert(rv == -1); | |
740 | ASSERT_ZERO_LABEL(rv); | |
741 | ASSERT_READ_ZERO_LABEL(&rem, sizeof(rem)); | |
742 | } | |
743 | ||
744 | void test_socketpair() { | |
745 | int fd[2]; | |
746 | ||
747 | dfsan_set_label(i_label, fd, sizeof(fd)); | |
748 | int rv = socketpair(PF_LOCAL, SOCK_STREAM, 0, fd); | |
749 | assert(rv == 0); | |
750 | ASSERT_ZERO_LABEL(rv); | |
751 | ASSERT_READ_ZERO_LABEL(fd, sizeof(fd)); | |
752 | } | |
753 | ||
754 | void test_write() { | |
755 | int fd = open("/dev/null", O_WRONLY); | |
756 | ||
757 | char buf[] = "a string"; | |
758 | int len = strlen(buf); | |
759 | ||
760 | // The result of a write always unlabeled. | |
761 | int res = write(fd, buf, len); | |
762 | assert(res > 0); | |
763 | ASSERT_ZERO_LABEL(res); | |
764 | ||
765 | // Label all arguments to write(). | |
766 | dfsan_set_label(i_label, &(buf[3]), 1); | |
767 | dfsan_set_label(j_label, &fd, sizeof(fd)); | |
768 | dfsan_set_label(i_label, &len, sizeof(len)); | |
769 | ||
770 | // The value returned by write() should have no label. | |
771 | res = write(fd, buf, len); | |
772 | ASSERT_ZERO_LABEL(res); | |
773 | ||
774 | close(fd); | |
775 | } | |
776 | ||
777 | int main(void) { | |
778 | i_label = dfsan_create_label("i", 0); | |
779 | j_label = dfsan_create_label("j", 0); | |
780 | k_label = dfsan_create_label("k", 0); | |
781 | i_j_label = dfsan_union(i_label, j_label); | |
782 | ||
783 | test_calloc(); | |
784 | test_clock_gettime(); | |
785 | test_ctime_r(); | |
786 | test_dfsan_set_write_callback(); | |
787 | test_dl_iterate_phdr(); | |
788 | test_dlopen(); | |
789 | test_fgets(); | |
790 | test_fstat(); | |
791 | test_get_current_dir_name(); | |
792 | test_getcwd(); | |
793 | test_gethostname(); | |
794 | test_getpwuid_r(); | |
795 | test_getrlimit(); | |
796 | test_getrusage(); | |
797 | test_gettimeofday(); | |
798 | test_inet_pton(); | |
799 | test_localtime_r(); | |
800 | test_memchr(); | |
801 | test_memcmp(); | |
802 | test_memcpy(); | |
803 | test_memset(); | |
804 | test_nanosleep(); | |
805 | test_poll(); | |
806 | test_pread(); | |
807 | test_pthread_create(); | |
808 | test_read(); | |
809 | test_sched_getaffinity(); | |
810 | test_select(); | |
811 | test_sigaction(); | |
812 | test_sigemptyset(); | |
813 | test_socketpair(); | |
814 | test_stat(); | |
815 | test_strcasecmp(); | |
816 | test_strchr(); | |
817 | test_strcmp(); | |
818 | test_strcpy(); | |
819 | test_strdup(); | |
820 | test_strlen(); | |
821 | test_strncasecmp(); | |
822 | test_strncmp(); | |
823 | test_strncpy(); | |
824 | test_strrchr(); | |
825 | test_strstr(); | |
826 | test_strtod(); | |
827 | test_strtol(); | |
828 | test_strtoll(); | |
829 | test_strtoul(); | |
830 | test_strtoull(); | |
831 | test_time(); | |
832 | test_write(); | |
833 | } |