1 //===-- dfsan.cpp ---------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of DataFlowSanitizer. 10 // 11 // This file defines the custom functions listed in done_abilist.txt. 12 //===----------------------------------------------------------------------===// 13 14 #include "sanitizer_common/sanitizer_common.h" 15 #include "sanitizer_common/sanitizer_internal_defs.h" 16 #include "sanitizer_common/sanitizer_linux.h" 17 18 #include "dfsan/dfsan.h" 19 20 #include <arpa/inet.h> 21 #include <assert.h> 22 #include <ctype.h> 23 #include <dlfcn.h> 24 #include <link.h> 25 #include <poll.h> 26 #include <pthread.h> 27 #include <pwd.h> 28 #include <sched.h> 29 #include <signal.h> 30 #include <stdarg.h> 31 #include <stdint.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <sys/resource.h> 36 #include <sys/select.h> 37 #include <sys/stat.h> 38 #include <sys/time.h> 39 #include <sys/types.h> 40 #include <time.h> 41 #include <unistd.h> 42 43 using namespace __dfsan; 44 45 #define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) \ 46 do { \ 47 if (f) \ 48 f(__VA_ARGS__); \ 49 } while (false) 50 #define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \ 51 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__); 52 53 extern "C" { 54 SANITIZER_INTERFACE_ATTRIBUTE int 55 __dfsw_stat(const char *path, struct stat *buf, dfsan_label path_label, 56 dfsan_label buf_label, dfsan_label *ret_label) { 57 int ret = stat(path, buf); 58 if (ret == 0) 59 dfsan_set_label(0, buf, sizeof(struct stat)); 60 *ret_label = 0; 61 return ret; 62 } 63 64 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_fstat(int fd, struct stat *buf, 65 dfsan_label fd_label, 66 dfsan_label buf_label, 67 dfsan_label *ret_label) { 68 int ret = fstat(fd, buf); 69 if (ret == 0) 70 dfsan_set_label(0, buf, sizeof(struct stat)); 71 *ret_label = 0; 72 return ret; 73 } 74 75 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strchr(const char *s, int c, 76 dfsan_label s_label, 77 dfsan_label c_label, 78 dfsan_label *ret_label) { 79 for (size_t i = 0;; ++i) { 80 if (s[i] == c || s[i] == 0) { 81 if (flags().strict_data_dependencies) { 82 *ret_label = s_label; 83 } else { 84 *ret_label = dfsan_union(dfsan_read_label(s, i + 1), 85 dfsan_union(s_label, c_label)); 86 } 87 88 // If s[i] is the \0 at the end of the string, and \0 is not the 89 // character we are searching for, then return null. 90 if (s[i] == 0 && c != 0) { 91 return nullptr; 92 } 93 return const_cast<char *>(s + i); 94 } 95 } 96 } 97 98 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, uptr caller_pc, 99 const void *s1, const void *s2, size_t n, 100 dfsan_label s1_label, dfsan_label s2_label, 101 dfsan_label n_label) 102 103 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_memcmp(const void *s1, const void *s2, 104 size_t n, dfsan_label s1_label, 105 dfsan_label s2_label, 106 dfsan_label n_label, 107 dfsan_label *ret_label) { 108 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_memcmp, GET_CALLER_PC(), s1, s2, n, 109 s1_label, s2_label, n_label); 110 const char *cs1 = (const char *) s1, *cs2 = (const char *) s2; 111 for (size_t i = 0; i != n; ++i) { 112 if (cs1[i] != cs2[i]) { 113 if (flags().strict_data_dependencies) { 114 *ret_label = 0; 115 } else { 116 *ret_label = dfsan_union(dfsan_read_label(cs1, i + 1), 117 dfsan_read_label(cs2, i + 1)); 118 } 119 return cs1[i] - cs2[i]; 120 } 121 } 122 123 if (flags().strict_data_dependencies) { 124 *ret_label = 0; 125 } else { 126 *ret_label = dfsan_union(dfsan_read_label(cs1, n), 127 dfsan_read_label(cs2, n)); 128 } 129 return 0; 130 } 131 132 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, uptr caller_pc, 133 const char *s1, const char *s2, 134 dfsan_label s1_label, dfsan_label s2_label) 135 136 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strcmp(const char *s1, const char *s2, 137 dfsan_label s1_label, 138 dfsan_label s2_label, 139 dfsan_label *ret_label) { 140 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strcmp, GET_CALLER_PC(), s1, s2, 141 s1_label, s2_label); 142 for (size_t i = 0;; ++i) { 143 if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0) { 144 if (flags().strict_data_dependencies) { 145 *ret_label = 0; 146 } else { 147 *ret_label = dfsan_union(dfsan_read_label(s1, i + 1), 148 dfsan_read_label(s2, i + 1)); 149 } 150 return s1[i] - s2[i]; 151 } 152 } 153 return 0; 154 } 155 156 SANITIZER_INTERFACE_ATTRIBUTE int 157 __dfsw_strcasecmp(const char *s1, const char *s2, dfsan_label s1_label, 158 dfsan_label s2_label, dfsan_label *ret_label) { 159 for (size_t i = 0;; ++i) { 160 char s1_lower = tolower(s1[i]); 161 char s2_lower = tolower(s2[i]); 162 163 if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0) { 164 if (flags().strict_data_dependencies) { 165 *ret_label = 0; 166 } else { 167 *ret_label = dfsan_union(dfsan_read_label(s1, i + 1), 168 dfsan_read_label(s2, i + 1)); 169 } 170 return s1_lower - s2_lower; 171 } 172 } 173 return 0; 174 } 175 176 DECLARE_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, uptr caller_pc, 177 const char *s1, const char *s2, size_t n, 178 dfsan_label s1_label, dfsan_label s2_label, 179 dfsan_label n_label) 180 181 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_strncmp(const char *s1, const char *s2, 182 size_t n, dfsan_label s1_label, 183 dfsan_label s2_label, 184 dfsan_label n_label, 185 dfsan_label *ret_label) { 186 if (n == 0) { 187 *ret_label = 0; 188 return 0; 189 } 190 191 CALL_WEAK_INTERCEPTOR_HOOK(dfsan_weak_hook_strncmp, GET_CALLER_PC(), s1, s2, 192 n, s1_label, s2_label, n_label); 193 194 for (size_t i = 0;; ++i) { 195 if (s1[i] != s2[i] || s1[i] == 0 || s2[i] == 0 || i == n - 1) { 196 if (flags().strict_data_dependencies) { 197 *ret_label = 0; 198 } else { 199 *ret_label = dfsan_union(dfsan_read_label(s1, i + 1), 200 dfsan_read_label(s2, i + 1)); 201 } 202 return s1[i] - s2[i]; 203 } 204 } 205 return 0; 206 } 207 208 SANITIZER_INTERFACE_ATTRIBUTE int 209 __dfsw_strncasecmp(const char *s1, const char *s2, size_t n, 210 dfsan_label s1_label, dfsan_label s2_label, 211 dfsan_label n_label, dfsan_label *ret_label) { 212 if (n == 0) { 213 *ret_label = 0; 214 return 0; 215 } 216 217 for (size_t i = 0;; ++i) { 218 char s1_lower = tolower(s1[i]); 219 char s2_lower = tolower(s2[i]); 220 221 if (s1_lower != s2_lower || s1[i] == 0 || s2[i] == 0 || i == n - 1) { 222 if (flags().strict_data_dependencies) { 223 *ret_label = 0; 224 } else { 225 *ret_label = dfsan_union(dfsan_read_label(s1, i + 1), 226 dfsan_read_label(s2, i + 1)); 227 } 228 return s1_lower - s2_lower; 229 } 230 } 231 return 0; 232 } 233 234 SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_calloc(size_t nmemb, size_t size, 235 dfsan_label nmemb_label, 236 dfsan_label size_label, 237 dfsan_label *ret_label) { 238 void *p = calloc(nmemb, size); 239 dfsan_set_label(0, p, nmemb * size); 240 *ret_label = 0; 241 return p; 242 } 243 244 SANITIZER_INTERFACE_ATTRIBUTE size_t 245 __dfsw_strlen(const char *s, dfsan_label s_label, dfsan_label *ret_label) { 246 size_t ret = strlen(s); 247 if (flags().strict_data_dependencies) { 248 *ret_label = 0; 249 } else { 250 *ret_label = dfsan_read_label(s, ret + 1); 251 } 252 return ret; 253 } 254 255 256 static void *dfsan_memcpy(void *dest, const void *src, size_t n) { 257 dfsan_label *sdest = shadow_for(dest); 258 const dfsan_label *ssrc = shadow_for(src); 259 internal_memcpy((void *)sdest, (const void *)ssrc, n * sizeof(dfsan_label)); 260 return internal_memcpy(dest, src, n); 261 } 262 263 static void dfsan_memset(void *s, int c, dfsan_label c_label, size_t n) { 264 internal_memset(s, c, n); 265 dfsan_set_label(c_label, s, n); 266 } 267 268 SANITIZER_INTERFACE_ATTRIBUTE 269 void *__dfsw_memcpy(void *dest, const void *src, size_t n, 270 dfsan_label dest_label, dfsan_label src_label, 271 dfsan_label n_label, dfsan_label *ret_label) { 272 *ret_label = dest_label; 273 return dfsan_memcpy(dest, src, n); 274 } 275 276 SANITIZER_INTERFACE_ATTRIBUTE 277 void *__dfsw_memset(void *s, int c, size_t n, 278 dfsan_label s_label, dfsan_label c_label, 279 dfsan_label n_label, dfsan_label *ret_label) { 280 dfsan_memset(s, c, c_label, n); 281 *ret_label = s_label; 282 return s; 283 } 284 285 SANITIZER_INTERFACE_ATTRIBUTE char * 286 __dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) { 287 size_t len = strlen(s); 288 void *p = malloc(len+1); 289 dfsan_memcpy(p, s, len+1); 290 *ret_label = 0; 291 return static_cast<char *>(p); 292 } 293 294 SANITIZER_INTERFACE_ATTRIBUTE char * 295 __dfsw_strncpy(char *s1, const char *s2, size_t n, dfsan_label s1_label, 296 dfsan_label s2_label, dfsan_label n_label, 297 dfsan_label *ret_label) { 298 size_t len = strlen(s2); 299 if (len < n) { 300 dfsan_memcpy(s1, s2, len+1); 301 dfsan_memset(s1+len+1, 0, 0, n-len-1); 302 } else { 303 dfsan_memcpy(s1, s2, n); 304 } 305 306 *ret_label = s1_label; 307 return s1; 308 } 309 310 SANITIZER_INTERFACE_ATTRIBUTE ssize_t 311 __dfsw_pread(int fd, void *buf, size_t count, off_t offset, 312 dfsan_label fd_label, dfsan_label buf_label, 313 dfsan_label count_label, dfsan_label offset_label, 314 dfsan_label *ret_label) { 315 ssize_t ret = pread(fd, buf, count, offset); 316 if (ret > 0) 317 dfsan_set_label(0, buf, ret); 318 *ret_label = 0; 319 return ret; 320 } 321 322 SANITIZER_INTERFACE_ATTRIBUTE ssize_t 323 __dfsw_read(int fd, void *buf, size_t count, 324 dfsan_label fd_label, dfsan_label buf_label, 325 dfsan_label count_label, 326 dfsan_label *ret_label) { 327 ssize_t ret = read(fd, buf, count); 328 if (ret > 0) 329 dfsan_set_label(0, buf, ret); 330 *ret_label = 0; 331 return ret; 332 } 333 334 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_clock_gettime(clockid_t clk_id, 335 struct timespec *tp, 336 dfsan_label clk_id_label, 337 dfsan_label tp_label, 338 dfsan_label *ret_label) { 339 int ret = clock_gettime(clk_id, tp); 340 if (ret == 0) 341 dfsan_set_label(0, tp, sizeof(struct timespec)); 342 *ret_label = 0; 343 return ret; 344 } 345 346 static void unpoison(const void *ptr, uptr size) { 347 dfsan_set_label(0, const_cast<void *>(ptr), size); 348 } 349 350 // dlopen() ultimately calls mmap() down inside the loader, which generally 351 // doesn't participate in dynamic symbol resolution. Therefore we won't 352 // intercept its calls to mmap, and we have to hook it here. 353 SANITIZER_INTERFACE_ATTRIBUTE void * 354 __dfsw_dlopen(const char *filename, int flag, dfsan_label filename_label, 355 dfsan_label flag_label, dfsan_label *ret_label) { 356 void *handle = dlopen(filename, flag); 357 link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE(handle); 358 if (map) 359 ForEachMappedRegion(map, unpoison); 360 *ret_label = 0; 361 return handle; 362 } 363 364 struct pthread_create_info { 365 void *(*start_routine_trampoline)(void *, void *, dfsan_label, dfsan_label *); 366 void *start_routine; 367 void *arg; 368 }; 369 370 static void *pthread_create_cb(void *p) { 371 pthread_create_info pci(*(pthread_create_info *)p); 372 free(p); 373 dfsan_label ret_label; 374 return pci.start_routine_trampoline(pci.start_routine, pci.arg, 0, 375 &ret_label); 376 } 377 378 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_pthread_create( 379 pthread_t *thread, const pthread_attr_t *attr, 380 void *(*start_routine_trampoline)(void *, void *, dfsan_label, 381 dfsan_label *), 382 void *start_routine, void *arg, dfsan_label thread_label, 383 dfsan_label attr_label, dfsan_label start_routine_label, 384 dfsan_label arg_label, dfsan_label *ret_label) { 385 pthread_create_info *pci = 386 (pthread_create_info *)malloc(sizeof(pthread_create_info)); 387 pci->start_routine_trampoline = start_routine_trampoline; 388 pci->start_routine = start_routine; 389 pci->arg = arg; 390 int rv = pthread_create(thread, attr, pthread_create_cb, (void *)pci); 391 if (rv != 0) 392 free(pci); 393 *ret_label = 0; 394 return rv; 395 } 396 397 struct dl_iterate_phdr_info { 398 int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, 399 size_t size, void *data, dfsan_label info_label, 400 dfsan_label size_label, dfsan_label data_label, 401 dfsan_label *ret_label); 402 void *callback; 403 void *data; 404 }; 405 406 int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *data) { 407 dl_iterate_phdr_info *dipi = (dl_iterate_phdr_info *)data; 408 dfsan_set_label(0, *info); 409 dfsan_set_label(0, const_cast<char *>(info->dlpi_name), 410 strlen(info->dlpi_name) + 1); 411 dfsan_set_label( 412 0, const_cast<char *>(reinterpret_cast<const char *>(info->dlpi_phdr)), 413 sizeof(*info->dlpi_phdr) * info->dlpi_phnum); 414 dfsan_label ret_label; 415 return dipi->callback_trampoline(dipi->callback, info, size, dipi->data, 0, 0, 416 0, &ret_label); 417 } 418 419 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_dl_iterate_phdr( 420 int (*callback_trampoline)(void *callback, struct dl_phdr_info *info, 421 size_t size, void *data, dfsan_label info_label, 422 dfsan_label size_label, dfsan_label data_label, 423 dfsan_label *ret_label), 424 void *callback, void *data, dfsan_label callback_label, 425 dfsan_label data_label, dfsan_label *ret_label) { 426 dl_iterate_phdr_info dipi = { callback_trampoline, callback, data }; 427 *ret_label = 0; 428 return dl_iterate_phdr(dl_iterate_phdr_cb, &dipi); 429 } 430 431 SANITIZER_INTERFACE_ATTRIBUTE 432 char *__dfsw_ctime_r(const time_t *timep, char *buf, dfsan_label timep_label, 433 dfsan_label buf_label, dfsan_label *ret_label) { 434 char *ret = ctime_r(timep, buf); 435 if (ret) { 436 dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), buf, 437 strlen(buf) + 1); 438 *ret_label = buf_label; 439 } else { 440 *ret_label = 0; 441 } 442 return ret; 443 } 444 445 SANITIZER_INTERFACE_ATTRIBUTE 446 char *__dfsw_fgets(char *s, int size, FILE *stream, dfsan_label s_label, 447 dfsan_label size_label, dfsan_label stream_label, 448 dfsan_label *ret_label) { 449 char *ret = fgets(s, size, stream); 450 if (ret) { 451 dfsan_set_label(0, ret, strlen(ret) + 1); 452 *ret_label = s_label; 453 } else { 454 *ret_label = 0; 455 } 456 return ret; 457 } 458 459 SANITIZER_INTERFACE_ATTRIBUTE 460 char *__dfsw_getcwd(char *buf, size_t size, dfsan_label buf_label, 461 dfsan_label size_label, dfsan_label *ret_label) { 462 char *ret = getcwd(buf, size); 463 if (ret) { 464 dfsan_set_label(0, ret, strlen(ret) + 1); 465 *ret_label = buf_label; 466 } else { 467 *ret_label = 0; 468 } 469 return ret; 470 } 471 472 SANITIZER_INTERFACE_ATTRIBUTE 473 char *__dfsw_get_current_dir_name(dfsan_label *ret_label) { 474 char *ret = get_current_dir_name(); 475 if (ret) { 476 dfsan_set_label(0, ret, strlen(ret) + 1); 477 } 478 *ret_label = 0; 479 return ret; 480 } 481 482 SANITIZER_INTERFACE_ATTRIBUTE 483 int __dfsw_gethostname(char *name, size_t len, dfsan_label name_label, 484 dfsan_label len_label, dfsan_label *ret_label) { 485 int ret = gethostname(name, len); 486 if (ret == 0) { 487 dfsan_set_label(0, name, strlen(name) + 1); 488 } 489 *ret_label = 0; 490 return ret; 491 } 492 493 SANITIZER_INTERFACE_ATTRIBUTE 494 int __dfsw_getrlimit(int resource, struct rlimit *rlim, 495 dfsan_label resource_label, dfsan_label rlim_label, 496 dfsan_label *ret_label) { 497 int ret = getrlimit(resource, rlim); 498 if (ret == 0) { 499 dfsan_set_label(0, rlim, sizeof(struct rlimit)); 500 } 501 *ret_label = 0; 502 return ret; 503 } 504 505 SANITIZER_INTERFACE_ATTRIBUTE 506 int __dfsw_getrusage(int who, struct rusage *usage, dfsan_label who_label, 507 dfsan_label usage_label, dfsan_label *ret_label) { 508 int ret = getrusage(who, usage); 509 if (ret == 0) { 510 dfsan_set_label(0, usage, sizeof(struct rusage)); 511 } 512 *ret_label = 0; 513 return ret; 514 } 515 516 SANITIZER_INTERFACE_ATTRIBUTE 517 char *__dfsw_strcpy(char *dest, const char *src, dfsan_label dst_label, 518 dfsan_label src_label, dfsan_label *ret_label) { 519 char *ret = strcpy(dest, src); // NOLINT 520 if (ret) { 521 internal_memcpy(shadow_for(dest), shadow_for(src), 522 sizeof(dfsan_label) * (strlen(src) + 1)); 523 } 524 *ret_label = dst_label; 525 return ret; 526 } 527 528 SANITIZER_INTERFACE_ATTRIBUTE 529 long int __dfsw_strtol(const char *nptr, char **endptr, int base, 530 dfsan_label nptr_label, dfsan_label endptr_label, 531 dfsan_label base_label, dfsan_label *ret_label) { 532 char *tmp_endptr; 533 long int ret = strtol(nptr, &tmp_endptr, base); 534 if (endptr) { 535 *endptr = tmp_endptr; 536 } 537 if (tmp_endptr > nptr) { 538 // If *tmp_endptr is '\0' include its label as well. 539 *ret_label = dfsan_union( 540 base_label, 541 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); 542 } else { 543 *ret_label = 0; 544 } 545 return ret; 546 } 547 548 SANITIZER_INTERFACE_ATTRIBUTE 549 double __dfsw_strtod(const char *nptr, char **endptr, 550 dfsan_label nptr_label, dfsan_label endptr_label, 551 dfsan_label *ret_label) { 552 char *tmp_endptr; 553 double ret = strtod(nptr, &tmp_endptr); 554 if (endptr) { 555 *endptr = tmp_endptr; 556 } 557 if (tmp_endptr > nptr) { 558 // If *tmp_endptr is '\0' include its label as well. 559 *ret_label = dfsan_read_label( 560 nptr, 561 tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)); 562 } else { 563 *ret_label = 0; 564 } 565 return ret; 566 } 567 568 SANITIZER_INTERFACE_ATTRIBUTE 569 long long int __dfsw_strtoll(const char *nptr, char **endptr, int base, 570 dfsan_label nptr_label, dfsan_label endptr_label, 571 dfsan_label base_label, dfsan_label *ret_label) { 572 char *tmp_endptr; 573 long long int ret = strtoll(nptr, &tmp_endptr, base); 574 if (endptr) { 575 *endptr = tmp_endptr; 576 } 577 if (tmp_endptr > nptr) { 578 // If *tmp_endptr is '\0' include its label as well. 579 *ret_label = dfsan_union( 580 base_label, 581 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); 582 } else { 583 *ret_label = 0; 584 } 585 return ret; 586 } 587 588 SANITIZER_INTERFACE_ATTRIBUTE 589 unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base, 590 dfsan_label nptr_label, dfsan_label endptr_label, 591 dfsan_label base_label, dfsan_label *ret_label) { 592 char *tmp_endptr; 593 unsigned long int ret = strtoul(nptr, &tmp_endptr, base); 594 if (endptr) { 595 *endptr = tmp_endptr; 596 } 597 if (tmp_endptr > nptr) { 598 // If *tmp_endptr is '\0' include its label as well. 599 *ret_label = dfsan_union( 600 base_label, 601 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); 602 } else { 603 *ret_label = 0; 604 } 605 return ret; 606 } 607 608 SANITIZER_INTERFACE_ATTRIBUTE 609 long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr, 610 dfsan_label nptr_label, 611 int base, dfsan_label endptr_label, 612 dfsan_label base_label, 613 dfsan_label *ret_label) { 614 char *tmp_endptr; 615 long long unsigned int ret = strtoull(nptr, &tmp_endptr, base); 616 if (endptr) { 617 *endptr = tmp_endptr; 618 } 619 if (tmp_endptr > nptr) { 620 // If *tmp_endptr is '\0' include its label as well. 621 *ret_label = dfsan_union( 622 base_label, 623 dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1))); 624 } else { 625 *ret_label = 0; 626 } 627 return ret; 628 } 629 630 SANITIZER_INTERFACE_ATTRIBUTE 631 time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) { 632 time_t ret = time(t); 633 if (ret != (time_t) -1 && t) { 634 dfsan_set_label(0, t, sizeof(time_t)); 635 } 636 *ret_label = 0; 637 return ret; 638 } 639 640 SANITIZER_INTERFACE_ATTRIBUTE 641 int __dfsw_inet_pton(int af, const char *src, void *dst, dfsan_label af_label, 642 dfsan_label src_label, dfsan_label dst_label, 643 dfsan_label *ret_label) { 644 int ret = inet_pton(af, src, dst); 645 if (ret == 1) { 646 dfsan_set_label(dfsan_read_label(src, strlen(src) + 1), dst, 647 af == AF_INET ? sizeof(struct in_addr) : sizeof(in6_addr)); 648 } 649 *ret_label = 0; 650 return ret; 651 } 652 653 SANITIZER_INTERFACE_ATTRIBUTE 654 struct tm *__dfsw_localtime_r(const time_t *timep, struct tm *result, 655 dfsan_label timep_label, dfsan_label result_label, 656 dfsan_label *ret_label) { 657 struct tm *ret = localtime_r(timep, result); 658 if (ret) { 659 dfsan_set_label(dfsan_read_label(timep, sizeof(time_t)), result, 660 sizeof(struct tm)); 661 *ret_label = result_label; 662 } else { 663 *ret_label = 0; 664 } 665 return ret; 666 } 667 668 SANITIZER_INTERFACE_ATTRIBUTE 669 int __dfsw_getpwuid_r(id_t uid, struct passwd *pwd, 670 char *buf, size_t buflen, struct passwd **result, 671 dfsan_label uid_label, dfsan_label pwd_label, 672 dfsan_label buf_label, dfsan_label buflen_label, 673 dfsan_label result_label, dfsan_label *ret_label) { 674 // Store the data in pwd, the strings referenced from pwd in buf, and the 675 // address of pwd in *result. On failure, NULL is stored in *result. 676 int ret = getpwuid_r(uid, pwd, buf, buflen, result); 677 if (ret == 0) { 678 dfsan_set_label(0, pwd, sizeof(struct passwd)); 679 dfsan_set_label(0, buf, strlen(buf) + 1); 680 } 681 *ret_label = 0; 682 dfsan_set_label(0, result, sizeof(struct passwd*)); 683 return ret; 684 } 685 686 SANITIZER_INTERFACE_ATTRIBUTE 687 int __dfsw_poll(struct pollfd *fds, nfds_t nfds, int timeout, 688 dfsan_label dfs_label, dfsan_label nfds_label, 689 dfsan_label timeout_label, dfsan_label *ret_label) { 690 int ret = poll(fds, nfds, timeout); 691 if (ret >= 0) { 692 for (; nfds > 0; --nfds) { 693 dfsan_set_label(0, &fds[nfds - 1].revents, sizeof(fds[nfds - 1].revents)); 694 } 695 } 696 *ret_label = 0; 697 return ret; 698 } 699 700 SANITIZER_INTERFACE_ATTRIBUTE 701 int __dfsw_select(int nfds, fd_set *readfds, fd_set *writefds, 702 fd_set *exceptfds, struct timeval *timeout, 703 dfsan_label nfds_label, dfsan_label readfds_label, 704 dfsan_label writefds_label, dfsan_label exceptfds_label, 705 dfsan_label timeout_label, dfsan_label *ret_label) { 706 int ret = select(nfds, readfds, writefds, exceptfds, timeout); 707 // Clear everything (also on error) since their content is either set or 708 // undefined. 709 if (readfds) { 710 dfsan_set_label(0, readfds, sizeof(fd_set)); 711 } 712 if (writefds) { 713 dfsan_set_label(0, writefds, sizeof(fd_set)); 714 } 715 if (exceptfds) { 716 dfsan_set_label(0, exceptfds, sizeof(fd_set)); 717 } 718 dfsan_set_label(0, timeout, sizeof(struct timeval)); 719 *ret_label = 0; 720 return ret; 721 } 722 723 SANITIZER_INTERFACE_ATTRIBUTE 724 int __dfsw_sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask, 725 dfsan_label pid_label, 726 dfsan_label cpusetsize_label, 727 dfsan_label mask_label, dfsan_label *ret_label) { 728 int ret = sched_getaffinity(pid, cpusetsize, mask); 729 if (ret == 0) { 730 dfsan_set_label(0, mask, cpusetsize); 731 } 732 *ret_label = 0; 733 return ret; 734 } 735 736 SANITIZER_INTERFACE_ATTRIBUTE 737 int __dfsw_sigemptyset(sigset_t *set, dfsan_label set_label, 738 dfsan_label *ret_label) { 739 int ret = sigemptyset(set); 740 dfsan_set_label(0, set, sizeof(sigset_t)); 741 return ret; 742 } 743 744 SANITIZER_INTERFACE_ATTRIBUTE 745 int __dfsw_sigaction(int signum, const struct sigaction *act, 746 struct sigaction *oldact, dfsan_label signum_label, 747 dfsan_label act_label, dfsan_label oldact_label, 748 dfsan_label *ret_label) { 749 int ret = sigaction(signum, act, oldact); 750 if (oldact) { 751 dfsan_set_label(0, oldact, sizeof(struct sigaction)); 752 } 753 *ret_label = 0; 754 return ret; 755 } 756 757 SANITIZER_INTERFACE_ATTRIBUTE 758 int __dfsw_gettimeofday(struct timeval *tv, struct timezone *tz, 759 dfsan_label tv_label, dfsan_label tz_label, 760 dfsan_label *ret_label) { 761 int ret = gettimeofday(tv, tz); 762 if (tv) { 763 dfsan_set_label(0, tv, sizeof(struct timeval)); 764 } 765 if (tz) { 766 dfsan_set_label(0, tz, sizeof(struct timezone)); 767 } 768 *ret_label = 0; 769 return ret; 770 } 771 772 SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n, 773 dfsan_label s_label, 774 dfsan_label c_label, 775 dfsan_label n_label, 776 dfsan_label *ret_label) { 777 void *ret = memchr(s, c, n); 778 if (flags().strict_data_dependencies) { 779 *ret_label = ret ? s_label : 0; 780 } else { 781 size_t len = 782 ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1 783 : n; 784 *ret_label = 785 dfsan_union(dfsan_read_label(s, len), dfsan_union(s_label, c_label)); 786 } 787 return ret; 788 } 789 790 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c, 791 dfsan_label s_label, 792 dfsan_label c_label, 793 dfsan_label *ret_label) { 794 char *ret = strrchr(s, c); 795 if (flags().strict_data_dependencies) { 796 *ret_label = ret ? s_label : 0; 797 } else { 798 *ret_label = 799 dfsan_union(dfsan_read_label(s, strlen(s) + 1), 800 dfsan_union(s_label, c_label)); 801 } 802 803 return ret; 804 } 805 806 SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle, 807 dfsan_label haystack_label, 808 dfsan_label needle_label, 809 dfsan_label *ret_label) { 810 char *ret = strstr(haystack, needle); 811 if (flags().strict_data_dependencies) { 812 *ret_label = ret ? haystack_label : 0; 813 } else { 814 size_t len = ret ? ret + strlen(needle) - haystack : strlen(haystack) + 1; 815 *ret_label = 816 dfsan_union(dfsan_read_label(haystack, len), 817 dfsan_union(dfsan_read_label(needle, strlen(needle) + 1), 818 dfsan_union(haystack_label, needle_label))); 819 } 820 821 return ret; 822 } 823 824 SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req, 825 struct timespec *rem, 826 dfsan_label req_label, 827 dfsan_label rem_label, 828 dfsan_label *ret_label) { 829 int ret = nanosleep(req, rem); 830 *ret_label = 0; 831 if (ret == -1) { 832 // Interrupted by a signal, rem is filled with the remaining time. 833 dfsan_set_label(0, rem, sizeof(struct timespec)); 834 } 835 return ret; 836 } 837 838 SANITIZER_INTERFACE_ATTRIBUTE int 839 __dfsw_socketpair(int domain, int type, int protocol, int sv[2], 840 dfsan_label domain_label, dfsan_label type_label, 841 dfsan_label protocol_label, dfsan_label sv_label, 842 dfsan_label *ret_label) { 843 int ret = socketpair(domain, type, protocol, sv); 844 *ret_label = 0; 845 if (ret == 0) { 846 dfsan_set_label(0, sv, sizeof(*sv) * 2); 847 } 848 return ret; 849 } 850 851 // Type of the trampoline function passed to the custom version of 852 // dfsan_set_write_callback. 853 typedef void (*write_trampoline_t)( 854 void *callback, 855 int fd, const void *buf, ssize_t count, 856 dfsan_label fd_label, dfsan_label buf_label, dfsan_label count_label); 857 858 // Calls to dfsan_set_write_callback() set the values in this struct. 859 // Calls to the custom version of write() read (and invoke) them. 860 static struct { 861 write_trampoline_t write_callback_trampoline = nullptr; 862 void *write_callback = nullptr; 863 } write_callback_info; 864 865 SANITIZER_INTERFACE_ATTRIBUTE void 866 __dfsw_dfsan_set_write_callback( 867 write_trampoline_t write_callback_trampoline, 868 void *write_callback, 869 dfsan_label write_callback_label, 870 dfsan_label *ret_label) { 871 write_callback_info.write_callback_trampoline = write_callback_trampoline; 872 write_callback_info.write_callback = write_callback; 873 } 874 875 SANITIZER_INTERFACE_ATTRIBUTE int 876 __dfsw_write(int fd, const void *buf, size_t count, 877 dfsan_label fd_label, dfsan_label buf_label, 878 dfsan_label count_label, dfsan_label *ret_label) { 879 if (write_callback_info.write_callback) { 880 write_callback_info.write_callback_trampoline( 881 write_callback_info.write_callback, 882 fd, buf, count, 883 fd_label, buf_label, count_label); 884 } 885 886 *ret_label = 0; 887 return write(fd, buf, count); 888 } 889 } // namespace __dfsan 890 891 // Type used to extract a dfsan_label with va_arg() 892 typedef int dfsan_label_va; 893 894 // Formats a chunk either a constant string or a single format directive (e.g., 895 // '%.3f'). 896 struct Formatter { 897 Formatter(char *str_, const char *fmt_, size_t size_) 898 : str(str_), str_off(0), size(size_), fmt_start(fmt_), fmt_cur(fmt_), 899 width(-1) {} 900 901 int format() { 902 char *tmp_fmt = build_format_string(); 903 int retval = 904 snprintf(str + str_off, str_off < size ? size - str_off : 0, tmp_fmt, 905 0 /* used only to avoid warnings */); 906 free(tmp_fmt); 907 return retval; 908 } 909 910 template <typename T> int format(T arg) { 911 char *tmp_fmt = build_format_string(); 912 int retval; 913 if (width >= 0) { 914 retval = snprintf(str + str_off, str_off < size ? size - str_off : 0, 915 tmp_fmt, width, arg); 916 } else { 917 retval = snprintf(str + str_off, str_off < size ? size - str_off : 0, 918 tmp_fmt, arg); 919 } 920 free(tmp_fmt); 921 return retval; 922 } 923 924 char *build_format_string() { 925 size_t fmt_size = fmt_cur - fmt_start + 1; 926 char *new_fmt = (char *)malloc(fmt_size + 1); 927 assert(new_fmt); 928 internal_memcpy(new_fmt, fmt_start, fmt_size); 929 new_fmt[fmt_size] = '\0'; 930 return new_fmt; 931 } 932 933 char *str_cur() { return str + str_off; } 934 935 size_t num_written_bytes(int retval) { 936 if (retval < 0) { 937 return 0; 938 } 939 940 size_t num_avail = str_off < size ? size - str_off : 0; 941 if (num_avail == 0) { 942 return 0; 943 } 944 945 size_t num_written = retval; 946 // A return value of {v,}snprintf of size or more means that the output was 947 // truncated. 948 if (num_written >= num_avail) { 949 num_written -= num_avail; 950 } 951 952 return num_written; 953 } 954 955 char *str; 956 size_t str_off; 957 size_t size; 958 const char *fmt_start; 959 const char *fmt_cur; 960 int width; 961 }; 962 963 // Formats the input and propagates the input labels to the output. The output 964 // is stored in 'str'. 'size' bounds the number of output bytes. 'format' and 965 // 'ap' are the format string and the list of arguments for formatting. Returns 966 // the return value vsnprintf would return. 967 // 968 // The function tokenizes the format string in chunks representing either a 969 // constant string or a single format directive (e.g., '%.3f') and formats each 970 // chunk independently into the output string. This approach allows to figure 971 // out which bytes of the output string depends on which argument and thus to 972 // propagate labels more precisely. 973 // 974 // WARNING: This implementation does not support conversion specifiers with 975 // positional arguments. 976 static int format_buffer(char *str, size_t size, const char *fmt, 977 dfsan_label *va_labels, dfsan_label *ret_label, 978 va_list ap) { 979 Formatter formatter(str, fmt, size); 980 981 while (*formatter.fmt_cur) { 982 formatter.fmt_start = formatter.fmt_cur; 983 formatter.width = -1; 984 int retval = 0; 985 986 if (*formatter.fmt_cur != '%') { 987 // Ordinary character. Consume all the characters until a '%' or the end 988 // of the string. 989 for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%'; 990 ++formatter.fmt_cur) {} 991 retval = formatter.format(); 992 dfsan_set_label(0, formatter.str_cur(), 993 formatter.num_written_bytes(retval)); 994 } else { 995 // Conversion directive. Consume all the characters until a conversion 996 // specifier or the end of the string. 997 bool end_fmt = false; 998 for (; *formatter.fmt_cur && !end_fmt; ) { 999 switch (*++formatter.fmt_cur) { 1000 case 'd': 1001 case 'i': 1002 case 'o': 1003 case 'u': 1004 case 'x': 1005 case 'X': 1006 switch (*(formatter.fmt_cur - 1)) { 1007 case 'h': 1008 // Also covers the 'hh' case (since the size of the arg is still 1009 // an int). 1010 retval = formatter.format(va_arg(ap, int)); 1011 break; 1012 case 'l': 1013 if (formatter.fmt_cur - formatter.fmt_start >= 2 && 1014 *(formatter.fmt_cur - 2) == 'l') { 1015 retval = formatter.format(va_arg(ap, long long int)); 1016 } else { 1017 retval = formatter.format(va_arg(ap, long int)); 1018 } 1019 break; 1020 case 'q': 1021 retval = formatter.format(va_arg(ap, long long int)); 1022 break; 1023 case 'j': 1024 retval = formatter.format(va_arg(ap, intmax_t)); 1025 break; 1026 case 'z': 1027 case 't': 1028 retval = formatter.format(va_arg(ap, size_t)); 1029 break; 1030 default: 1031 retval = formatter.format(va_arg(ap, int)); 1032 } 1033 dfsan_set_label(*va_labels++, formatter.str_cur(), 1034 formatter.num_written_bytes(retval)); 1035 end_fmt = true; 1036 break; 1037 1038 case 'a': 1039 case 'A': 1040 case 'e': 1041 case 'E': 1042 case 'f': 1043 case 'F': 1044 case 'g': 1045 case 'G': 1046 if (*(formatter.fmt_cur - 1) == 'L') { 1047 retval = formatter.format(va_arg(ap, long double)); 1048 } else { 1049 retval = formatter.format(va_arg(ap, double)); 1050 } 1051 dfsan_set_label(*va_labels++, formatter.str_cur(), 1052 formatter.num_written_bytes(retval)); 1053 end_fmt = true; 1054 break; 1055 1056 case 'c': 1057 retval = formatter.format(va_arg(ap, int)); 1058 dfsan_set_label(*va_labels++, formatter.str_cur(), 1059 formatter.num_written_bytes(retval)); 1060 end_fmt = true; 1061 break; 1062 1063 case 's': { 1064 char *arg = va_arg(ap, char *); 1065 retval = formatter.format(arg); 1066 va_labels++; 1067 internal_memcpy(shadow_for(formatter.str_cur()), shadow_for(arg), 1068 sizeof(dfsan_label) * 1069 formatter.num_written_bytes(retval)); 1070 end_fmt = true; 1071 break; 1072 } 1073 1074 case 'p': 1075 retval = formatter.format(va_arg(ap, void *)); 1076 dfsan_set_label(*va_labels++, formatter.str_cur(), 1077 formatter.num_written_bytes(retval)); 1078 end_fmt = true; 1079 break; 1080 1081 case 'n': { 1082 int *ptr = va_arg(ap, int *); 1083 *ptr = (int)formatter.str_off; 1084 va_labels++; 1085 dfsan_set_label(0, ptr, sizeof(ptr)); 1086 end_fmt = true; 1087 break; 1088 } 1089 1090 case '%': 1091 retval = formatter.format(); 1092 dfsan_set_label(0, formatter.str_cur(), 1093 formatter.num_written_bytes(retval)); 1094 end_fmt = true; 1095 break; 1096 1097 case '*': 1098 formatter.width = va_arg(ap, int); 1099 va_labels++; 1100 break; 1101 1102 default: 1103 break; 1104 } 1105 } 1106 } 1107 1108 if (retval < 0) { 1109 return retval; 1110 } 1111 1112 formatter.fmt_cur++; 1113 formatter.str_off += retval; 1114 } 1115 1116 *ret_label = 0; 1117 1118 // Number of bytes written in total. 1119 return formatter.str_off; 1120 } 1121 1122 extern "C" { 1123 SANITIZER_INTERFACE_ATTRIBUTE 1124 int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label, 1125 dfsan_label format_label, dfsan_label *va_labels, 1126 dfsan_label *ret_label, ...) { 1127 va_list ap; 1128 va_start(ap, ret_label); 1129 int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, ap); 1130 va_end(ap); 1131 return ret; 1132 } 1133 1134 SANITIZER_INTERFACE_ATTRIBUTE 1135 int __dfsw_snprintf(char *str, size_t size, const char *format, 1136 dfsan_label str_label, dfsan_label size_label, 1137 dfsan_label format_label, dfsan_label *va_labels, 1138 dfsan_label *ret_label, ...) { 1139 va_list ap; 1140 va_start(ap, ret_label); 1141 int ret = format_buffer(str, size, format, va_labels, ret_label, ap); 1142 va_end(ap); 1143 return ret; 1144 } 1145 1146 // Default empty implementations (weak). Users should redefine them. 1147 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard, u32 *) {} 1148 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_guard_init, u32 *, 1149 u32 *) {} 1150 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_pcs_init, void) {} 1151 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_cov_trace_pc_indir, void) {} 1152 1153 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp, void) {} 1154 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp1, void) {} 1155 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp2, void) {} 1156 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp4, void) {} 1157 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_cmp8, void) {} 1158 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp1, 1159 void) {} 1160 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp2, 1161 void) {} 1162 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp4, 1163 void) {} 1164 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_const_cmp8, 1165 void) {} 1166 SANITIZER_INTERFACE_WEAK_DEF(void, __dfsw___sanitizer_cov_trace_switch, void) {} 1167 } // extern "C" 1168