1 // RUN: %clang_dfsan %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
2 // RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && DFSAN_OPTIONS="strict_data_dependencies=0" %run %t
3 // RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES %s -o %t && %run %t
4 // RUN: %clang_dfsan -DSTRICT_DATA_DEPENDENCIES -mllvm -dfsan-args-abi %s -o %t && %run %t
5 
6 // Tests custom implementations of various glibc functions.
7 
8 #include <sanitizer/dfsan_interface.h>
9 
10 #include <arpa/inet.h>
11 #include <assert.h>
12 #include <fcntl.h>
13 #include <link.h>
14 #include <poll.h>
15 #include <pthread.h>
16 #include <pwd.h>
17 #include <sched.h>
18 #include <signal.h>
19 #include <stdio.h>
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/select.h>
24 #include <sys/resource.h>
25 #include <sys/stat.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <time.h>
29 #include <unistd.h>
30 
31 dfsan_label i_label = 0;
32 dfsan_label j_label = 0;
33 dfsan_label k_label = 0;
34 dfsan_label i_j_label = 0;
35 
36 #define ASSERT_ZERO_LABEL(data) \
37   assert(0 == dfsan_get_label((long) (data)))
38 
39 #define ASSERT_READ_ZERO_LABEL(ptr, size) \
40   assert(0 == dfsan_read_label(ptr, size))
41 
42 #define ASSERT_LABEL(data, label) \
43   assert(label == dfsan_get_label((long) (data)))
44 
45 #define ASSERT_READ_LABEL(ptr, size, label) \
46   assert(label == dfsan_read_label(ptr, size))
47 
test_stat()48 void test_stat() {
49   int i = 1;
50   dfsan_set_label(i_label, &i, sizeof(i));
51 
52   struct stat s;
53   s.st_dev = i;
54   assert(0 == stat("/", &s));
55   ASSERT_ZERO_LABEL(s.st_dev);
56 
57   s.st_dev = i;
58   assert(-1 == stat("/nonexistent", &s));
59   ASSERT_LABEL(s.st_dev, i_label);
60 }
61 
test_fstat()62 void test_fstat() {
63   int i = 1;
64   dfsan_set_label(i_label, &i, sizeof(i));
65 
66   struct stat s;
67   int fd = open("/dev/zero", O_RDONLY);
68   s.st_dev = i;
69   int rv = fstat(fd, &s);
70   assert(0 == rv);
71   ASSERT_ZERO_LABEL(s.st_dev);
72 }
73 
test_memcmp()74 void test_memcmp() {
75   char str1[] = "str1", str2[] = "str2";
76   dfsan_set_label(i_label, &str1[3], 1);
77   dfsan_set_label(j_label, &str2[3], 1);
78 
79   int rv = memcmp(str1, str2, sizeof(str1));
80   assert(rv < 0);
81 #ifdef STRICT_DATA_DEPENDENCIES
82   ASSERT_ZERO_LABEL(rv);
83 #else
84   ASSERT_LABEL(rv, i_j_label);
85 #endif
86 }
87 
test_memcpy()88 void test_memcpy() {
89   char str1[] = "str1";
90   char str2[sizeof(str1)];
91   dfsan_set_label(i_label, &str1[3], 1);
92 
93   ASSERT_ZERO_LABEL(memcpy(str2, str1, sizeof(str1)));
94   assert(0 == memcmp(str2, str1, sizeof(str1)));
95   ASSERT_ZERO_LABEL(str2[0]);
96   ASSERT_LABEL(str2[3], i_label);
97 }
98 
test_memset()99 void test_memset() {
100   char buf[8];
101   int j = 'a';
102   dfsan_set_label(j_label, &j, sizeof(j));
103 
104   ASSERT_ZERO_LABEL(memset(&buf, j, sizeof(buf)));
105   for (int i = 0; i < 8; ++i) {
106     ASSERT_LABEL(buf[i], j_label);
107     assert(buf[i] == 'a');
108   }
109 }
110 
test_strcmp()111 void test_strcmp() {
112   char str1[] = "str1", str2[] = "str2";
113   dfsan_set_label(i_label, &str1[3], 1);
114   dfsan_set_label(j_label, &str2[3], 1);
115 
116   int rv = strcmp(str1, str2);
117   assert(rv < 0);
118 #ifdef STRICT_DATA_DEPENDENCIES
119   ASSERT_ZERO_LABEL(rv);
120 #else
121   ASSERT_LABEL(rv, i_j_label);
122 #endif
123 }
124 
test_strlen()125 void test_strlen() {
126   char str1[] = "str1";
127   dfsan_set_label(i_label, &str1[3], 1);
128 
129   int rv = strlen(str1);
130   assert(rv == 4);
131 #ifdef STRICT_DATA_DEPENDENCIES
132   ASSERT_ZERO_LABEL(rv);
133 #else
134   ASSERT_LABEL(rv, i_label);
135 #endif
136 }
137 
test_strdup()138 void test_strdup() {
139   char str1[] = "str1";
140   dfsan_set_label(i_label, &str1[3], 1);
141 
142   char *strd = strdup(str1);
143   ASSERT_ZERO_LABEL(strd[0]);
144   ASSERT_LABEL(strd[3], i_label);
145   free(strd);
146 }
147 
test_strncpy()148 void test_strncpy() {
149   char str1[] = "str1";
150   char str2[sizeof(str1)];
151   dfsan_set_label(i_label, &str1[3], 1);
152 
153   char *strd = strncpy(str2, str1, 5);
154   assert(strd == str2);
155   assert(strcmp(str1, str2) == 0);
156   ASSERT_ZERO_LABEL(strd);
157   ASSERT_ZERO_LABEL(strd[0]);
158   ASSERT_ZERO_LABEL(strd[1]);
159   ASSERT_ZERO_LABEL(strd[2]);
160   ASSERT_LABEL(strd[3], i_label);
161 
162   strd = strncpy(str2, str1, 3);
163   assert(strd == str2);
164   assert(strncmp(str1, str2, 3) == 0);
165   ASSERT_ZERO_LABEL(strd);
166   ASSERT_ZERO_LABEL(strd[0]);
167   ASSERT_ZERO_LABEL(strd[1]);
168   ASSERT_ZERO_LABEL(strd[2]);
169 }
170 
test_strncmp()171 void test_strncmp() {
172   char str1[] = "str1", str2[] = "str2";
173   dfsan_set_label(i_label, &str1[3], 1);
174   dfsan_set_label(j_label, &str2[3], 1);
175 
176   int rv = strncmp(str1, str2, sizeof(str1));
177   assert(rv < 0);
178 #ifdef STRICT_DATA_DEPENDENCIES
179   ASSERT_ZERO_LABEL(rv);
180 #else
181   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
182 #endif
183 
184   rv = strncmp(str1, str2, 3);
185   assert(rv == 0);
186   ASSERT_ZERO_LABEL(rv);
187 }
188 
test_strcasecmp()189 void test_strcasecmp() {
190   char str1[] = "str1", str2[] = "str2", str3[] = "Str1";
191   dfsan_set_label(i_label, &str1[3], 1);
192   dfsan_set_label(j_label, &str2[3], 1);
193   dfsan_set_label(j_label, &str3[2], 1);
194 
195   int rv = strcasecmp(str1, str2);
196   assert(rv < 0);
197 #ifdef STRICT_DATA_DEPENDENCIES
198   ASSERT_ZERO_LABEL(rv);
199 #else
200   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
201 #endif
202 
203   rv = strcasecmp(str1, str3);
204   assert(rv == 0);
205 #ifdef STRICT_DATA_DEPENDENCIES
206   ASSERT_ZERO_LABEL(rv);
207 #else
208   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
209 #endif
210 }
211 
test_strncasecmp()212 void test_strncasecmp() {
213   char str1[] = "Str1", str2[] = "str2";
214   dfsan_set_label(i_label, &str1[3], 1);
215   dfsan_set_label(j_label, &str2[3], 1);
216 
217   int rv = strncasecmp(str1, str2, sizeof(str1));
218   assert(rv < 0);
219 #ifdef STRICT_DATA_DEPENDENCIES
220   ASSERT_ZERO_LABEL(rv);
221 #else
222   ASSERT_LABEL(rv, dfsan_union(i_label, j_label));
223 #endif
224 
225   rv = strncasecmp(str1, str2, 3);
226   assert(rv == 0);
227   ASSERT_ZERO_LABEL(rv);
228 }
229 
test_strchr()230 void test_strchr() {
231   char str1[] = "str1";
232   dfsan_set_label(i_label, &str1[3], 1);
233 
234   char *crv = strchr(str1, 'r');
235   assert(crv == &str1[2]);
236   ASSERT_ZERO_LABEL(crv);
237 
238   crv = strchr(str1, '1');
239   assert(crv == &str1[3]);
240 #ifdef STRICT_DATA_DEPENDENCIES
241   ASSERT_ZERO_LABEL(crv);
242 #else
243   ASSERT_LABEL(crv, i_label);
244 #endif
245 
246   crv = strchr(str1, 'x');
247   assert(!crv);
248 #ifdef STRICT_DATA_DEPENDENCIES
249   ASSERT_ZERO_LABEL(crv);
250 #else
251   ASSERT_LABEL(crv, i_label);
252 #endif
253 }
254 
test_calloc()255 void test_calloc() {
256   // With any luck this sequence of calls will cause calloc to return the same
257   // pointer both times.  This is probably the best we can do to test this
258   // function.
259   char *crv = (char *) calloc(4096, 1);
260   ASSERT_ZERO_LABEL(crv[0]);
261   dfsan_set_label(i_label, crv, 100);
262   free(crv);
263 
264   crv = (char *) calloc(4096, 1);
265   ASSERT_ZERO_LABEL(crv[0]);
266   free(crv);
267 }
268 
test_read()269 void test_read() {
270   char buf[16];
271   dfsan_set_label(i_label, buf, 1);
272   dfsan_set_label(j_label, buf + 15, 1);
273 
274   ASSERT_LABEL(buf[0], i_label);
275   ASSERT_LABEL(buf[15], j_label);
276 
277   int fd = open("/dev/zero", O_RDONLY);
278   int rv = read(fd, buf, sizeof(buf));
279   assert(rv == sizeof(buf));
280   ASSERT_ZERO_LABEL(rv);
281   ASSERT_ZERO_LABEL(buf[0]);
282   ASSERT_ZERO_LABEL(buf[15]);
283   close(fd);
284 }
285 
test_pread()286 void test_pread() {
287   char buf[16];
288   dfsan_set_label(i_label, buf, 1);
289   dfsan_set_label(j_label, buf + 15, 1);
290 
291   ASSERT_LABEL(buf[0], i_label);
292   ASSERT_LABEL(buf[15], j_label);
293 
294   int fd = open("/bin/sh", O_RDONLY);
295   int rv = pread(fd, buf, sizeof(buf), 0);
296   assert(rv == sizeof(buf));
297   ASSERT_ZERO_LABEL(rv);
298   ASSERT_ZERO_LABEL(buf[0]);
299   ASSERT_ZERO_LABEL(buf[15]);
300   close(fd);
301 }
302 
test_dlopen()303 void test_dlopen() {
304   void *map = dlopen(NULL, RTLD_NOW);
305   assert(map);
306   ASSERT_ZERO_LABEL(map);
307   dlclose(map);
308   map = dlopen("/nonexistent", RTLD_NOW);
309   assert(!map);
310   ASSERT_ZERO_LABEL(map);
311 }
312 
test_clock_gettime()313 void test_clock_gettime() {
314   struct timespec tp;
315   dfsan_set_label(j_label, ((char *)&tp) + 3, 1);
316   int t = clock_gettime(CLOCK_REALTIME, &tp);
317   assert(t == 0);
318   ASSERT_ZERO_LABEL(t);
319   ASSERT_ZERO_LABEL(((char *)&tp)[3]);
320 }
321 
test_ctime_r()322 void test_ctime_r() {
323   char *buf = (char*) malloc(64);
324   time_t t = 0;
325 
326   char *ret = ctime_r(&t, buf);
327   ASSERT_ZERO_LABEL(ret);
328   assert(buf == ret);
329   ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1);
330 
331   dfsan_set_label(i_label, &t, sizeof(t));
332   ret = ctime_r(&t, buf);
333   ASSERT_ZERO_LABEL(ret);
334   ASSERT_READ_LABEL(buf, strlen(buf) + 1, i_label);
335 
336   t = 0;
337   dfsan_set_label(j_label, &buf, sizeof(&buf));
338   ret = ctime_r(&t, buf);
339   ASSERT_LABEL(ret, j_label);
340   ASSERT_READ_ZERO_LABEL(buf, strlen(buf) + 1);
341 }
342 
343 static int write_callback_count = 0;
344 static int last_fd;
345 static const unsigned char *last_buf;
346 static size_t last_count;
347 
write_callback(int fd,const void * buf,size_t count)348 void write_callback(int fd, const void *buf, size_t count) {
349   write_callback_count++;
350 
351   last_fd = fd;
352   last_buf = (const unsigned char*) buf;
353   last_count = count;
354 }
355 
test_dfsan_set_write_callback()356 void test_dfsan_set_write_callback() {
357   char buf[] = "Sample chars";
358   int buf_len = strlen(buf);
359 
360   int fd = open("/dev/null", O_WRONLY);
361 
362   dfsan_set_write_callback(write_callback);
363 
364   write_callback_count = 0;
365 
366   // Callback should be invoked on every call to write().
367   int res = write(fd, buf, buf_len);
368   assert(write_callback_count == 1);
369   ASSERT_READ_ZERO_LABEL(&res, sizeof(res));
370   ASSERT_READ_ZERO_LABEL(&last_fd, sizeof(last_fd));
371   ASSERT_READ_ZERO_LABEL(last_buf, sizeof(last_buf));
372   ASSERT_READ_ZERO_LABEL(&last_count, sizeof(last_count));
373 
374   // Add a label to write() arguments.  Check that the labels are readable from
375   // the values passed to the callback.
376   dfsan_set_label(i_label, &fd, sizeof(fd));
377   dfsan_set_label(j_label, &(buf[3]), 1);
378   dfsan_set_label(k_label, &buf_len, sizeof(buf_len));
379 
380   res = write(fd, buf, buf_len);
381   assert(write_callback_count == 2);
382   ASSERT_READ_ZERO_LABEL(&res, sizeof(res));
383   ASSERT_READ_LABEL(&last_fd, sizeof(last_fd), i_label);
384   ASSERT_READ_LABEL(&last_buf[3], sizeof(last_buf[3]), j_label);
385   ASSERT_READ_LABEL(last_buf, sizeof(last_buf), j_label);
386   ASSERT_READ_LABEL(&last_count, sizeof(last_count), k_label);
387 
388   dfsan_set_write_callback(NULL);
389 }
390 
test_fgets()391 void test_fgets() {
392   char *buf = (char*) malloc(128);
393   FILE *f = fopen("/etc/passwd", "r");
394   dfsan_set_label(j_label, buf, 1);
395   char *ret = fgets(buf, sizeof(buf), f);
396   assert(ret == buf);
397   ASSERT_ZERO_LABEL(ret);
398   ASSERT_READ_ZERO_LABEL(buf, 128);
399   dfsan_set_label(j_label, &buf, sizeof(&buf));
400   ret = fgets(buf, sizeof(buf), f);
401   ASSERT_LABEL(ret, j_label);
402   fclose(f);
403 }
404 
test_getcwd()405 void test_getcwd() {
406   char buf[1024];
407   char *ptr = buf;
408   dfsan_set_label(i_label, buf + 2, 2);
409   char* ret = getcwd(buf, sizeof(buf));
410   assert(ret == buf);
411   assert(ret[0] == '/');
412   ASSERT_READ_ZERO_LABEL(buf + 2, 2);
413   dfsan_set_label(i_label, &ptr, sizeof(ptr));
414   ret = getcwd(ptr, sizeof(buf));
415   ASSERT_LABEL(ret, i_label);
416 }
417 
test_get_current_dir_name()418 void test_get_current_dir_name() {
419   char* ret = get_current_dir_name();
420   assert(ret);
421   assert(ret[0] == '/');
422   ASSERT_READ_ZERO_LABEL(ret, strlen(ret) + 1);
423 }
424 
test_gethostname()425 void test_gethostname() {
426   char buf[1024];
427   dfsan_set_label(i_label, buf + 2, 2);
428   assert(gethostname(buf, sizeof(buf)) == 0);
429   ASSERT_READ_ZERO_LABEL(buf + 2, 2);
430 }
431 
test_getrlimit()432 void test_getrlimit() {
433   struct rlimit rlim;
434   dfsan_set_label(i_label, &rlim, sizeof(rlim));
435   assert(getrlimit(RLIMIT_CPU, &rlim) == 0);
436   ASSERT_READ_ZERO_LABEL(&rlim, sizeof(rlim));
437 }
438 
test_getrusage()439 void test_getrusage() {
440   struct rusage usage;
441   dfsan_set_label(i_label, &usage, sizeof(usage));
442   assert(getrusage(RUSAGE_SELF, &usage) == 0);
443   ASSERT_READ_ZERO_LABEL(&usage, sizeof(usage));
444 }
445 
test_strcpy()446 void test_strcpy() {
447   char src[] = "hello world";
448   char dst[sizeof(src) + 2];
449   dfsan_set_label(0, src, sizeof(src));
450   dfsan_set_label(0, dst, sizeof(dst));
451   dfsan_set_label(i_label, src + 2, 1);
452   dfsan_set_label(j_label, src + 3, 1);
453   dfsan_set_label(j_label, dst + 4, 1);
454   dfsan_set_label(i_label, dst + 12, 1);
455   char *ret = strcpy(dst, src);
456   assert(ret == dst);
457   assert(strcmp(src, dst) == 0);
458   for (int i = 0; i < strlen(src) + 1; ++i) {
459     assert(dfsan_get_label(dst[i]) == dfsan_get_label(src[i]));
460   }
461   // Note: if strlen(src) + 1 were used instead to compute the first untouched
462   // byte of dest, the label would be I|J. This is because strlen() might
463   // return a non-zero label, and because by default pointer labels are not
464   // ignored on loads.
465   ASSERT_LABEL(dst[12], i_label);
466 }
467 
test_strtol()468 void test_strtol() {
469   char buf[] = "1234578910";
470   char *endptr = NULL;
471   dfsan_set_label(i_label, buf + 1, 1);
472   dfsan_set_label(j_label, buf + 10, 1);
473   long int ret = strtol(buf, &endptr, 10);
474   assert(ret == 1234578910);
475   assert(endptr == buf + 10);
476   ASSERT_LABEL(ret, i_j_label);
477 }
478 
test_strtoll()479 void test_strtoll() {
480   char buf[] = "1234578910 ";
481   char *endptr = NULL;
482   dfsan_set_label(i_label, buf + 1, 1);
483   dfsan_set_label(j_label, buf + 2, 1);
484   long long int ret = strtoll(buf, &endptr, 10);
485   assert(ret == 1234578910);
486   assert(endptr == buf + 10);
487   ASSERT_LABEL(ret, i_j_label);
488 }
489 
test_strtoul()490 void test_strtoul() {
491   char buf[] = "0xffffffffffffaa";
492   char *endptr = NULL;
493   dfsan_set_label(i_label, buf + 1, 1);
494   dfsan_set_label(j_label, buf + 2, 1);
495   long unsigned int ret = strtol(buf, &endptr, 16);
496   assert(ret == 72057594037927850);
497   assert(endptr == buf + 16);
498   ASSERT_LABEL(ret, i_j_label);
499 }
500 
test_strtoull()501 void test_strtoull() {
502   char buf[] = "0xffffffffffffffaa";
503   char *endptr = NULL;
504   dfsan_set_label(i_label, buf + 1, 1);
505   dfsan_set_label(j_label, buf + 2, 1);
506   long long unsigned int ret = strtoull(buf, &endptr, 16);
507   assert(ret == 0xffffffffffffffaa);
508   assert(endptr == buf + 18);
509   ASSERT_LABEL(ret, i_j_label);
510 }
511 
test_strtod()512 void test_strtod() {
513   char buf[] = "12345.76 foo";
514   char *endptr = NULL;
515   dfsan_set_label(i_label, buf + 1, 1);
516   dfsan_set_label(j_label, buf + 6, 1);
517   double ret = strtod(buf, &endptr);
518   assert(ret == 12345.76);
519   assert(endptr == buf + 8);
520   ASSERT_LABEL(ret, i_j_label);
521 }
522 
test_time()523 void test_time() {
524   time_t t = 0;
525   dfsan_set_label(i_label, &t, 1);
526   time_t ret = time(&t);
527   assert(ret == t);
528   assert(ret > 0);
529   ASSERT_ZERO_LABEL(t);
530 }
531 
test_inet_pton()532 void test_inet_pton() {
533   char addr4[] = "127.0.0.1";
534   dfsan_set_label(i_label, addr4 + 3, 1);
535   struct in_addr in4;
536   int ret4 = inet_pton(AF_INET, addr4, &in4);
537   assert(ret4 == 1);
538   ASSERT_READ_LABEL(&in4, sizeof(in4), i_label);
539   assert(in4.s_addr == 0x0100007f);
540 
541   char addr6[] = "::1";
542   dfsan_set_label(j_label, addr6 + 3, 1);
543   struct in6_addr in6;
544   int ret6 = inet_pton(AF_INET6, addr6, &in6);
545   assert(ret6 == 1);
546   ASSERT_READ_LABEL(((char *) &in6) + sizeof(in6) - 1, 1, j_label);
547 }
548 
test_localtime_r()549 void test_localtime_r() {
550   time_t t0 = 1384800998;
551   struct tm t1;
552   dfsan_set_label(i_label, &t0, sizeof(t0));
553   struct tm* ret = localtime_r(&t0, &t1);
554   assert(ret == &t1);
555   assert(t1.tm_min == 56);
556   ASSERT_LABEL(t1.tm_mon, i_label);
557 }
558 
test_getpwuid_r()559 void test_getpwuid_r() {
560   struct passwd pwd;
561   char buf[1024];
562   struct passwd *result;
563 
564   dfsan_set_label(i_label, &pwd, 4);
565   int ret = getpwuid_r(0, &pwd, buf, sizeof(buf), &result);
566   assert(ret == 0);
567   assert(strcmp(pwd.pw_name, "root") == 0);
568   assert(result == &pwd);
569   ASSERT_READ_ZERO_LABEL(&pwd, 4);
570 }
571 
test_poll()572 void test_poll() {
573   struct pollfd fd;
574   fd.fd = 0;
575   fd.events = POLLIN;
576   dfsan_set_label(i_label, &fd.revents, sizeof(fd.revents));
577   int ret = poll(&fd, 1, 1);
578   ASSERT_ZERO_LABEL(fd.revents);
579   assert(ret >= 0);
580 }
581 
test_select()582 void test_select() {
583   struct timeval t;
584   fd_set fds;
585   t.tv_sec = 2;
586   FD_SET(0, &fds);
587   dfsan_set_label(i_label, &fds, sizeof(fds));
588   dfsan_set_label(j_label, &t, sizeof(t));
589   int ret = select(1, &fds, NULL, NULL, &t);
590   assert(ret >= 0);
591   ASSERT_ZERO_LABEL(t.tv_sec);
592   ASSERT_READ_ZERO_LABEL(&fds, sizeof(fds));
593 }
594 
test_sched_getaffinity()595 void test_sched_getaffinity() {
596   cpu_set_t mask;
597   dfsan_set_label(j_label, &mask, 1);
598   int ret = sched_getaffinity(0, sizeof(mask), &mask);
599   assert(ret == 0);
600   ASSERT_READ_ZERO_LABEL(&mask, sizeof(mask));
601 }
602 
test_sigemptyset()603 void test_sigemptyset() {
604   sigset_t set;
605   dfsan_set_label(j_label, &set, 1);
606   int ret = sigemptyset(&set);
607   assert(ret == 0);
608   ASSERT_READ_ZERO_LABEL(&set, sizeof(set));
609 }
610 
test_sigaction()611 void test_sigaction() {
612   struct sigaction oldact;
613   dfsan_set_label(j_label, &oldact, 1);
614   int ret = sigaction(SIGUSR1, NULL, &oldact);
615   assert(ret == 0);
616   ASSERT_READ_ZERO_LABEL(&oldact, sizeof(oldact));
617 }
618 
test_gettimeofday()619 void test_gettimeofday() {
620   struct timeval tv;
621   struct timezone tz;
622   dfsan_set_label(i_label, &tv, sizeof(tv));
623   dfsan_set_label(j_label, &tz, sizeof(tz));
624   int ret = gettimeofday(&tv, &tz);
625   assert(ret == 0);
626   ASSERT_READ_ZERO_LABEL(&tv, sizeof(tv));
627   ASSERT_READ_ZERO_LABEL(&tz, sizeof(tz));
628 }
629 
pthread_create_test_cb(void * p)630 void *pthread_create_test_cb(void *p) {
631   assert(p == (void *)1);
632   ASSERT_ZERO_LABEL(p);
633   return (void *)2;
634 }
635 
test_pthread_create()636 void test_pthread_create() {
637   pthread_t pt;
638   pthread_create(&pt, 0, pthread_create_test_cb, (void *)1);
639   void *cbrv;
640   pthread_join(pt, &cbrv);
641   assert(cbrv == (void *)2);
642 }
643 
dl_iterate_phdr_test_cb(struct dl_phdr_info * info,size_t size,void * data)644 int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size,
645                             void *data) {
646   assert(data == (void *)3);
647   ASSERT_ZERO_LABEL(info);
648   ASSERT_ZERO_LABEL(size);
649   ASSERT_ZERO_LABEL(data);
650   return 0;
651 }
652 
test_dl_iterate_phdr()653 void test_dl_iterate_phdr() {
654   dl_iterate_phdr(dl_iterate_phdr_test_cb, (void *)3);
655 }
656 
test_strrchr()657 void test_strrchr() {
658   char str1[] = "str1str1";
659   dfsan_set_label(i_label, &str1[7], 1);
660 
661   char *rv = strrchr(str1, 'r');
662   assert(rv == &str1[6]);
663 #ifdef STRICT_DATA_DEPENDENCIES
664   ASSERT_ZERO_LABEL(rv);
665 #else
666   ASSERT_LABEL(rv, i_label);
667 #endif
668 }
669 
test_strstr()670 void test_strstr() {
671   char str1[] = "str1str1";
672   dfsan_set_label(i_label, &str1[3], 1);
673   dfsan_set_label(j_label, &str1[5], 1);
674 
675   char *rv = strstr(str1, "1s");
676   assert(rv == &str1[3]);
677 #ifdef STRICT_DATA_DEPENDENCIES
678   ASSERT_ZERO_LABEL(rv);
679 #else
680   ASSERT_LABEL(rv, i_label);
681 #endif
682 
683   rv = strstr(str1, "2s");
684   assert(rv == NULL);
685 #ifdef STRICT_DATA_DEPENDENCIES
686   ASSERT_ZERO_LABEL(rv);
687 #else
688   ASSERT_LABEL(rv, i_j_label);
689 #endif
690 }
691 
test_memchr()692 void test_memchr() {
693   char str1[] = "str1";
694   dfsan_set_label(i_label, &str1[3], 1);
695   dfsan_set_label(j_label, &str1[4], 1);
696 
697   char *crv = (char *) memchr(str1, 'r', sizeof(str1));
698   assert(crv == &str1[2]);
699   ASSERT_ZERO_LABEL(crv);
700 
701   crv = (char *) memchr(str1, '1', sizeof(str1));
702   assert(crv == &str1[3]);
703 #ifdef STRICT_DATA_DEPENDENCIES
704   ASSERT_ZERO_LABEL(crv);
705 #else
706   ASSERT_LABEL(crv, i_label);
707 #endif
708 
709   crv = (char *) memchr(str1, 'x', sizeof(str1));
710   assert(!crv);
711 #ifdef STRICT_DATA_DEPENDENCIES
712   ASSERT_ZERO_LABEL(crv);
713 #else
714   ASSERT_LABEL(crv, i_j_label);
715 #endif
716 }
717 
alarm_handler(int unused)718 void alarm_handler(int unused) {
719   ;
720 }
721 
test_nanosleep()722 void test_nanosleep() {
723   struct timespec req, rem;
724   req.tv_sec = 1;
725   req.tv_nsec = 0;
726   dfsan_set_label(i_label, &rem, sizeof(rem));
727 
728   // non interrupted
729   int rv = nanosleep(&req, &rem);
730   assert(rv == 0);
731   ASSERT_ZERO_LABEL(rv);
732   ASSERT_READ_LABEL(&rem, 1, i_label);
733 
734   // interrupted by an alarm
735   signal(SIGALRM, alarm_handler);
736   req.tv_sec = 3;
737   alarm(1);
738   rv = nanosleep(&req, &rem);
739   assert(rv == -1);
740   ASSERT_ZERO_LABEL(rv);
741   ASSERT_READ_ZERO_LABEL(&rem, sizeof(rem));
742 }
743 
test_socketpair()744 void test_socketpair() {
745   int fd[2];
746 
747   dfsan_set_label(i_label, fd, sizeof(fd));
748   int rv = socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
749   assert(rv == 0);
750   ASSERT_ZERO_LABEL(rv);
751   ASSERT_READ_ZERO_LABEL(fd, sizeof(fd));
752 }
753 
test_write()754 void test_write() {
755   int fd = open("/dev/null", O_WRONLY);
756 
757   char buf[] = "a string";
758   int len = strlen(buf);
759 
760   // The result of a write always unlabeled.
761   int res = write(fd, buf, len);
762   assert(res > 0);
763   ASSERT_ZERO_LABEL(res);
764 
765   // Label all arguments to write().
766   dfsan_set_label(i_label, &(buf[3]), 1);
767   dfsan_set_label(j_label, &fd, sizeof(fd));
768   dfsan_set_label(i_label, &len, sizeof(len));
769 
770   // The value returned by write() should have no label.
771   res = write(fd, buf, len);
772   ASSERT_ZERO_LABEL(res);
773 
774   close(fd);
775 }
776 
777 template <class T>
test_sprintf_chunk(const char * expected,const char * format,T arg)778 void test_sprintf_chunk(const char* expected, const char* format, T arg) {
779   char buf[512];
780   memset(buf, 'a', sizeof(buf));
781 
782   char padded_expected[512];
783   strcpy(padded_expected, "foo ");
784   strcat(padded_expected, expected);
785   strcat(padded_expected, " bar");
786 
787   char padded_format[512];
788   strcpy(padded_format, "foo ");
789   strcat(padded_format, format);
790   strcat(padded_format, " bar");
791 
792   // Non labelled arg.
793   assert(sprintf(buf, padded_format,  arg) == strlen(padded_expected));
794   assert(strcmp(buf, padded_expected) == 0);
795   ASSERT_READ_LABEL(buf, strlen(padded_expected), 0);
796   memset(buf, 'a', sizeof(buf));
797 
798   // Labelled arg.
799   dfsan_set_label(i_label, &arg, sizeof(arg));
800   assert(sprintf(buf, padded_format,  arg) == strlen(padded_expected));
801   assert(strcmp(buf, padded_expected) == 0);
802   ASSERT_READ_LABEL(buf, 4, 0);
803   ASSERT_READ_LABEL(buf + 4, strlen(padded_expected) - 8, i_label);
804   ASSERT_READ_LABEL(buf + (strlen(padded_expected) - 4), 4, 0);
805 }
806 
test_sprintf()807 void test_sprintf() {
808   char buf[2048];
809   memset(buf, 'a', sizeof(buf));
810 
811   // Test formatting (no conversion specifier).
812   assert(sprintf(buf, "Hello world!") == 12);
813   assert(strcmp(buf, "Hello world!") == 0);
814   ASSERT_READ_LABEL(buf, sizeof(buf), 0);
815 
816   // Test for extra arguments.
817   assert(sprintf(buf, "Hello world!", 42, "hello") == 12);
818   assert(strcmp(buf, "Hello world!") == 0);
819   ASSERT_READ_LABEL(buf, sizeof(buf), 0);
820 
821   // Test formatting & label propagation (multiple conversion specifiers): %s,
822   // %d, %n, %f, and %%.
823   const char* s = "world";
824   int m = 8;
825   int d = 27;
826   dfsan_set_label(k_label, (void *) (s + 1), 2);
827   dfsan_set_label(i_label, &m, sizeof(m));
828   dfsan_set_label(j_label, &d, sizeof(d));
829   int n;
830   int r = sprintf(buf, "hello %s, %-d/%d/%d %f %% %n%d", s, 2014, m, d,
831                   12345.6781234, &n, 1000);
832   assert(r == 42);
833   assert(strcmp(buf, "hello world, 2014/8/27 12345.678123 % 1000") == 0);
834   ASSERT_READ_LABEL(buf, 7, 0);
835   ASSERT_READ_LABEL(buf + 7, 2, k_label);
836   ASSERT_READ_LABEL(buf + 9, 9, 0);
837   ASSERT_READ_LABEL(buf + 18, 1, i_label);
838   ASSERT_READ_LABEL(buf + 19, 1, 0);
839   ASSERT_READ_LABEL(buf + 20, 2, j_label);
840   ASSERT_READ_LABEL(buf + 22, 15, 0);
841   ASSERT_LABEL(r, 0);
842   assert(n == 38);
843 
844   // Test formatting & label propagation (single conversion specifier, with
845   // additional length and precision modifiers).
846   test_sprintf_chunk("-559038737", "%d", 0xdeadbeef);
847   test_sprintf_chunk("3735928559", "%u", 0xdeadbeef);
848   test_sprintf_chunk("12345", "%i", 12345);
849   test_sprintf_chunk("751", "%o", 0751);
850   test_sprintf_chunk("babe", "%x", 0xbabe);
851   test_sprintf_chunk("0000BABE", "%.8X", 0xbabe);
852   test_sprintf_chunk("-17", "%hhd", 0xdeadbeef);
853   test_sprintf_chunk("-16657", "%hd", 0xdeadbeef);
854   test_sprintf_chunk("deadbeefdeadbeef", "%lx", 0xdeadbeefdeadbeef);
855   test_sprintf_chunk("0xdeadbeefdeadbeef", "%p",
856                  (void *)  0xdeadbeefdeadbeef);
857   test_sprintf_chunk("18446744073709551615", "%ju", (intmax_t) -1);
858   test_sprintf_chunk("18446744073709551615", "%zu", (size_t) -1);
859   test_sprintf_chunk("18446744073709551615", "%tu", (size_t) -1);
860 
861   test_sprintf_chunk("0x1.f9acffa7eb6bfp-4", "%a", 0.123456);
862   test_sprintf_chunk("0X1.F9ACFFA7EB6BFP-4", "%A", 0.123456);
863   test_sprintf_chunk("0.12346", "%.5f", 0.123456);
864   test_sprintf_chunk("0.123456", "%g", 0.123456);
865   test_sprintf_chunk("1.234560e-01", "%e", 0.123456);
866   test_sprintf_chunk("1.234560E-01", "%E", 0.123456);
867   test_sprintf_chunk("0.1234567891234560", "%.16Lf",
868                      (long double) 0.123456789123456);
869 
870   test_sprintf_chunk("z", "%c", 'z');
871 
872   // %n, %s, %d, %f, and %% already tested
873 
874   // Test formatting with width passed as an argument.
875   r = sprintf(buf, "hi %*d my %*s friend %.*f", 3, 1, 6, "dear", 4, 3.14159265359);
876   assert(r == 30);
877   assert(strcmp(buf, "hi   1 my   dear friend 3.1416") == 0);
878 }
879 
test_snprintf()880 void test_snprintf() {
881   char buf[2048];
882   memset(buf, 'a', sizeof(buf));
883   dfsan_set_label(0, buf, sizeof(buf));
884   const char* s = "world";
885   int y = 2014;
886   int m = 8;
887   int d = 27;
888   dfsan_set_label(k_label, (void *) (s + 1), 2);
889   dfsan_set_label(i_label, &y, sizeof(y));
890   dfsan_set_label(j_label, &m, sizeof(m));
891   int r = snprintf(buf, 19, "hello %s, %-d/%d/%d %f", s, y, m, d,
892                    12345.6781234);
893   // The return value is the number of bytes that would have been written to
894   // the final string if enough space had been available.
895   assert(r == 35);
896   assert(memcmp(buf, "hello world, 2014/", 19) == 0);
897   ASSERT_READ_LABEL(buf, 7, 0);
898   ASSERT_READ_LABEL(buf + 7, 2, k_label);
899   ASSERT_READ_LABEL(buf + 9, 4, 0);
900   ASSERT_READ_LABEL(buf + 13, 4, i_label);
901   ASSERT_READ_LABEL(buf + 17, 2, 0);
902   ASSERT_LABEL(r, 0);
903 }
904 
main(void)905 int main(void) {
906   i_label = dfsan_create_label("i", 0);
907   j_label = dfsan_create_label("j", 0);
908   k_label = dfsan_create_label("k", 0);
909   i_j_label = dfsan_union(i_label, j_label);
910 
911   test_calloc();
912   test_clock_gettime();
913   test_ctime_r();
914   test_dfsan_set_write_callback();
915   test_dl_iterate_phdr();
916   test_dlopen();
917   test_fgets();
918   test_fstat();
919   test_get_current_dir_name();
920   test_getcwd();
921   test_gethostname();
922   test_getpwuid_r();
923   test_getrlimit();
924   test_getrusage();
925   test_gettimeofday();
926   test_inet_pton();
927   test_localtime_r();
928   test_memchr();
929   test_memcmp();
930   test_memcpy();
931   test_memset();
932   test_nanosleep();
933   test_poll();
934   test_pread();
935   test_pthread_create();
936   test_read();
937   test_sched_getaffinity();
938   test_select();
939   test_sigaction();
940   test_sigemptyset();
941   test_snprintf();
942   test_socketpair();
943   test_sprintf();
944   test_stat();
945   test_strcasecmp();
946   test_strchr();
947   test_strcmp();
948   test_strcpy();
949   test_strdup();
950   test_strlen();
951   test_strncasecmp();
952   test_strncmp();
953   test_strncpy();
954   test_strrchr();
955   test_strstr();
956   test_strtod();
957   test_strtol();
958   test_strtoll();
959   test_strtoul();
960   test_strtoull();
961   test_time();
962   test_write();
963 }
964