1 | // DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -o %t && %run %t |
2 | // DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -o %t && %run %t |
3 | // DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -o %t && %run %t |
4 | // DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -o %t && %run %t |
5 | |
6 | #include <assert.h> |
7 | #include <sanitizer/dfsan_interface.h> |
8 | #include <stdbool.h> |
9 | #include <stdio.h> |
10 | #include <string.h> |
11 | #include <sys/mman.h> |
12 | #include <unistd.h> |
13 | |
14 | size_t () { |
15 | size_t ret = 0; |
16 | pid_t pid = getpid(); |
17 | |
18 | char fname[256]; |
19 | sprintf(s: fname, format: "/proc/%ld/task/%ld/smaps" , (long)pid, (long)pid); |
20 | FILE *f = fopen(filename: fname, modes: "r" ); |
21 | assert(f); |
22 | |
23 | char buf[256]; |
24 | while (fgets(s: buf, n: sizeof(buf), stream: f) != NULL) { |
25 | int64_t ; |
26 | if (sscanf(s: buf, format: "Rss: %ld kB" , &rss) == 1) |
27 | ret += rss; |
28 | } |
29 | assert(feof(f)); |
30 | fclose(stream: f); |
31 | |
32 | return ret; |
33 | } |
34 | |
35 | int main(int argc, char **argv) { |
36 | const size_t map_size = 100 << 20; |
37 | size_t before = get_rss_kb(); |
38 | |
39 | // mmap and touch all addresses. The overhead is 1x. |
40 | char *p = mmap(NULL, len: map_size, PROT_READ | PROT_WRITE, |
41 | MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0); |
42 | memset(s: p, c: 0xff, n: map_size); |
43 | size_t after_mmap = get_rss_kb(); |
44 | |
45 | // store labels to all addresses. The overhead is 2x. |
46 | const dfsan_label label = 8; |
47 | char val = 0xff; |
48 | dfsan_set_label(label, addr: &val, size: sizeof(val)); |
49 | memset(s: p, c: val, n: map_size); |
50 | size_t after_mmap_and_set_label = get_rss_kb(); |
51 | |
52 | // fixed-mmap the same address. OS recyles pages and reinitializes data at the |
53 | // address. This should be the same to calling munmap. |
54 | p = mmap(addr: p, len: map_size, PROT_READ | PROT_WRITE, |
55 | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, fd: -1, offset: 0); |
56 | size_t after_fixed_mmap = get_rss_kb(); |
57 | |
58 | // store labels to all addresses. |
59 | memset(s: p, c: val, n: map_size); |
60 | size_t after_mmap_and_set_label2 = get_rss_kb(); |
61 | |
62 | // munmap the addresses. |
63 | munmap(addr: p, len: map_size); |
64 | size_t after_munmap = get_rss_kb(); |
65 | |
66 | fprintf( |
67 | stderr, |
68 | format: "RSS at start: %zu, after mmap: %zu, after mmap+set label: %zu, after " |
69 | "fixed map: %zu, after another mmap+set label: %zu, after munmap: %zu\n" , |
70 | before, after_mmap, after_mmap_and_set_label, after_fixed_mmap, |
71 | after_mmap_and_set_label2, after_munmap); |
72 | |
73 | const size_t mmap_cost_kb = map_size >> 10; |
74 | // Shadow space (1:1 with application memory) |
75 | const size_t mmap_shadow_cost_kb = sizeof(dfsan_label) * mmap_cost_kb; |
76 | #ifdef ORIGIN_TRACKING |
77 | // Origin space (1:1 with application memory) |
78 | const size_t mmap_origin_cost_kb = mmap_cost_kb; |
79 | #else |
80 | const size_t mmap_origin_cost_kb = 0; |
81 | #endif |
82 | assert(after_mmap >= before + mmap_cost_kb); |
83 | assert(after_mmap_and_set_label >= |
84 | after_mmap + mmap_shadow_cost_kb + mmap_origin_cost_kb); |
85 | assert(after_mmap_and_set_label2 >= |
86 | before + mmap_cost_kb + mmap_shadow_cost_kb + mmap_origin_cost_kb); |
87 | |
88 | #ifdef ORIGIN_TRACKING |
89 | // This value is chosen based on observed difference. |
90 | const size_t mmap_origin_chain_kb = 4000; |
91 | #else |
92 | const size_t mmap_origin_chain_kb = 0; |
93 | #endif |
94 | |
95 | // RSS may not change memory amount after munmap to the same level as the |
96 | // start of the program. The assert checks the memory up to a delta. |
97 | const size_t delta = 5000; |
98 | // Origin chains are not freed, even when the origin space which refers to |
99 | // them is freed, so mmap_origin_chain_kb is added to account for this. |
100 | assert(after_fixed_mmap <= before + delta + mmap_origin_chain_kb); |
101 | assert(after_munmap <= before + delta + mmap_origin_chain_kb); |
102 | |
103 | return 0; |
104 | } |
105 | |