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