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