1 // RUN: %clang_dfsan %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t 2 // RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t 3 // RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t 4 // RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi %s -o %t && %run %t 5 6 // Tests custom implementations of various glibc functions. 7 8 #include <sanitizer/dfsan_interface.h> 9 10 #include <arpa/inet.h> 11 #include <assert.h> 12 #include <fcntl.h> 13 #include <link.h> 14 #include <poll.h> 15 #include <pthread.h> 16 #include <pwd.h> 17 #include <sched.h> 18 #include <signal.h> 19 #include <stdio.h> 20 #include <stdint.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 = (char *) calloc(4096, 1); 260 ASSERT_ZERO_LABEL(crv[0]); 261 dfsan_set_label(i_label, crv, 100); 262 free(crv); 263 264 crv = (char *) 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 unsigned char *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 = (const unsigned char*) 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 = (char *) memchr(str1, 'r', sizeof(str1)); 698 assert(crv == &str1[2]); 699 ASSERT_ZERO_LABEL(crv); 700 701 crv = (char *) 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 = (char *) 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 template <class T> 778 void test_sprintf_chunk(const char* expected, const char* format, T arg) { 779 char buf[512]; 780 memset(buf, 'a', sizeof(buf)); 781 782 char padded_expected[512]; 783 strcpy(padded_expected, "foo "); 784 strcat(padded_expected, expected); 785 strcat(padded_expected, " bar"); 786 787 char padded_format[512]; 788 strcpy(padded_format, "foo "); 789 strcat(padded_format, format); 790 strcat(padded_format, " bar"); 791 792 // Non labelled arg. 793 assert(sprintf(buf, padded_format, arg) == strlen(padded_expected)); 794 assert(strcmp(buf, padded_expected) == 0); 795 ASSERT_READ_LABEL(buf, strlen(padded_expected), 0); 796 memset(buf, 'a', sizeof(buf)); 797 798 // Labelled arg. 799 dfsan_set_label(i_label, &arg, sizeof(arg)); 800 assert(sprintf(buf, padded_format, arg) == strlen(padded_expected)); 801 assert(strcmp(buf, padded_expected) == 0); 802 ASSERT_READ_LABEL(buf, 4, 0); 803 ASSERT_READ_LABEL(buf + 4, strlen(padded_expected) - 8, i_label); 804 ASSERT_READ_LABEL(buf + (strlen(padded_expected) - 4), 4, 0); 805 } 806 807 void test_sprintf() { 808 char buf[2048]; 809 memset(buf, 'a', sizeof(buf)); 810 811 // Test formatting (no conversion specifier). 812 assert(sprintf(buf, "Hello world!") == 12); 813 assert(strcmp(buf, "Hello world!") == 0); 814 ASSERT_READ_LABEL(buf, sizeof(buf), 0); 815 816 // Test for extra arguments. 817 assert(sprintf(buf, "Hello world!", 42, "hello") == 12); 818 assert(strcmp(buf, "Hello world!") == 0); 819 ASSERT_READ_LABEL(buf, sizeof(buf), 0); 820 821 // Test formatting & label propagation (multiple conversion specifiers): %s, 822 // %d, %n, %f, and %%. 823 const char* s = "world"; 824 int m = 8; 825 int d = 27; 826 dfsan_set_label(k_label, (void *) (s + 1), 2); 827 dfsan_set_label(i_label, &m, sizeof(m)); 828 dfsan_set_label(j_label, &d, sizeof(d)); 829 int n; 830 int r = sprintf(buf, "hello %s, %-d/%d/%d %f %% %n%d", s, 2014, m, d, 831 12345.6781234, &n, 1000); 832 assert(r == 42); 833 assert(strcmp(buf, "hello world, 2014/8/27 12345.678123 % 1000") == 0); 834 ASSERT_READ_LABEL(buf, 7, 0); 835 ASSERT_READ_LABEL(buf + 7, 2, k_label); 836 ASSERT_READ_LABEL(buf + 9, 9, 0); 837 ASSERT_READ_LABEL(buf + 18, 1, i_label); 838 ASSERT_READ_LABEL(buf + 19, 1, 0); 839 ASSERT_READ_LABEL(buf + 20, 2, j_label); 840 ASSERT_READ_LABEL(buf + 22, 15, 0); 841 ASSERT_LABEL(r, 0); 842 assert(n == 38); 843 844 // Test formatting & label propagation (single conversion specifier, with 845 // additional length and precision modifiers). 846 test_sprintf_chunk("-559038737", "%d", 0xdeadbeef); 847 test_sprintf_chunk("3735928559", "%u", 0xdeadbeef); 848 test_sprintf_chunk("12345", "%i", 12345); 849 test_sprintf_chunk("751", "%o", 0751); 850 test_sprintf_chunk("babe", "%x", 0xbabe); 851 test_sprintf_chunk("0000BABE", "%.8X", 0xbabe); 852 test_sprintf_chunk("-17", "%hhd", 0xdeadbeef); 853 test_sprintf_chunk("-16657", "%hd", 0xdeadbeef); 854 test_sprintf_chunk("deadbeefdeadbeef", "%lx", 0xdeadbeefdeadbeef); 855 test_sprintf_chunk("0xdeadbeefdeadbeef", "%p", 856 (void *) 0xdeadbeefdeadbeef); 857 test_sprintf_chunk("18446744073709551615", "%ju", (intmax_t) -1); 858 test_sprintf_chunk("18446744073709551615", "%zu", (size_t) -1); 859 test_sprintf_chunk("18446744073709551615", "%tu", (size_t) -1); 860 861 test_sprintf_chunk("0x1.f9acffa7eb6bfp-4", "%a", 0.123456); 862 test_sprintf_chunk("0X1.F9ACFFA7EB6BFP-4", "%A", 0.123456); 863 test_sprintf_chunk("0.12346", "%.5f", 0.123456); 864 test_sprintf_chunk("0.123456", "%g", 0.123456); 865 test_sprintf_chunk("1.234560e-01", "%e", 0.123456); 866 test_sprintf_chunk("1.234560E-01", "%E", 0.123456); 867 test_sprintf_chunk("0.1234567891234560", "%.16Lf", 868 (long double) 0.123456789123456); 869 870 test_sprintf_chunk("z", "%c", 'z'); 871 872 // %n, %s, %d, %f, and %% already tested 873 874 // Test formatting with width passed as an argument. 875 r = sprintf(buf, "hi %*d my %*s friend %.*f", 3, 1, 6, "dear", 4, 3.14159265359); 876 assert(r == 30); 877 assert(strcmp(buf, "hi 1 my dear friend 3.1416") == 0); 878 } 879 880 void test_snprintf() { 881 char buf[2048]; 882 memset(buf, 'a', sizeof(buf)); 883 dfsan_set_label(0, buf, sizeof(buf)); 884 const char* s = "world"; 885 int y = 2014; 886 int m = 8; 887 int d = 27; 888 dfsan_set_label(k_label, (void *) (s + 1), 2); 889 dfsan_set_label(i_label, &y, sizeof(y)); 890 dfsan_set_label(j_label, &m, sizeof(m)); 891 int r = snprintf(buf, 19, "hello %s, %-d/%d/%d %f", s, y, m, d, 892 12345.6781234); 893 // The return value is the number of bytes that would have been written to 894 // the final string if enough space had been available. 895 assert(r == 35); 896 assert(memcmp(buf, "hello world, 2014/", 19) == 0); 897 ASSERT_READ_LABEL(buf, 7, 0); 898 ASSERT_READ_LABEL(buf + 7, 2, k_label); 899 ASSERT_READ_LABEL(buf + 9, 4, 0); 900 ASSERT_READ_LABEL(buf + 13, 4, i_label); 901 ASSERT_READ_LABEL(buf + 17, 2, 0); 902 ASSERT_LABEL(r, 0); 903 } 904 905 int main(void) { 906 i_label = dfsan_create_label("i", 0); 907 j_label = dfsan_create_label("j", 0); 908 k_label = dfsan_create_label("k", 0); 909 i_j_label = dfsan_union(i_label, j_label); 910 911 test_calloc(); 912 test_clock_gettime(); 913 test_ctime_r(); 914 test_dfsan_set_write_callback(); 915 test_dl_iterate_phdr(); 916 test_dlopen(); 917 test_fgets(); 918 test_fstat(); 919 test_get_current_dir_name(); 920 test_getcwd(); 921 test_gethostname(); 922 test_getpwuid_r(); 923 test_getrlimit(); 924 test_getrusage(); 925 test_gettimeofday(); 926 test_inet_pton(); 927 test_localtime_r(); 928 test_memchr(); 929 test_memcmp(); 930 test_memcpy(); 931 test_memset(); 932 test_nanosleep(); 933 test_poll(); 934 test_pread(); 935 test_pthread_create(); 936 test_read(); 937 test_sched_getaffinity(); 938 test_select(); 939 test_sigaction(); 940 test_sigemptyset(); 941 test_snprintf(); 942 test_socketpair(); 943 test_sprintf(); 944 test_stat(); 945 test_strcasecmp(); 946 test_strchr(); 947 test_strcmp(); 948 test_strcpy(); 949 test_strdup(); 950 test_strlen(); 951 test_strncasecmp(); 952 test_strncmp(); 953 test_strncpy(); 954 test_strrchr(); 955 test_strstr(); 956 test_strtod(); 957 test_strtol(); 958 test_strtoll(); 959 test_strtoul(); 960 test_strtoull(); 961 test_time(); 962 test_write(); 963 } 964