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