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 // `man strchr` says: 255 // The terminating null byte is considered part of the string, so that if c 256 // is specified as '\0', these functions return a pointer to the terminator. 257 crv = strchr(str1, '\0'); 258 assert(crv == &str1[4]); 259 #ifdef STRICT_DATA_DEPENDENCIES 260 ASSERT_ZERO_LABEL(crv); 261 #else 262 ASSERT_LABEL(crv, i_label); 263 #endif 264 } 265 266 void test_calloc() { 267 // With any luck this sequence of calls will cause calloc to return the same 268 // pointer both times. This is probably the best we can do to test this 269 // function. 270 char *crv = (char *) calloc(4096, 1); 271 ASSERT_ZERO_LABEL(crv[0]); 272 dfsan_set_label(i_label, crv, 100); 273 free(crv); 274 275 crv = (char *) calloc(4096, 1); 276 ASSERT_ZERO_LABEL(crv[0]); 277 free(crv); 278 } 279 280 void test_read() { 281 char buf[16]; 282 dfsan_set_label(i_label, buf, 1); 283 dfsan_set_label(j_label, buf + 15, 1); 284 285 ASSERT_LABEL(buf[0], i_label); 286 ASSERT_LABEL(buf[15], j_label); 287 288 int fd = open("/dev/zero", O_RDONLY); 289 int rv = read(fd, buf, sizeof(buf)); 290 assert(rv == sizeof(buf)); 291 ASSERT_ZERO_LABEL(rv); 292 ASSERT_ZERO_LABEL(buf[0]); 293 ASSERT_ZERO_LABEL(buf[15]); 294 close(fd); 295 } 296 297 void test_pread() { 298 char buf[16]; 299 dfsan_set_label(i_label, buf, 1); 300 dfsan_set_label(j_label, buf + 15, 1); 301 302 ASSERT_LABEL(buf[0], i_label); 303 ASSERT_LABEL(buf[15], j_label); 304 305 int fd = open("/bin/sh", O_RDONLY); 306 int rv = pread(fd, buf, sizeof(buf), 0); 307 assert(rv == sizeof(buf)); 308 ASSERT_ZERO_LABEL(rv); 309 ASSERT_ZERO_LABEL(buf[0]); 310 ASSERT_ZERO_LABEL(buf[15]); 311 close(fd); 312 } 313 314 void test_dlopen() { 315 void *map = dlopen(NULL, RTLD_NOW); 316 assert(map); 317 ASSERT_ZERO_LABEL(map); 318 dlclose(map); 319 map = dlopen("/nonexistent", RTLD_NOW); 320 assert(!map); 321 ASSERT_ZERO_LABEL(map); 322 } 323 324 void test_clock_gettime() { 325 struct timespec tp; 326 dfsan_set_label(j_label, ((char *)&tp) + 3, 1); 327 int t = clock_gettime(CLOCK_REALTIME, &tp); 328 assert(t == 0); 329 ASSERT_ZERO_LABEL(t); 330 ASSERT_ZERO_LABEL(((char *)&tp)[3]); 331 } 332 333 void test_ctime_r() { 334 char *buf = (char*) malloc(64); 335 time_t t = 0; 336 337 char *ret = ctime_r(&t, buf); 338 ASSERT_ZERO_LABEL(ret); 339 assert(buf == ret); 340 ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1); 341 342 dfsan_set_label(i_label, &t, sizeof(t)); 343 ret = ctime_r(&t, buf); 344 ASSERT_ZERO_LABEL(ret); 345 ASSERT_READ_LABEL(buf, strlen(buf) + 1, i_label); 346 347 t = 0; 348 dfsan_set_label(j_label, &buf, sizeof(&buf)); 349 ret = ctime_r(&t, buf); 350 ASSERT_LABEL(ret, j_label); 351 ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1); 352 } 353 354 static int write_callback_count = 0; 355 static int last_fd; 356 static const unsigned char *last_buf; 357 static size_t last_count; 358 359 void write_callback(int fd, const void *buf, size_t count) { 360 write_callback_count++; 361 362 last_fd = fd; 363 last_buf = (const unsigned char*) buf; 364 last_count = count; 365 } 366 367 void test_dfsan_set_write_callback() { 368 char buf[] = "Sample chars"; 369 int buf_len = strlen(buf); 370 371 int fd = open("/dev/null", O_WRONLY); 372 373 dfsan_set_write_callback(write_callback); 374 375 write_callback_count = 0; 376 377 // Callback should be invoked on every call to write(). 378 int res = write(fd, buf, buf_len); 379 assert(write_callback_count == 1); 380 ASSERT_READ_ZERO_LABEL(&res, sizeof(res)); 381 ASSERT_READ_ZERO_LABEL(&last_fd, sizeof(last_fd)); 382 ASSERT_READ_ZERO_LABEL(last_buf, sizeof(last_buf)); 383 ASSERT_READ_ZERO_LABEL(&last_count, sizeof(last_count)); 384 385 // Add a label to write() arguments. Check that the labels are readable from 386 // the values passed to the callback. 387 dfsan_set_label(i_label, &fd, sizeof(fd)); 388 dfsan_set_label(j_label, &(buf[3]), 1); 389 dfsan_set_label(k_label, &buf_len, sizeof(buf_len)); 390 391 res = write(fd, buf, buf_len); 392 assert(write_callback_count == 2); 393 ASSERT_READ_ZERO_LABEL(&res, sizeof(res)); 394 ASSERT_READ_LABEL(&last_fd, sizeof(last_fd), i_label); 395 ASSERT_READ_LABEL(&last_buf[3], sizeof(last_buf[3]), j_label); 396 ASSERT_READ_LABEL(last_buf, sizeof(last_buf), j_label); 397 ASSERT_READ_LABEL(&last_count, sizeof(last_count), k_label); 398 399 dfsan_set_write_callback(NULL); 400 } 401 402 void test_fgets() { 403 char *buf = (char*) malloc(128); 404 FILE *f = fopen("/etc/passwd", "r"); 405 dfsan_set_label(j_label, buf, 1); 406 char *ret = fgets(buf, sizeof(buf), f); 407 assert(ret == buf); 408 ASSERT_ZERO_LABEL(ret); 409 ASSERT_READ_ZERO_LABEL(buf, 128); 410 dfsan_set_label(j_label, &buf, sizeof(&buf)); 411 ret = fgets(buf, sizeof(buf), f); 412 ASSERT_LABEL(ret, j_label); 413 fclose(f); 414 } 415 416 void test_getcwd() { 417 char buf[1024]; 418 char *ptr = buf; 419 dfsan_set_label(i_label, buf + 2, 2); 420 char* ret = getcwd(buf, sizeof(buf)); 421 assert(ret == buf); 422 assert(ret[0] == '/'); 423 ASSERT_READ_ZERO_LABEL(buf + 2, 2); 424 dfsan_set_label(i_label, &ptr, sizeof(ptr)); 425 ret = getcwd(ptr, sizeof(buf)); 426 ASSERT_LABEL(ret, i_label); 427 } 428 429 void test_get_current_dir_name() { 430 char* ret = get_current_dir_name(); 431 assert(ret); 432 assert(ret[0] == '/'); 433 ASSERT_READ_ZERO_LABEL(ret, strlen(ret) + 1); 434 } 435 436 void test_gethostname() { 437 char buf[1024]; 438 dfsan_set_label(i_label, buf + 2, 2); 439 assert(gethostname(buf, sizeof(buf)) == 0); 440 ASSERT_READ_ZERO_LABEL(buf + 2, 2); 441 } 442 443 void test_getrlimit() { 444 struct rlimit rlim; 445 dfsan_set_label(i_label, &rlim, sizeof(rlim)); 446 assert(getrlimit(RLIMIT_CPU, &rlim) == 0); 447 ASSERT_READ_ZERO_LABEL(&rlim, sizeof(rlim)); 448 } 449 450 void test_getrusage() { 451 struct rusage usage; 452 dfsan_set_label(i_label, &usage, sizeof(usage)); 453 assert(getrusage(RUSAGE_SELF, &usage) == 0); 454 ASSERT_READ_ZERO_LABEL(&usage, sizeof(usage)); 455 } 456 457 void test_strcpy() { 458 char src[] = "hello world"; 459 char dst[sizeof(src) + 2]; 460 dfsan_set_label(0, src, sizeof(src)); 461 dfsan_set_label(0, dst, sizeof(dst)); 462 dfsan_set_label(i_label, src + 2, 1); 463 dfsan_set_label(j_label, src + 3, 1); 464 dfsan_set_label(j_label, dst + 4, 1); 465 dfsan_set_label(i_label, dst + 12, 1); 466 char *ret = strcpy(dst, src); 467 assert(ret == dst); 468 assert(strcmp(src, dst) == 0); 469 for (int i = 0; i < strlen(src) + 1; ++i) { 470 assert(dfsan_get_label(dst[i]) == dfsan_get_label(src[i])); 471 } 472 // Note: if strlen(src) + 1 were used instead to compute the first untouched 473 // byte of dest, the label would be I|J. This is because strlen() might 474 // return a non-zero label, and because by default pointer labels are not 475 // ignored on loads. 476 ASSERT_LABEL(dst[12], i_label); 477 } 478 479 void test_strtol() { 480 char buf[] = "1234578910"; 481 char *endptr = NULL; 482 dfsan_set_label(i_label, buf + 1, 1); 483 dfsan_set_label(j_label, buf + 10, 1); 484 long int ret = strtol(buf, &endptr, 10); 485 assert(ret == 1234578910); 486 assert(endptr == buf + 10); 487 ASSERT_LABEL(ret, i_j_label); 488 } 489 490 void test_strtoll() { 491 char buf[] = "1234578910 "; 492 char *endptr = NULL; 493 dfsan_set_label(i_label, buf + 1, 1); 494 dfsan_set_label(j_label, buf + 2, 1); 495 long long int ret = strtoll(buf, &endptr, 10); 496 assert(ret == 1234578910); 497 assert(endptr == buf + 10); 498 ASSERT_LABEL(ret, i_j_label); 499 } 500 501 void test_strtoul() { 502 char buf[] = "0xffffffffffffaa"; 503 char *endptr = NULL; 504 dfsan_set_label(i_label, buf + 1, 1); 505 dfsan_set_label(j_label, buf + 2, 1); 506 long unsigned int ret = strtol(buf, &endptr, 16); 507 assert(ret == 72057594037927850); 508 assert(endptr == buf + 16); 509 ASSERT_LABEL(ret, i_j_label); 510 } 511 512 void test_strtoull() { 513 char buf[] = "0xffffffffffffffaa"; 514 char *endptr = NULL; 515 dfsan_set_label(i_label, buf + 1, 1); 516 dfsan_set_label(j_label, buf + 2, 1); 517 long long unsigned int ret = strtoull(buf, &endptr, 16); 518 assert(ret == 0xffffffffffffffaa); 519 assert(endptr == buf + 18); 520 ASSERT_LABEL(ret, i_j_label); 521 } 522 523 void test_strtod() { 524 char buf[] = "12345.76 foo"; 525 char *endptr = NULL; 526 dfsan_set_label(i_label, buf + 1, 1); 527 dfsan_set_label(j_label, buf + 6, 1); 528 double ret = strtod(buf, &endptr); 529 assert(ret == 12345.76); 530 assert(endptr == buf + 8); 531 ASSERT_LABEL(ret, i_j_label); 532 } 533 534 void test_time() { 535 time_t t = 0; 536 dfsan_set_label(i_label, &t, 1); 537 time_t ret = time(&t); 538 assert(ret == t); 539 assert(ret > 0); 540 ASSERT_ZERO_LABEL(t); 541 } 542 543 void test_inet_pton() { 544 char addr4[] = "127.0.0.1"; 545 dfsan_set_label(i_label, addr4 + 3, 1); 546 struct in_addr in4; 547 int ret4 = inet_pton(AF_INET, addr4, &in4); 548 assert(ret4 == 1); 549 ASSERT_READ_LABEL(&in4, sizeof(in4), i_label); 550 assert(in4.s_addr == htonl(0x7f000001)); 551 552 char addr6[] = "::1"; 553 dfsan_set_label(j_label, addr6 + 3, 1); 554 struct in6_addr in6; 555 int ret6 = inet_pton(AF_INET6, addr6, &in6); 556 assert(ret6 == 1); 557 ASSERT_READ_LABEL(((char *) &in6) + sizeof(in6) - 1, 1, j_label); 558 } 559 560 void test_localtime_r() { 561 time_t t0 = 1384800998; 562 struct tm t1; 563 dfsan_set_label(i_label, &t0, sizeof(t0)); 564 struct tm* ret = localtime_r(&t0, &t1); 565 assert(ret == &t1); 566 assert(t1.tm_min == 56); 567 ASSERT_LABEL(t1.tm_mon, i_label); 568 } 569 570 void test_getpwuid_r() { 571 struct passwd pwd; 572 char buf[1024]; 573 struct passwd *result; 574 575 dfsan_set_label(i_label, &pwd, 4); 576 int ret = getpwuid_r(0, &pwd, buf, sizeof(buf), &result); 577 assert(ret == 0); 578 assert(strcmp(pwd.pw_name, "root") == 0); 579 assert(result == &pwd); 580 ASSERT_READ_ZERO_LABEL(&pwd, 4); 581 } 582 583 void test_poll() { 584 struct pollfd fd; 585 fd.fd = 0; 586 fd.events = POLLIN; 587 dfsan_set_label(i_label, &fd.revents, sizeof(fd.revents)); 588 int ret = poll(&fd, 1, 1); 589 ASSERT_ZERO_LABEL(fd.revents); 590 assert(ret >= 0); 591 } 592 593 void test_select() { 594 struct timeval t; 595 fd_set fds; 596 t.tv_sec = 2; 597 FD_SET(0, &fds); 598 dfsan_set_label(i_label, &fds, sizeof(fds)); 599 dfsan_set_label(j_label, &t, sizeof(t)); 600 int ret = select(1, &fds, NULL, NULL, &t); 601 assert(ret >= 0); 602 ASSERT_ZERO_LABEL(t.tv_sec); 603 ASSERT_READ_ZERO_LABEL(&fds, sizeof(fds)); 604 } 605 606 void test_sched_getaffinity() { 607 cpu_set_t mask; 608 dfsan_set_label(j_label, &mask, 1); 609 int ret = sched_getaffinity(0, sizeof(mask), &mask); 610 assert(ret == 0); 611 ASSERT_READ_ZERO_LABEL(&mask, sizeof(mask)); 612 } 613 614 void test_sigemptyset() { 615 sigset_t set; 616 dfsan_set_label(j_label, &set, 1); 617 int ret = sigemptyset(&set); 618 assert(ret == 0); 619 ASSERT_READ_ZERO_LABEL(&set, sizeof(set)); 620 } 621 622 void test_sigaction() { 623 struct sigaction oldact; 624 dfsan_set_label(j_label, &oldact, 1); 625 int ret = sigaction(SIGUSR1, NULL, &oldact); 626 assert(ret == 0); 627 ASSERT_READ_ZERO_LABEL(&oldact, sizeof(oldact)); 628 } 629 630 void test_gettimeofday() { 631 struct timeval tv; 632 struct timezone tz; 633 dfsan_set_label(i_label, &tv, sizeof(tv)); 634 dfsan_set_label(j_label, &tz, sizeof(tz)); 635 int ret = gettimeofday(&tv, &tz); 636 assert(ret == 0); 637 ASSERT_READ_ZERO_LABEL(&tv, sizeof(tv)); 638 ASSERT_READ_ZERO_LABEL(&tz, sizeof(tz)); 639 } 640 641 void *pthread_create_test_cb(void *p) { 642 assert(p == (void *)1); 643 ASSERT_ZERO_LABEL(p); 644 return (void *)2; 645 } 646 647 void test_pthread_create() { 648 pthread_t pt; 649 pthread_create(&pt, 0, pthread_create_test_cb, (void *)1); 650 void *cbrv; 651 pthread_join(pt, &cbrv); 652 assert(cbrv == (void *)2); 653 } 654 655 int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size, 656 void *data) { 657 assert(data == (void *)3); 658 ASSERT_ZERO_LABEL(info); 659 ASSERT_ZERO_LABEL(size); 660 ASSERT_ZERO_LABEL(data); 661 return 0; 662 } 663 664 void test_dl_iterate_phdr() { 665 dl_iterate_phdr(dl_iterate_phdr_test_cb, (void *)3); 666 } 667 668 void test_strrchr() { 669 char str1[] = "str1str1"; 670 dfsan_set_label(i_label, &str1[7], 1); 671 672 char *rv = strrchr(str1, 'r'); 673 assert(rv == &str1[6]); 674 #ifdef STRICT_DATA_DEPENDENCIES 675 ASSERT_ZERO_LABEL(rv); 676 #else 677 ASSERT_LABEL(rv, i_label); 678 #endif 679 } 680 681 void test_strstr() { 682 char str1[] = "str1str1"; 683 dfsan_set_label(i_label, &str1[3], 1); 684 dfsan_set_label(j_label, &str1[5], 1); 685 686 char *rv = strstr(str1, "1s"); 687 assert(rv == &str1[3]); 688 #ifdef STRICT_DATA_DEPENDENCIES 689 ASSERT_ZERO_LABEL(rv); 690 #else 691 ASSERT_LABEL(rv, i_label); 692 #endif 693 694 rv = strstr(str1, "2s"); 695 assert(rv == NULL); 696 #ifdef STRICT_DATA_DEPENDENCIES 697 ASSERT_ZERO_LABEL(rv); 698 #else 699 ASSERT_LABEL(rv, i_j_label); 700 #endif 701 } 702 703 void test_memchr() { 704 char str1[] = "str1"; 705 dfsan_set_label(i_label, &str1[3], 1); 706 dfsan_set_label(j_label, &str1[4], 1); 707 708 char *crv = (char *) memchr(str1, 'r', sizeof(str1)); 709 assert(crv == &str1[2]); 710 ASSERT_ZERO_LABEL(crv); 711 712 crv = (char *) memchr(str1, '1', sizeof(str1)); 713 assert(crv == &str1[3]); 714 #ifdef STRICT_DATA_DEPENDENCIES 715 ASSERT_ZERO_LABEL(crv); 716 #else 717 ASSERT_LABEL(crv, i_label); 718 #endif 719 720 crv = (char *) memchr(str1, 'x', sizeof(str1)); 721 assert(!crv); 722 #ifdef STRICT_DATA_DEPENDENCIES 723 ASSERT_ZERO_LABEL(crv); 724 #else 725 ASSERT_LABEL(crv, i_j_label); 726 #endif 727 } 728 729 void alarm_handler(int unused) { 730 ; 731 } 732 733 void test_nanosleep() { 734 struct timespec req, rem; 735 req.tv_sec = 1; 736 req.tv_nsec = 0; 737 dfsan_set_label(i_label, &rem, sizeof(rem)); 738 739 // non interrupted 740 int rv = nanosleep(&req, &rem); 741 assert(rv == 0); 742 ASSERT_ZERO_LABEL(rv); 743 ASSERT_READ_LABEL(&rem, 1, i_label); 744 745 // interrupted by an alarm 746 signal(SIGALRM, alarm_handler); 747 req.tv_sec = 3; 748 alarm(1); 749 rv = nanosleep(&req, &rem); 750 assert(rv == -1); 751 ASSERT_ZERO_LABEL(rv); 752 ASSERT_READ_ZERO_LABEL(&rem, sizeof(rem)); 753 } 754 755 void test_socketpair() { 756 int fd[2]; 757 758 dfsan_set_label(i_label, fd, sizeof(fd)); 759 int rv = socketpair(PF_LOCAL, SOCK_STREAM, 0, fd); 760 assert(rv == 0); 761 ASSERT_ZERO_LABEL(rv); 762 ASSERT_READ_ZERO_LABEL(fd, sizeof(fd)); 763 } 764 765 void test_write() { 766 int fd = open("/dev/null", O_WRONLY); 767 768 char buf[] = "a string"; 769 int len = strlen(buf); 770 771 // The result of a write always unlabeled. 772 int res = write(fd, buf, len); 773 assert(res > 0); 774 ASSERT_ZERO_LABEL(res); 775 776 // Label all arguments to write(). 777 dfsan_set_label(i_label, &(buf[3]), 1); 778 dfsan_set_label(j_label, &fd, sizeof(fd)); 779 dfsan_set_label(i_label, &len, sizeof(len)); 780 781 // The value returned by write() should have no label. 782 res = write(fd, buf, len); 783 ASSERT_ZERO_LABEL(res); 784 785 close(fd); 786 } 787 788 template <class T> 789 void test_sprintf_chunk(const char* expected, const char* format, T arg) { 790 char buf[512]; 791 memset(buf, 'a', sizeof(buf)); 792 793 char padded_expected[512]; 794 strcpy(padded_expected, "foo "); 795 strcat(padded_expected, expected); 796 strcat(padded_expected, " bar"); 797 798 char padded_format[512]; 799 strcpy(padded_format, "foo "); 800 strcat(padded_format, format); 801 strcat(padded_format, " bar"); 802 803 // Non labelled arg. 804 assert(sprintf(buf, padded_format, arg) == strlen(padded_expected)); 805 assert(strcmp(buf, padded_expected) == 0); 806 ASSERT_READ_LABEL(buf, strlen(padded_expected), 0); 807 memset(buf, 'a', sizeof(buf)); 808 809 // Labelled arg. 810 dfsan_set_label(i_label, &arg, sizeof(arg)); 811 assert(sprintf(buf, padded_format, arg) == strlen(padded_expected)); 812 assert(strcmp(buf, padded_expected) == 0); 813 ASSERT_READ_LABEL(buf, 4, 0); 814 ASSERT_READ_LABEL(buf + 4, strlen(padded_expected) - 8, i_label); 815 ASSERT_READ_LABEL(buf + (strlen(padded_expected) - 4), 4, 0); 816 } 817 818 void test_sprintf() { 819 char buf[2048]; 820 memset(buf, 'a', sizeof(buf)); 821 822 // Test formatting (no conversion specifier). 823 assert(sprintf(buf, "Hello world!") == 12); 824 assert(strcmp(buf, "Hello world!") == 0); 825 ASSERT_READ_LABEL(buf, sizeof(buf), 0); 826 827 // Test for extra arguments. 828 assert(sprintf(buf, "Hello world!", 42, "hello") == 12); 829 assert(strcmp(buf, "Hello world!") == 0); 830 ASSERT_READ_LABEL(buf, sizeof(buf), 0); 831 832 // Test formatting & label propagation (multiple conversion specifiers): %s, 833 // %d, %n, %f, and %%. 834 const char* s = "world"; 835 int m = 8; 836 int d = 27; 837 dfsan_set_label(k_label, (void *) (s + 1), 2); 838 dfsan_set_label(i_label, &m, sizeof(m)); 839 dfsan_set_label(j_label, &d, sizeof(d)); 840 int n; 841 int r = sprintf(buf, "hello %s, %-d/%d/%d %f %% %n%d", s, 2014, m, d, 842 12345.6781234, &n, 1000); 843 assert(r == 42); 844 assert(strcmp(buf, "hello world, 2014/8/27 12345.678123 % 1000") == 0); 845 ASSERT_READ_LABEL(buf, 7, 0); 846 ASSERT_READ_LABEL(buf + 7, 2, k_label); 847 ASSERT_READ_LABEL(buf + 9, 9, 0); 848 ASSERT_READ_LABEL(buf + 18, 1, i_label); 849 ASSERT_READ_LABEL(buf + 19, 1, 0); 850 ASSERT_READ_LABEL(buf + 20, 2, j_label); 851 ASSERT_READ_LABEL(buf + 22, 15, 0); 852 ASSERT_LABEL(r, 0); 853 assert(n == 38); 854 855 // Test formatting & label propagation (single conversion specifier, with 856 // additional length and precision modifiers). 857 test_sprintf_chunk("-559038737", "%d", 0xdeadbeef); 858 test_sprintf_chunk("3735928559", "%u", 0xdeadbeef); 859 test_sprintf_chunk("12345", "%i", 12345); 860 test_sprintf_chunk("751", "%o", 0751); 861 test_sprintf_chunk("babe", "%x", 0xbabe); 862 test_sprintf_chunk("0000BABE", "%.8X", 0xbabe); 863 test_sprintf_chunk("-17", "%hhd", 0xdeadbeef); 864 test_sprintf_chunk("-16657", "%hd", 0xdeadbeef); 865 test_sprintf_chunk("deadbeefdeadbeef", "%lx", 0xdeadbeefdeadbeef); 866 test_sprintf_chunk("0xdeadbeefdeadbeef", "%p", 867 (void *) 0xdeadbeefdeadbeef); 868 test_sprintf_chunk("18446744073709551615", "%ju", (intmax_t) -1); 869 test_sprintf_chunk("18446744073709551615", "%zu", (size_t) -1); 870 test_sprintf_chunk("18446744073709551615", "%tu", (size_t) -1); 871 872 test_sprintf_chunk("0x1.f9acffa7eb6bfp-4", "%a", 0.123456); 873 test_sprintf_chunk("0X1.F9ACFFA7EB6BFP-4", "%A", 0.123456); 874 test_sprintf_chunk("0.12346", "%.5f", 0.123456); 875 test_sprintf_chunk("0.123456", "%g", 0.123456); 876 test_sprintf_chunk("1.234560e-01", "%e", 0.123456); 877 test_sprintf_chunk("1.234560E-01", "%E", 0.123456); 878 test_sprintf_chunk("0.1234567891234560", "%.16Lf", 879 (long double) 0.123456789123456); 880 881 test_sprintf_chunk("z", "%c", 'z'); 882 883 // %n, %s, %d, %f, and %% already tested 884 885 // Test formatting with width passed as an argument. 886 r = sprintf(buf, "hi %*d my %*s friend %.*f", 3, 1, 6, "dear", 4, 3.14159265359); 887 assert(r == 30); 888 assert(strcmp(buf, "hi 1 my dear friend 3.1416") == 0); 889 } 890 891 void test_snprintf() { 892 char buf[2048]; 893 memset(buf, 'a', sizeof(buf)); 894 dfsan_set_label(0, buf, sizeof(buf)); 895 const char* s = "world"; 896 int y = 2014; 897 int m = 8; 898 int d = 27; 899 dfsan_set_label(k_label, (void *) (s + 1), 2); 900 dfsan_set_label(i_label, &y, sizeof(y)); 901 dfsan_set_label(j_label, &m, sizeof(m)); 902 int r = snprintf(buf, 19, "hello %s, %-d/%d/%d %f", s, y, m, d, 903 12345.6781234); 904 // The return value is the number of bytes that would have been written to 905 // the final string if enough space had been available. 906 assert(r == 35); 907 assert(memcmp(buf, "hello world, 2014/", 19) == 0); 908 ASSERT_READ_LABEL(buf, 7, 0); 909 ASSERT_READ_LABEL(buf + 7, 2, k_label); 910 ASSERT_READ_LABEL(buf + 9, 4, 0); 911 ASSERT_READ_LABEL(buf + 13, 4, i_label); 912 ASSERT_READ_LABEL(buf + 17, 2, 0); 913 ASSERT_LABEL(r, 0); 914 } 915 916 int main(void) { 917 i_label = dfsan_create_label("i", 0); 918 j_label = dfsan_create_label("j", 0); 919 k_label = dfsan_create_label("k", 0); 920 i_j_label = dfsan_union(i_label, j_label); 921 922 test_calloc(); 923 test_clock_gettime(); 924 test_ctime_r(); 925 test_dfsan_set_write_callback(); 926 test_dl_iterate_phdr(); 927 test_dlopen(); 928 test_fgets(); 929 test_fstat(); 930 test_get_current_dir_name(); 931 test_getcwd(); 932 test_gethostname(); 933 test_getpwuid_r(); 934 test_getrlimit(); 935 test_getrusage(); 936 test_gettimeofday(); 937 test_inet_pton(); 938 test_localtime_r(); 939 test_memchr(); 940 test_memcmp(); 941 test_memcpy(); 942 test_memset(); 943 test_nanosleep(); 944 test_poll(); 945 test_pread(); 946 test_pthread_create(); 947 test_read(); 948 test_sched_getaffinity(); 949 test_select(); 950 test_sigaction(); 951 test_sigemptyset(); 952 test_snprintf(); 953 test_socketpair(); 954 test_sprintf(); 955 test_stat(); 956 test_strcasecmp(); 957 test_strchr(); 958 test_strcmp(); 959 test_strcpy(); 960 test_strdup(); 961 test_strlen(); 962 test_strncasecmp(); 963 test_strncmp(); 964 test_strncpy(); 965 test_strrchr(); 966 test_strstr(); 967 test_strtod(); 968 test_strtol(); 969 test_strtoll(); 970 test_strtoul(); 971 test_strtoull(); 972 test_time(); 973 test_write(); 974 } 975