├── .gitignore ├── 1_phy2dram_mapping ├── Makefile ├── README.md └── latency.c ├── 2_find_aggressors ├── Makefile ├── README.md ├── pagemap.c └── pagemap.h ├── 3_rowhammer_test ├── Makefile ├── README.md ├── find_vulnerable.c └── input │ └── input0 ├── 4_experiments ├── bitflip_iteration │ ├── Makefile │ ├── bitflip_iteration.c │ └── input │ │ ├── flippable_all │ │ ├── input0 │ │ └── input_mixed ├── compare_all_instr │ ├── Makefile │ ├── compare_instr.c │ └── input │ │ ├── flippable_all │ │ ├── input0 │ │ └── input_mixed ├── disable_cachemaint │ ├── Makefile │ ├── README.md │ ├── disable_cache_maint.c │ └── execute.sh ├── multi_thread │ ├── Makefile │ ├── input │ │ ├── flippable_all │ │ ├── input0 │ │ └── input_mixed │ └── multi_thread.c └── time_measure │ ├── Makefile │ └── time_measure.c ├── 5_modify_refresh_rate ├── Makefile ├── README.md └── sysreg.c └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /1_phy2dram_mapping/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += latency.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | 9 | test: 10 | sudo dmesg -C 11 | sudo insmod latency.ko 12 | sudo rmmod latency.ko 13 | dmesg 14 | -------------------------------------------------------------------------------- /1_phy2dram_mapping/README.md: -------------------------------------------------------------------------------- 1 | # Reverse engineering address mapping 2 | * This mapping is done using kernel module 3 | * Use methods provided in **One Bit Flip, One Cloud Flops: Cross-VM Row Hammer 4 | Attacks and Privilege Escalation** by Yuan Xiao et al. 5 | 6 | * The output shows the time needed to access two physical addresses with 7 | two bits different (latency). 8 | * The output has the form L(i,j): T, meaning when two addresses are different 9 | in bit i and bit j, the access time is T. (if i=j, they have only one 10 | different bit. 11 | * Only when two addresses are in different rows of the same bank, the latency 12 | is large, we can use this feature to identify the row, column, bank bits. 13 | * The mapping on ARM is relatively simpler than on x86. This is enough for us 14 | to find the lowest row bit 15 | 16 | -------------------------------------------------------------------------------- /1_phy2dram_mapping/latency.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * two_bit_latency-armv8 -- measure the latency between accessing two addresses 3 | with two bits different on ARMv8 4 | * By VandySec Group 5 | *******************************************************************************/ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define LAT_ARRAY_SIZE 8 * 1024 * 1024 13 | #define LAT_LENGTH 22 14 | 15 | char array[LAT_ARRAY_SIZE]; 16 | 17 | int 18 | module_bgn(void) 19 | { 20 | 21 | int i, j, k, l; 22 | unsigned sum = 0; 23 | unsigned long writeValue = 0; 24 | unsigned long t1 = 0; 25 | unsigned long t2 = 0; 26 | unsigned long temp = 0; 27 | unsigned long basis; 28 | unsigned long v_addr; 29 | unsigned long v_addr_0; 30 | unsigned long v_addr_1; 31 | unsigned diff_bit; 32 | unsigned diff_bit2; 33 | unsigned long mask; 34 | //unsigned long p_addr; 35 | unsigned long random; 36 | // Start 37 | printk(KERN_INFO "Insert module \n"); 38 | 39 | // Set up PMU 40 | // enable PMC 41 | writeValue = 0x80000000; 42 | asm volatile("MSR PMCNTENSET_EL0, %0":: "r" (writeValue)); 43 | // Performance Control Register | 00111 | 44 | // Always enable cycle counter | enable export events | 45 | // disable clock divider | reset clock couner | reset event couner 46 | writeValue = 0x00000007; 47 | asm volatile("MSR PMCR_EL0, %0":: "r" (writeValue)); 48 | 49 | // Initialize basis 50 | basis = (unsigned long) array; 51 | basis >>= LAT_LENGTH; 52 | basis += 1; 53 | basis <<= LAT_LENGTH; 54 | 55 | for (l = 6; l < LAT_LENGTH; l++) { 56 | for (k = 6; k < LAT_LENGTH; k++) { 57 | diff_bit = k; 58 | diff_bit2 = l; 59 | mask = (1 << diff_bit) | (1 << diff_bit2); 60 | for (j = 0; j < 100; j++) { 61 | // Two address differs only in diff_bit 62 | get_random_bytes(&random, 8); 63 | random >>= (64 - LAT_LENGTH); 64 | v_addr = basis + random; 65 | v_addr_1 = v_addr | mask; 66 | v_addr_0 = v_addr & ~(mask); 67 | 68 | preempt_disable(); 69 | 70 | // Barrier 71 | asm volatile("DSB 0XF"); 72 | asm volatile("ISB"); 73 | 74 | // Cycle Counter1 t1 75 | asm volatile("MRS %0, PMCCNTR_EL0":"=r" (t1)); 76 | for (i = 0; i < 1000; ++i) { 77 | // Load 78 | asm volatile("ldr %[d], [%[a]]"::[d] "r" (temp), [a] "r" (v_addr_0)); 79 | asm volatile("ldr %[d], [%[a]]"::[d] "r" (temp), [a] "r" (v_addr_1)); 80 | // Clear by VA 81 | asm volatile("DC CIVAC, %0"::"r" (v_addr_0)); 82 | asm volatile("DC CIVAC, %0"::"r" (v_addr_1)); 83 | 84 | // Barier 85 | asm volatile("DSB 0XF"); 86 | asm volatile("ISB"); 87 | } 88 | // Cycle Counter 2 t2 89 | asm volatile("MRS %0, PMCCNTR_EL0":"=r" (t2)); 90 | 91 | preempt_enable(); 92 | 93 | sum += (t2 - t1); 94 | } 95 | sum /= 100000; 96 | printk("L(%2u, %2u): %u \t",diff_bit, diff_bit2, sum); 97 | } 98 | printk("\n"); 99 | } 100 | return 0; 101 | } 102 | 103 | void 104 | module_end(void) 105 | { 106 | printk(KERN_INFO "Remove module \n"); 107 | } 108 | 109 | module_init(module_bgn); 110 | module_exit(module_end); 111 | 112 | MODULE_LICENSE("GPL"); 113 | MODULE_AUTHOR("VandySec Group"); 114 | MODULE_DESCRIPTION("Two-bit latency on ARMv8"); 115 | MODULE_VERSION("0.01"); 116 | 117 | -------------------------------------------------------------------------------- /2_find_aggressors/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all : librowhammer.so 3 | 4 | librowhammer.so : pagemap.c 5 | gcc -fPIC -shared -o librowhammer.so pagemap.c 6 | 7 | install : 8 | sudo cp librowhammer.so /usr/local/lib/ 9 | sudo cp pagemap.h /usr/local/include/ 10 | sudo ldconfig 11 | 12 | uninstall : 13 | sudo rm /usr/local/lib/librowhammer.so 14 | sudo rm /usr/local/include/pagemap.h 15 | 16 | -------------------------------------------------------------------------------- /2_find_aggressors/README.md: -------------------------------------------------------------------------------- 1 | # Find Aggressors 2 | 3 | This is the library used to find candidate aggressor rows 4 | 5 | To perform rowhammer test without input file, this module must be installed 6 | 7 | ## How to use 8 | make 9 | 10 | make install 11 | 12 | -------------------------------------------------------------------------------- /2_find_aggressors/pagemap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * pagemap -- find candidate aggressor rows to hammer 3 | * By VandySec Group 4 | **/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "pagemap.h" 10 | 11 | candidate_t * 12 | find_candidates(unsigned long addr_bgn, unsigned long addr_end, 13 | unsigned page_bits, unsigned target_bit) 14 | { 15 | unsigned i; 16 | unsigned page_size = 1 << page_bits; 17 | pid_t pid = getpid(); 18 | FILE *fp; 19 | char path[200]; 20 | unsigned long va; 21 | unsigned long pa; 22 | uint64_t offset; 23 | uint64_t val; 24 | uint64_t pfn; 25 | 26 | candidate_t *head = NULL; 27 | candidate_t *temp = NULL; 28 | candidate_t *prev; 29 | candidate_t *curr; 30 | 31 | // if page_bits is 12, then 11...0 are used for page offset 32 | if (addr_end <= addr_bgn || target_bit < page_bits) { 33 | printf("not well-defined arguments\n"); 34 | exit(-1); 35 | } 36 | 37 | sprintf(path, "/proc/%u/pagemap", pid); 38 | fp = fopen(path, "rb"); 39 | 40 | va = addr_bgn >> page_bits; 41 | va <<= page_bits; 42 | if (va < addr_bgn) 43 | va += page_size; 44 | 45 | while (va < addr_end) { 46 | offset = va / page_size * 8; 47 | fseek(fp, offset, SEEK_SET); 48 | val = 0; 49 | for (i = 0; i < 8; ++i) { 50 | unsigned char c = getc(fp); 51 | val |= ((uint64_t) c << (8 * i)); 52 | } 53 | 54 | if (val & 0x8000000000000000 == 0) { 55 | printf("some page is not in memory yet\n"); 56 | exit(-1); 57 | } 58 | 59 | pfn = val & 0x7FFFFFFFFFFFFF; 60 | pa = pfn << page_bits; 61 | 62 | prev = NULL; 63 | curr = temp; 64 | while (curr != NULL) { 65 | if ((pa ^ curr->pa1) != (1 << target_bit)) { 66 | prev = curr; 67 | curr = curr->next; 68 | continue; 69 | } 70 | // matching candidate is found, so move it into another list 71 | curr->pa2 = pa; 72 | curr->va2 = va; 73 | if (prev != NULL) 74 | prev->next = curr->next; 75 | else 76 | temp = curr->next; 77 | curr->next = head; 78 | head = curr; 79 | break; 80 | } 81 | 82 | // if we didn't find a matching candidate 83 | if (curr == NULL) { 84 | curr = (candidate_t *) malloc(sizeof(candidate_t)); 85 | curr->pa1 = pa; 86 | curr->va1 = va; 87 | curr->next = temp; 88 | temp = curr; 89 | } 90 | 91 | va += page_size; 92 | } 93 | 94 | cleanup_candidates(temp); 95 | return head; 96 | } 97 | 98 | void 99 | cleanup_candidates(candidate_t *head) 100 | { 101 | candidate_t *curr; 102 | while (head != NULL) { 103 | curr = head; 104 | head = head->next; 105 | free(curr); 106 | } 107 | } 108 | 109 | -------------------------------------------------------------------------------- /2_find_aggressors/pagemap.h: -------------------------------------------------------------------------------- 1 | #ifndef ROWHAMMER_PAGEMAP_H 2 | #define ROWHAMMER_PAGEMAP_H 3 | 4 | typedef struct candidate { 5 | unsigned long pa1; 6 | unsigned long va1; 7 | unsigned long pa2; 8 | unsigned long va2; 9 | struct candidate *next; 10 | } candidate_t; 11 | 12 | candidate_t * 13 | find_candidates(unsigned long, unsigned long, unsigned, unsigned); 14 | 15 | void 16 | cleanup_candidates(candidate_t *); 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /3_rowhammer_test/Makefile: -------------------------------------------------------------------------------- 1 | FNAME=input0 2 | all : 3 | gcc find_vulnerable.c -lrowhammer -pthread 4 | 5 | run : 6 | sudo ./a.out 7 | clean : 8 | rm ./a.out 9 | send : 10 | cat results_0_to_1 results_1_to_0 > results 11 | cp results ../4_experiments/bitflip_iteration/input/$(FNAME) 12 | cp results ../4_experiments/compare_all_instr/input/$(FNAME) 13 | cp results ../4_experiments/multi_thread/input/$(FNAME) 14 | -------------------------------------------------------------------------------- /3_rowhammer_test/README.md: -------------------------------------------------------------------------------- 1 | # Find Vulnerable Bits 2 | * This code is used to search for vulnerable bits by hammering: 3 | 1. Address pairs given in an input file 4 | 2. Address pairs found in a large address pool 5 | * The input(if available) and output has the same format 6 | * Aggressor_phys_addr1 aggressor_phys_addr2 initial_bit 7 | * Contains the physical addresses of two aggressor rows. 8 | * If the initial_bit is 0, 0_to_1 bit flip can occur in the victim row 9 | * If the initial_bit is 1, 1_to_0 bit flip can occur in the victim row 10 | * The output can be used as input in ../final_experients/ directory 11 | * Use make send FNAME=(FILENAME) to copy the output to the input directories 12 | * Specify the name to be stored as FILENAME 13 | -------------------------------------------------------------------------------- /3_rowhammer_test/find_vulnerable.c: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * find_vulnerable -- find bits that are easy to be flipped 3 | * By VandySec Group 4 | *******************************************************************************/ 5 | #define _GNU_SOURCE 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define PAGE_SIZE 4096 19 | #define VAL_SIZE sizeof(unsigned long) 20 | /******************************************************************************* 21 | * Parameters: 22 | * CHUNK_SIZE :Size of the memory chunk where we implement rowhammer attacks 23 | * VPN_SIZE :Size of the array used to store virtual page number 24 | * TIMES :Number of aggressor pairs to be hammered 25 | * HAMMER_ROUND:Number of iterataions to repeatedly access the aggressor rows 26 | * USE_INPUT :Obtain aggressor rows from input(1)/ using find_candidate()(0) 27 | * INPUT_FILE :If input file is used, specify the path to the input file 28 | * OUT_INTERVAL:The interval to display results 29 | * INIT_BIT :Initialize victim rows with 0/1 to find 0_to_1/1_to_0 bit flip 30 | *******************************************************************************/ 31 | #define CHUNK_SIZE 0x40000000 32 | #define VPN_SIZE 0x80000 33 | #define TIMES 150000 34 | #define HAMMER_ROUND 2500000 35 | #define USE_INPUT 0 36 | #define INPUT_FILE "input/input0" 37 | #define OUT_INTERVAL 100 38 | #define INIT_BIT 1 39 | 40 | // structure used to store possible aggressor pairs 41 | struct attkr_t{ 42 | unsigned long pa1; 43 | unsigned long pa2; 44 | unsigned long va1; 45 | unsigned long va2; 46 | unsigned long vctm_base; 47 | unsigned long init_val; 48 | struct attkr_t *next; 49 | }; 50 | 51 | // large chunk to search for vulnerable bits 52 | unsigned long chunk[CHUNK_SIZE / VAL_SIZE]; 53 | // virtual_to_physical mappint 54 | unsigned long va_tab[VPN_SIZE]; 55 | // counter for the number of bit flips 56 | unsigned cnt = 0; 57 | 58 | // function to generate physical to virtual address mapping 59 | void 60 | generate_va_table(int pgmp) 61 | { 62 | for (int i = 0; i < CHUNK_SIZE / VAL_SIZE; i += PAGE_SIZE / VAL_SIZE){ 63 | unsigned long data; 64 | unsigned long index = (unsigned long)&chunk[i] / PAGE_SIZE * sizeof(data); 65 | // read data in pagemap file 66 | if (pread(pgmp, &data, sizeof(data), index) != sizeof(data)) { 67 | perror("pread"); 68 | break; 69 | } 70 | // store the virtual page number 71 | unsigned long pfn = data & 0x7fffffffffffff; 72 | if (pfn <= 0 || pfn > VPN_SIZE){ 73 | perror("VPN_TABLE TOO SMALL"); 74 | break; 75 | } else 76 | va_tab[pfn] = index / sizeof(data) * PAGE_SIZE; 77 | } 78 | } 79 | 80 | // function convert physical address to virtual address 81 | unsigned long * 82 | pa_to_va(unsigned long pa) 83 | { 84 | unsigned long va_off = pa % PAGE_SIZE; 85 | unsigned long va_pfn = pa / PAGE_SIZE; 86 | if (va_tab[va_pfn] == 0) 87 | return 0; 88 | else 89 | return (unsigned long *)(va_tab[va_pfn] + va_off); 90 | } 91 | 92 | // generate a list of aggressor rows based on the input file 93 | struct attkr_t * 94 | generate_addr_list(char *fname) 95 | { 96 | FILE *f_in = fopen(fname, "r"); 97 | char str[999]; 98 | unsigned long attk_pa1, attk_pa2, attk_pfn1, attk_pfn2, init_val; 99 | struct attkr_t *head, *curr, *prev; 100 | head = NULL; 101 | curr = head; 102 | while (fscanf(f_in, "%s", str) != EOF){ 103 | attk_pa1 = (unsigned long)strtol(str, NULL, 16); 104 | fscanf(f_in, "%s", str); 105 | attk_pa2 = (unsigned long)strtol(str, NULL, 16); 106 | fscanf(f_in, "%s", str); 107 | init_val = (unsigned long)(-strtol(str, NULL, 10)); 108 | attk_pfn1 = attk_pa1 / PAGE_SIZE; 109 | attk_pfn2 = attk_pa2 / PAGE_SIZE; 110 | curr = (struct attkr_t *)malloc(sizeof(struct attkr_t)); 111 | curr->pa1 = attk_pa1; 112 | curr->pa2 = attk_pa2; 113 | curr->va1 = (unsigned long)pa_to_va(attk_pa1); 114 | curr->va2 = (unsigned long)pa_to_va(attk_pa2); 115 | curr->vctm_base = (attk_pfn1 + attk_pfn2) / 2 * PAGE_SIZE; 116 | curr->init_val = init_val; 117 | curr->next = NULL; 118 | 119 | if (curr->va1 == 0 || curr->va2 == 0){ 120 | free(curr); 121 | continue; 122 | } else if (head == NULL){ 123 | head = curr; 124 | prev = head; 125 | } else { 126 | prev->next = curr; 127 | prev = prev->next; 128 | } 129 | } 130 | fclose(f_in); 131 | return head; 132 | } 133 | 134 | int 135 | main(int argc, char **argv) 136 | { 137 | unsigned i, j; 138 | unsigned long addr1, addr2; 139 | unsigned long temp = -INIT_BIT; 140 | printf( 141 | "Select rowhammer approach\n" 142 | "1.DC CVAC + STR(default)\n" 143 | "2.DC CIVAC + STR\n" 144 | "3.DC CIVAC + LDR\n" 145 | "4.DC ZVA\n" 146 | "5.DC CVAC + STR + DSB\n" 147 | "6.DC CIVAC + STR + DSB\n" 148 | "7.DC CIVAC + LDR + DSB\n" 149 | "8.DC ZVA + DSB\n" 150 | ); 151 | int mode = getchar() - '0'; 152 | mode = mode > 0 && mode <= 8 ? mode : 1; 153 | printf("mode %d is selected\n", mode); 154 | 155 | #if INIT_BIT 156 | FILE *fp = fopen("results_1_to_0", "w"); 157 | #else 158 | FILE *fp = fopen("results_0_to_1", "w"); 159 | #endif 160 | 161 | char path[200]; 162 | sprintf(path, "/proc/%u/pagemap", getpid()); 163 | int pgmp = open(path, O_RDONLY); 164 | // initialize chunk 165 | for (i = 0; i < CHUNK_SIZE / VAL_SIZE; ++i) 166 | chunk[i] = -INIT_BIT; 167 | // generate pa-va mapping 168 | generate_va_table(pgmp); 169 | 170 | // addresses of attacker rows and victim rows 171 | unsigned long attk_pa1, attk_pa2, attk_pfn1, attk_pfn2; 172 | unsigned long vctm_pa, vctm_off, vctm_pfn, *vctm_va; 173 | 174 | 175 | #if USE_INPUT 176 | struct attkr_t *head, *curr; 177 | head = generate_addr_list(INPUT_FILE); 178 | #else 179 | candidate_t *head, *curr; 180 | unsigned long bgn, end; 181 | bgn = (unsigned long) chunk; 182 | end = bgn + CHUNK_SIZE; 183 | // hammer all possible attaker rows found 184 | head = find_candidates(bgn, end, 12, 16); 185 | #endif 186 | 187 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 188 | // get physical and virtual address for attacker rows 189 | attk_pa1 = curr->pa1; 190 | attk_pa2 = curr->pa2; 191 | attk_pfn1 = attk_pa1 / PAGE_SIZE; 192 | attk_pfn2 = attk_pa2 / PAGE_SIZE; 193 | addr1 = curr->va1; 194 | addr2 = curr->va2; 195 | 196 | 197 | switch (mode) { 198 | case 1: 199 | // hammer using DC CVAC + STR without DSB 200 | for (j = 0; j < HAMMER_ROUND; ++j) { 201 | asm volatile( 202 | "str %2, [%0]\n\t" 203 | "str %2, [%1]\n\t" 204 | "dc cvac, %0\n\t" 205 | "dc cvac, %1\n\t" 206 | //"dsb 0xb" 207 | ::"r" (addr1), "r" (addr2), "r" (temp) 208 | ); 209 | } 210 | break; 211 | case 2: 212 | // hammer using DC CIVAC + STR without DSB 213 | for (j = 0; j < HAMMER_ROUND; ++j) { 214 | asm volatile( 215 | "str %2, [%0]\n\t" 216 | "str %2, [%1]\n\t" 217 | "dc civac, %0\n\t" 218 | "dc civac, %1\n\t" 219 | //"dsb 0xb" 220 | ::"r" (addr1), "r" (addr2), "r" (temp) 221 | ); 222 | } 223 | break; 224 | case 3: 225 | // hammer using DC CIVAC + LDR without DSB 226 | for (j = 0; j < HAMMER_ROUND; ++j) { 227 | asm volatile( 228 | "ldr %2, [%0]\n\t" 229 | "ldr %2, [%1]\n\t" 230 | "dc civac, %0\n\t" 231 | "dc civac, %1\n\t" 232 | //"dsb 0xb" 233 | ::"r" (addr1), "r" (addr2), "r" (temp) 234 | ); 235 | } 236 | break; 237 | case 4: 238 | // hammer using DC ZVA without DSB 239 | asm volatile( 240 | "dc civac, %0\n\t" 241 | "dc civac, %1\n\t" 242 | ::"r" (addr1), "r" (addr2) 243 | ); 244 | for (j = 0; j < HAMMER_ROUND; ++j) { 245 | asm volatile( 246 | "dc zva, %0\n\t" 247 | "dc zva, %1\n\t" 248 | //"dsb 0xb" 249 | ::"r" (addr1), "r" (addr2) 250 | ); 251 | } 252 | break; 253 | case 5: 254 | // hammer using DC CVAC + STR with DSB 255 | for (j = 0; j < HAMMER_ROUND; ++j) { 256 | asm volatile( 257 | "str %2, [%0]\n\t" 258 | "str %2, [%1]\n\t" 259 | "dc cvac, %0\n\t" 260 | "dc cvac, %1\n\t" 261 | "dsb 0xb" 262 | ::"r" (addr1), "r" (addr2), "r" (temp) 263 | ); 264 | } 265 | break; 266 | case 6: 267 | // hammer using DC CIVAC + STR with DSB 268 | for (j = 0; j < HAMMER_ROUND; ++j) { 269 | asm volatile( 270 | "str %2, [%0]\n\t" 271 | "str %2, [%1]\n\t" 272 | "dc civac, %0\n\t" 273 | "dc civac, %1\n\t" 274 | "dsb 0xb" 275 | ::"r" (addr1), "r" (addr2), "r" (temp) 276 | ); 277 | } 278 | break; 279 | case 7: 280 | // hammer using DC CIVAC + LDR with DSB 281 | for (j = 0; j < HAMMER_ROUND; ++j) { 282 | asm volatile( 283 | "ldr %2, [%0]\n\t" 284 | "ldr %2, [%1]\n\t" 285 | "dc civac, %0\n\t" 286 | "dc civac, %1\n\t" 287 | "dsb 0xb" 288 | ::"r" (addr1), "r" (addr2), "r" (temp) 289 | ); 290 | } 291 | break; 292 | case 8: 293 | // hammer using DC ZVA with DSB 294 | asm volatile( 295 | "dc civac, %0\n\t" 296 | "dc civac, %1\n\t" 297 | ::"r" (addr1), "r" (addr2) 298 | ); 299 | for (j = 0; j < HAMMER_ROUND; ++j) { 300 | asm volatile( 301 | "dc zva, %0\n\t" 302 | "dc zva, %1\n\t" 303 | "dsb 0xb" 304 | ::"r" (addr1), "r" (addr2) 305 | ); 306 | } 307 | break; 308 | } 309 | 310 | // check victim row for bit flips 311 | for (j = 0; j < (1 << 15); j += VAL_SIZE) { 312 | vctm_pa = (attk_pfn1 + attk_pfn2) / 2 * PAGE_SIZE + j; 313 | vctm_off = vctm_pa % PAGE_SIZE; 314 | vctm_pfn = vctm_pa / PAGE_SIZE; 315 | // if victim row is not present 316 | if (va_tab[vctm_pfn] == 0) 317 | continue; 318 | // get virtual address of victim address 319 | vctm_va = (unsigned long *)(va_tab[vctm_pfn] + vctm_off); 320 | unsigned long val = *vctm_va; 321 | // output results if any bit flips occur 322 | if (val != -INIT_BIT) { 323 | cnt++; 324 | printf("attacker1:%lx\tattacker2:%lx\n", attk_pa1, attk_pa2); 325 | printf("cnt:%u victim:%lx becomes %lx\n", cnt, vctm_pa, val); 326 | fprintf(fp,"%8lx %8lx\t%u\n", attk_pa1, attk_pa2, INIT_BIT); 327 | } 328 | // reset values in victim rows 329 | *vctm_va = -INIT_BIT; 330 | } 331 | // display result every OUT_INTERVAL rounds 332 | if (i % OUT_INTERVAL == 0 ) 333 | printf("round:%u\tcount:%u\n\n", i, cnt); 334 | } 335 | fclose(fp); 336 | close(pgmp); 337 | } 338 | 339 | -------------------------------------------------------------------------------- /3_rowhammer_test/input/input0: -------------------------------------------------------------------------------- 1 | 6dc23000 6dc33000 2 | 6a233000 6a223000 3 | 7372a000 7373a000 4 | 73702000 73712000 5 | 735af000 735bf000 6 | 73569000 73579000 7 | 734c9000 734d9000 8 | 734a8000 734b8000 9 | 734a5000 734b5000 10 | 734a3000 734b3000 11 | 73b4c000 73b5c000 12 | 73b05000 73b15000 13 | 73aa4000 73ab4000 14 | 73a4c000 73a5c000 15 | 73a4b000 73a5b000 16 | 73a4b000 73a5b000 17 | 73a48000 73a58000 18 | 73a20000 73a30000 19 | 73984000 73994000 20 | 73982000 73992000 21 | 73946000 73956000 22 | 73927000 73937000 23 | 7382e000 7383e000 24 | 73fcb000 73fdb000 25 | 73eee000 73efe000 26 | 73ecf000 73edf000 27 | 73ea3000 73eb3000 28 | 73e6b000 73e7b000 29 | 73ded000 73dfd000 30 | 73dcb000 73ddb000 31 | 73da0000 73db0000 32 | 73d84000 73d94000 33 | 73d27000 73d37000 34 | 73cc5000 73cd5000 35 | 73c0d000 73c1d000 36 | 73c0d000 73c1d000 37 | 743ca000 743da000 38 | 7438e000 7439e000 39 | 7436d000 7437d000 40 | 742e2000 742f2000 41 | 742ab000 742bb000 42 | 741ed000 741fd000 43 | 746e2000 746f2000 44 | 746c0000 746d0000 45 | 74682000 74692000 46 | 74626000 74636000 47 | 745ca000 745da000 48 | 7456c000 7457c000 49 | 74543000 74553000 50 | 744c2000 744d2000 51 | 74468000 74478000 52 | 74428000 74438000 53 | 74bc7000 74bd7000 54 | 74b61000 74b71000 55 | 74a8f000 74a9f000 56 | 74a86000 74a96000 57 | 74a82000 74a92000 58 | 74a6c000 74a7c000 59 | 74969000 74979000 60 | 74960000 74970000 61 | 7492e000 7493e000 62 | 748e9000 748f9000 63 | 7486c000 7487c000 64 | 74ea0000 74eb0000 65 | 74d6c000 74d7c000 66 | 74d47000 74d57000 67 | 74d46000 74d56000 68 | 74d03000 74d13000 69 | 74d00000 74d10000 70 | 74ce5000 74cf5000 71 | 74cab000 74cbb000 72 | 74c88000 74c98000 73 | 74c27000 74c37000 74 | 753c9000 753d9000 75 | 75324000 75334000 76 | 75249000 75259000 77 | 75248000 75258000 78 | 7520f000 7521f000 79 | 75200000 75210000 80 | 751e7000 751f7000 81 | 75124000 75134000 82 | 75103000 75113000 83 | 750e7000 750f7000 84 | 750c3000 750d3000 85 | 75049000 75059000 86 | 75004000 75014000 87 | 75641000 75651000 88 | 75588000 75598000 89 | 75583000 75593000 90 | 7556a000 7557a000 91 | 75502000 75512000 92 | 75485000 75495000 93 | 75424000 75434000 94 | 75420000 75430000 95 | 75bc0000 75bd0000 96 | 75b42000 75b52000 97 | 75a62000 75a72000 98 | 75a05000 75a15000 99 | 759ca000 759da000 100 | 75949000 75959000 101 | 7592d000 7593d000 102 | 75e2d000 75e3d000 103 | 75dc6000 75dd6000 104 | 75d62000 75d72000 105 | 75cc8000 75cd8000 106 | 75cc5000 75cd5000 107 | 763e8000 763f8000 108 | 7636c000 7637c000 109 | 761a0000 761b0000 110 | 7618d000 7619d000 111 | 7618a000 7619a000 112 | 76160000 76170000 113 | 76120000 76130000 114 | 760ef000 760ff000 115 | 760c9000 760d9000 116 | 76045000 76055000 117 | 7600e000 7601e000 118 | 766ae000 766be000 119 | 76beb000 76bfb000 120 | 76ae6000 76af6000 121 | 76806000 76816000 122 | 76f26000 76f36000 123 | 76e6b000 76e7b000 124 | 76e0b000 76e1b000 125 | 76deb000 76dfb000 126 | 76d4d000 76d5d000 127 | 76d0e000 76d1e000 128 | 76c85000 76c95000 129 | 771ea000 771fa000 130 | 771ae000 771be000 131 | 7716c000 7717c000 132 | 7714f000 7715f000 133 | 77106000 77116000 134 | 770e1000 770f1000 135 | 770ca000 770da000 136 | 770a3000 770b3000 137 | 7702c000 7703c000 138 | 777ef000 777ff000 139 | 777ee000 777fe000 140 | 777e1000 777f1000 141 | 77640000 77650000 142 | 7756d000 7757d000 143 | 77488000 77498000 144 | 77be3000 77bf3000 145 | 77be1000 77bf1000 146 | 77ae3000 77af3000 147 | 77aaf000 77abf000 148 | 77a65000 77a75000 149 | 77a48000 77a58000 150 | 779ec000 779fc000 151 | 779ea000 779fa000 152 | 7798e000 7799e000 153 | 7798e000 7799e000 154 | 77963000 77973000 155 | 7794b000 7795b000 156 | 7786b000 7787b000 157 | 77861000 77871000 158 | 7784a000 7785a000 159 | 77845000 77855000 160 | 77f89000 77f99000 161 | 77f81000 77f91000 162 | 77f68000 77f78000 163 | 77f65000 77f75000 164 | 77eeb000 77efb000 165 | 77ea9000 77eb9000 166 | 77ea2000 77eb2000 167 | 77e02000 77e12000 168 | 77de4000 77df4000 169 | 77dc3000 77dd3000 170 | -------------------------------------------------------------------------------- /4_experiments/bitflip_iteration/Makefile: -------------------------------------------------------------------------------- 1 | all : 2 | gcc bitflip_iteration.c -lrowhammer -pthread 3 | 4 | run : 5 | sudo ./a.out 6 | clean : 7 | rm ./a.out 8 | -------------------------------------------------------------------------------- /4_experiments/bitflip_iteration/bitflip_iteration.c: -------------------------------------------------------------------------------- 1 | /** 2 | * bitflip_iteration -- find relationship between #bitflip and #iteration 3 | * By VandySec Group 4 | **/ 5 | #define _GNU_SOURCE 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define CHUNK_SIZE 0x40000000 19 | #define VPN_SIZE 0x80000 20 | #define PAGE_SIZE 4096 21 | #define ROW_SIZE 8192 22 | #define VAL_SIZE sizeof(unsigned long) 23 | #define HAMMER_ROUND 5000000 24 | 25 | #define INPUT_FILE "input/flippable_all" 26 | #define OUT_INTERVAL 10 27 | 28 | struct attkr_t{ 29 | unsigned long pa1; 30 | unsigned long pa2; 31 | unsigned long va1; 32 | unsigned long va2; 33 | unsigned long vctm_base; 34 | unsigned long init_val; 35 | struct attkr_t *next; 36 | }; 37 | 38 | unsigned long chunk[CHUNK_SIZE / VAL_SIZE]; 39 | unsigned long va_tab[VPN_SIZE]; 40 | unsigned cnt = 0; 41 | unsigned long temp = -1; 42 | unsigned long samp_pts[] = {5000000, 4000000, 3000000, 2500000, 2000000, 43 | 1500000, 1000000, 900000, 800000, 700000, 600000, 500000, 400000, 300000, 44 | 200000, 100000, 80000, 70000, 60000, 50000, 45 | 40000, 30000, 20000, 10000, 5000, 1000}; 46 | unsigned long samp_len; 47 | 48 | void 49 | generate_va_table(int pgmp) 50 | { 51 | for (int i = 0; i < CHUNK_SIZE / VAL_SIZE; i += PAGE_SIZE / VAL_SIZE){ 52 | unsigned long data; 53 | unsigned long index = (unsigned long)&chunk[i] / PAGE_SIZE * sizeof(data); 54 | if (pread(pgmp, &data, sizeof(data), index) != sizeof(data)) { 55 | perror("pread"); 56 | break; 57 | } 58 | unsigned long pfn = data & 0x7fffffffffffff; 59 | if (pfn <= 0 || pfn > VPN_SIZE){ 60 | perror("VPN_TABLE TOO SMALL"); 61 | break; 62 | } else 63 | va_tab[pfn] = index / sizeof(data) * PAGE_SIZE; 64 | } 65 | } 66 | 67 | unsigned long * 68 | pa_to_va(unsigned long pa) 69 | { 70 | unsigned long va_off = pa % PAGE_SIZE; 71 | unsigned long va_pfn = pa / PAGE_SIZE; 72 | if (va_tab[va_pfn] == 0) 73 | return 0; 74 | else 75 | return (unsigned long *)(va_tab[va_pfn] + va_off); 76 | } 77 | 78 | struct attkr_t * 79 | generate_addr_list(char *fname) 80 | { 81 | FILE *f_in = fopen(fname, "r"); 82 | char str[999]; 83 | unsigned long attk_pa1, attk_pa2, attk_pfn1, attk_pfn2, init_val; 84 | struct attkr_t *head, *curr, *prev; 85 | head = NULL; 86 | curr = head; 87 | while (fscanf(f_in, "%s", str) != EOF){ 88 | attk_pa1 = (unsigned long)strtol(str, NULL, 16); 89 | fscanf(f_in, "%s", str); 90 | attk_pa2 = (unsigned long)strtol(str, NULL, 16); 91 | fscanf(f_in, "%s", str); 92 | init_val = (unsigned long)(-strtol(str, NULL, 10)); 93 | attk_pfn1 = attk_pa1 / PAGE_SIZE; 94 | attk_pfn2 = attk_pa2 / PAGE_SIZE; 95 | 96 | curr = (struct attkr_t *)malloc(sizeof(struct attkr_t)); 97 | curr->pa1 = attk_pa1; 98 | curr->pa2 = attk_pa2; 99 | curr->va1 = (unsigned long)pa_to_va(attk_pa1); 100 | curr->va2 = (unsigned long)pa_to_va(attk_pa2); 101 | curr->vctm_base = (attk_pfn1 + attk_pfn2) / 2 * PAGE_SIZE; 102 | curr->init_val = init_val; 103 | curr->next = NULL; 104 | 105 | if (curr->va1 == 0 || curr->va2 == 0){ 106 | free(curr); 107 | continue; 108 | } else if (head == NULL){ 109 | head = curr; 110 | prev = head; 111 | } else { 112 | prev->next = curr; 113 | prev = prev->next; 114 | } 115 | } 116 | fclose(f_in); 117 | return head; 118 | } 119 | 120 | int 121 | main(int argc, char **argv) 122 | { 123 | unsigned i, j, k; 124 | unsigned long addr1, addr2; 125 | FILE *fp, *fcnt; 126 | char path[200]; 127 | sprintf(path, "/proc/%u/pagemap", getpid()); 128 | int pgmp = open(path, O_RDONLY); 129 | unsigned long vctm_pa, *vctm_va, val; 130 | char str[999]; 131 | struct attkr_t *head, *curr; 132 | unsigned long prev_init = -1; 133 | 134 | // initialize chunk 135 | for (i = 0; i < CHUNK_SIZE / VAL_SIZE; ++i) 136 | chunk[i] = -1; 137 | // generate pa-va mapping 138 | generate_va_table(pgmp); 139 | head = generate_addr_list(INPUT_FILE); 140 | 141 | unsigned long h_rnd; 142 | samp_len = sizeof(samp_pts) / sizeof(unsigned long); 143 | 144 | // START 145 | fp = fopen("results/addr_cvac_str.txt", "w"); 146 | fcnt = fopen("results/cnt_cvac_str.txt","w"); 147 | printf("civac_ldr\n"); 148 | for (k = 0; k < samp_len; k++){ 149 | h_rnd = samp_pts[k]; 150 | fprintf(fp,"rnd: %lu\n", h_rnd); 151 | fprintf(fcnt,"%lu\t", h_rnd); 152 | printf("round %lu\n", h_rnd); 153 | i = 0; 154 | cnt = 0; 155 | for(curr = head; curr != NULL; curr = curr->next){ 156 | addr1 = curr->va1; 157 | addr2 = curr->va2; 158 | if (addr1 == 0 || addr2 == 0) 159 | continue; 160 | i++; 161 | if (prev_init != curr->init_val){ 162 | printf("change check bit to %lx\n", curr->init_val); 163 | memset(chunk, curr->init_val, CHUNK_SIZE); 164 | prev_init = curr->init_val; 165 | } 166 | temp = curr->init_val; 167 | // DIFF 168 | for (int i = 0; i < h_rnd; ++i) { 169 | asm volatile( 170 | "str %2, [%0]\n\t" 171 | "str %2, [%1]\n\t" 172 | "dc cvac, %0\n\t" 173 | "dc cvac, %1\n\t" 174 | ::"r" (addr1), "r" (addr2), "r" (temp) 175 | ); 176 | } 177 | // DIFF 178 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 179 | // check victim row only 180 | vctm_pa = curr->vctm_base + j; vctm_va = pa_to_va(vctm_pa); 181 | if (vctm_va == 0) 182 | continue; 183 | val = *vctm_va; 184 | if (val != curr->init_val) { 185 | cnt++; 186 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 187 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 188 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 189 | } 190 | *vctm_va = curr->init_val; 191 | } 192 | if (i % OUT_INTERVAL == 0 ) 193 | printf("round:%u\tcount:%u\n\n", i, cnt); 194 | } 195 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 196 | } 197 | fclose(fp); 198 | fclose(fcnt); 199 | // END 200 | 201 | // START 202 | fp = fopen("results/addr_zva.txt", "w"); 203 | fcnt = fopen("results/cnt_zva.txt","w"); 204 | printf("zva\n"); 205 | for (k = 0; k < samp_len; k++){ 206 | h_rnd = samp_pts[k]; 207 | fprintf(fp,"rnd: %lu\n", h_rnd); 208 | fprintf(fcnt,"%lu\t", h_rnd); 209 | printf("round %lu\n", h_rnd); 210 | i = 0; 211 | cnt = 0; 212 | for(curr = head; curr != NULL; curr = curr->next){ 213 | addr1 = curr->va1; 214 | addr2 = curr->va2; 215 | if (addr1 == 0 || addr2 == 0) 216 | continue; 217 | i++; 218 | if (prev_init != curr->init_val){ 219 | printf("change check bit to %lx\n", curr->init_val); 220 | memset(chunk, curr->init_val, CHUNK_SIZE); 221 | prev_init = curr->init_val; 222 | } 223 | temp = curr->init_val; 224 | // DIFF 225 | asm volatile( 226 | "dc civac, %0\n\t" 227 | "dc civac, %1\n\t" 228 | ::"r" (addr1), "r" (addr2) 229 | ); 230 | for (int i = 0; i < h_rnd; ++i) { 231 | asm volatile( 232 | "dc zva, %0\n\t" 233 | "dc zva, %1\n\t" 234 | ::"r" (addr1), "r" (addr2) 235 | ); 236 | } 237 | // DIFF 238 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 239 | // check victim row only 240 | vctm_pa = curr->vctm_base + j; vctm_va = pa_to_va(vctm_pa); 241 | if (vctm_va == 0) 242 | continue; 243 | val = *vctm_va; 244 | if (val != curr->init_val) { 245 | cnt++; 246 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 247 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 248 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 249 | } 250 | *vctm_va = curr->init_val; 251 | } 252 | if (i % OUT_INTERVAL == 0 ) 253 | printf("round:%u\tcount:%u\n\n", i, cnt); 254 | } 255 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 256 | } 257 | fclose(fp); 258 | fclose(fcnt); 259 | // END 260 | 261 | // START 262 | fp = fopen("results/addr_civac_ldr.txt", "w"); 263 | fcnt = fopen("results/cnt_civac_ldr.txt","w"); 264 | printf("civac_ldr\n"); 265 | for (k = 0; k < samp_len; k++){ 266 | h_rnd = samp_pts[k]; 267 | fprintf(fp,"rnd: %lu\n", h_rnd); 268 | fprintf(fcnt,"%lu\t", h_rnd); 269 | printf("round %lu\n", h_rnd); 270 | i = 0; 271 | cnt = 0; 272 | for(curr = head; curr != NULL; curr = curr->next) { 273 | addr1 = curr->va1; 274 | addr2 = curr->va2; 275 | if (addr1 == 0 || addr2 == 0) 276 | continue; 277 | i++; 278 | if (prev_init != curr->init_val) { 279 | printf("change check bit to %lx\n", curr->init_val); 280 | memset(chunk, curr->init_val, CHUNK_SIZE); 281 | prev_init = curr->init_val; 282 | } 283 | temp = curr->init_val; 284 | // DIFF 285 | for (int i = 0; i < h_rnd; ++i) { 286 | asm volatile( 287 | "ldr %2, [%0]\n\t" 288 | "ldr %2, [%1]\n\t" 289 | "dc civac, %0\n\t" 290 | "dc civac, %1\n\t" 291 | ::"r" (addr1), "r" (addr2), "r" (temp) 292 | ); 293 | } 294 | // DIFF 295 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 296 | // check victim row only 297 | vctm_pa = curr->vctm_base + j; vctm_va = pa_to_va(vctm_pa); 298 | if (vctm_va == 0) 299 | continue; 300 | val = *vctm_va; 301 | if (val != curr->init_val) { 302 | cnt++; 303 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 304 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 305 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 306 | } 307 | *vctm_va = curr->init_val; 308 | } 309 | if (i % OUT_INTERVAL == 0 ) 310 | printf("round:%u\tcount:%u\n\n", i, cnt); 311 | } 312 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 313 | } 314 | fclose(fp); 315 | fclose(fcnt); 316 | // END 317 | 318 | // START 319 | fp = fopen("results/addr_civac_str.txt", "w"); 320 | fcnt = fopen("results/cnt_civac_str.txt","w"); 321 | printf("civac_ldr\n"); 322 | for (k = 0; k < samp_len; k++){ 323 | h_rnd = samp_pts[k]; 324 | fprintf(fp,"rnd: %lu\n", h_rnd); 325 | fprintf(fcnt,"%lu\t", h_rnd); 326 | printf("round %lu\n", h_rnd); 327 | i = 0; 328 | cnt = 0; 329 | for(curr = head; curr != NULL; curr = curr->next){ 330 | addr1 = curr->va1; 331 | addr2 = curr->va2; 332 | if (addr1 == 0 || addr2 == 0) 333 | continue; 334 | i++; 335 | if (prev_init != curr->init_val){ 336 | printf("change check bit to %lx\n", curr->init_val); 337 | memset(chunk, curr->init_val, CHUNK_SIZE); 338 | prev_init = curr->init_val; 339 | } 340 | temp = curr->init_val; 341 | // DIFF 342 | for (int i = 0; i < h_rnd; ++i) { 343 | asm volatile( 344 | "str %2, [%0]\n\t" 345 | "str %2, [%1]\n\t" 346 | "dc civac, %0\n\t" 347 | "dc civac, %1\n\t" 348 | ::"r" (addr1), "r" (addr2), "r" (temp) 349 | ); 350 | } 351 | // DIFF 352 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 353 | // check victim row only 354 | vctm_pa = curr->vctm_base + j; vctm_va = pa_to_va(vctm_pa); 355 | if (vctm_va == 0) 356 | continue; 357 | val = *vctm_va; 358 | if (val != curr->init_val) { 359 | cnt++; 360 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 361 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 362 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 363 | } 364 | *vctm_va = curr->init_val; 365 | } 366 | if (i % OUT_INTERVAL == 0 ) 367 | printf("round:%u\tcount:%u\n\n", i, cnt); 368 | } 369 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 370 | } 371 | fclose(fp); 372 | fclose(fcnt); 373 | // END 374 | 375 | close(pgmp); 376 | } 377 | 378 | -------------------------------------------------------------------------------- /4_experiments/bitflip_iteration/input/flippable_all: -------------------------------------------------------------------------------- 1 | 2582000 2592000 0 2 | 2a63000 2a73000 0 3 | 3ec5000 3ed5000 0 4 | 3f69000 3f79000 0 5 | 478d000 479d000 0 6 | 486b000 487b000 0 7 | 5783000 5793000 0 8 | 5c22000 5c32000 0 9 | 6040000 6050000 0 10 | 6140000 6150000 0 11 | 6ac3000 6ad3000 0 12 | 9468000 9478000 0 13 | aa07000 aa17000 0 14 | b349000 b359000 0 15 | dc8e000 dc9e000 0 16 | 10908000 10918000 0 17 | 10924000 10934000 0 18 | 10ae6000 10af6000 0 19 | 11bcb000 11bdb000 0 20 | 120aa000 120ba000 0 21 | 12464000 12474000 0 22 | 12a61000 12a71000 0 23 | 12d06000 12d16000 0 24 | 134ec000 134fc000 0 25 | 13aa0000 13ab0000 0 26 | 146ef000 146ff000 0 27 | 14fec000 14ffc000 0 28 | 1542c000 1543c000 0 29 | 154c8000 154d8000 0 30 | 15fcd000 15fdd000 0 31 | 16540000 16550000 0 32 | 16724000 16734000 0 33 | 1808f000 1809f000 0 34 | 18d20000 18d30000 0 35 | 1e18b000 1e19b000 0 36 | 1e228000 1e238000 0 37 | 1e604000 1e614000 0 38 | 1eea2000 1eeb2000 0 39 | 1f6a7000 1f6b7000 0 40 | 2014d000 2015d000 0 41 | 21c06000 21c16000 0 42 | 2220c000 2221c000 0 43 | 22e42000 22e52000 0 44 | 23ee3000 23ef3000 0 45 | 24dc0000 24dd0000 0 46 | 24fe3000 24ff3000 0 47 | 25240000 25250000 0 48 | 26340000 26350000 0 49 | 26388000 26398000 0 50 | 275a3000 275b3000 0 51 | 275c5000 275d5000 0 52 | 28f43000 28f53000 0 53 | 29aae000 29abe000 0 54 | 2d306000 2d316000 0 55 | 2da6f000 2da7f000 0 56 | 2dbc0000 2dbd0000 0 57 | 2e4c5000 2e4d5000 0 58 | 309c3000 309d3000 0 59 | 32243000 32253000 0 60 | 32343000 32353000 0 61 | 7326b000 7327b000 0 62 | 2a64000 2a74000 1 63 | 2a8b000 2a9b000 1 64 | 376f000 377f000 1 65 | 3ac0000 3ad0000 1 66 | 44ae000 44be000 1 67 | 44c9000 44d9000 1 68 | 478e000 479e000 1 69 | 4ae9000 4af9000 1 70 | 5968000 5978000 1 71 | 686b000 687b000 1 72 | 6b84000 6b94000 1 73 | 7b21000 7b31000 1 74 | 850c000 851c000 1 75 | 88c7000 88d7000 1 76 | 8e49000 8e59000 1 77 | 8f42000 8f52000 1 78 | 922e000 923e000 1 79 | 94c9000 94d9000 1 80 | 97a0000 97b0000 1 81 | 9908000 9918000 1 82 | a38b000 a39b000 1 83 | b0ec000 b0fc000 1 84 | b145000 b155000 1 85 | cae3000 caf3000 1 86 | d609000 d619000 1 87 | d806000 d816000 1 88 | 1056f000 1057f000 1 89 | 10b29000 10b39000 1 90 | 1168c000 1169c000 1 91 | 12742000 12752000 1 92 | 13162000 13172000 1 93 | 1438e000 1439e000 1 94 | 14b42000 14b52000 1 95 | 14e04000 14e14000 1 96 | 16da1000 16db1000 1 97 | 1718d000 1719d000 1 98 | 17964000 17974000 1 99 | 19064000 19074000 1 100 | 1958f000 1959f000 1 101 | 1aeeb000 1aefb000 1 102 | 1b22e000 1b23e000 1 103 | 1b34b000 1b35b000 1 104 | 1bbec000 1bbfc000 1 105 | 1c1a3000 1c1b3000 1 106 | 1d823000 1d833000 1 107 | 1d8ad000 1d8bd000 1 108 | 1e68f000 1e69f000 1 109 | 1f168000 1f178000 1 110 | 1ffa7000 1ffb7000 1 111 | 200c4000 200d4000 1 112 | 21244000 21254000 1 113 | 21b04000 21b14000 1 114 | 22307000 22317000 1 115 | 22469000 22479000 1 116 | 22922000 22932000 1 117 | 22c88000 22c98000 1 118 | 22dab000 22dbb000 1 119 | 22dca000 22dda000 1 120 | 255a4000 255b4000 1 121 | 255c2000 255d2000 1 122 | 25760000 25770000 1 123 | 25960000 25970000 1 124 | 27f84000 27f94000 1 125 | 28aa2000 28ab2000 1 126 | 29e64000 29e74000 1 127 | 29fa2000 29fb2000 1 128 | 2a20f000 2a21f000 1 129 | 2ac80000 2ac90000 1 130 | 2ccaa000 2ccba000 1 131 | 30c0c000 30c1c000 1 132 | 31aeb000 31afb000 1 133 | 32ce3000 32cf3000 1 134 | 79d07000 79d17000 1 135 | 7a780000 7a790000 1 136 | 7c408000 7c418000 1 137 | 138 | -------------------------------------------------------------------------------- /4_experiments/bitflip_iteration/input/input0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x5ec1ab/rowhammer_armv8/8e60cf3091798da8990e131574dac940415848fc/4_experiments/bitflip_iteration/input/input0 -------------------------------------------------------------------------------- /4_experiments/compare_all_instr/Makefile: -------------------------------------------------------------------------------- 1 | all : 2 | gcc compare_instr.c -lrowhammer -pthread 3 | 4 | run : 5 | sudo ./a.out 6 | clean : 7 | rm ./a.out 8 | -------------------------------------------------------------------------------- /4_experiments/compare_all_instr/compare_instr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * compare_all_instr -- compare effectiveness of different approaches 3 | * By VandySec Group 4 | **/ 5 | #define _GNU_SOURCE 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define CHUNK_SIZE 0x40000000 19 | #define VPN_SIZE 0x80000 20 | #define PAGE_SIZE 4096 21 | #define ROW_SIZE 8192 22 | #define VAL_SIZE sizeof(unsigned long) 23 | #define HAMMER_ROUND 5000000 24 | 25 | #define INPUT_FILE "input/flippable_all" 26 | #define OUT_INTERVAL 200 27 | 28 | struct attkr_t{ 29 | unsigned long pa1; 30 | unsigned long pa2; 31 | unsigned long va1; 32 | unsigned long va2; 33 | unsigned long vctm_base; 34 | unsigned long init_val; 35 | struct attkr_t *next; 36 | }; 37 | 38 | unsigned long chunk[CHUNK_SIZE / VAL_SIZE]; 39 | unsigned long va_tab[VPN_SIZE]; 40 | unsigned cnt = 0; 41 | 42 | void 43 | generate_va_table(int pgmp) 44 | { 45 | for (int i = 0; i < CHUNK_SIZE / VAL_SIZE; i += PAGE_SIZE / VAL_SIZE){ 46 | unsigned long data; 47 | unsigned long index = (unsigned long)&chunk[i] / PAGE_SIZE * sizeof(data); 48 | if (pread(pgmp, &data, sizeof(data), index) != sizeof(data)) { 49 | perror("pread"); 50 | break; 51 | } 52 | unsigned long pfn = data & 0x7fffffffffffff; 53 | if (pfn <= 0 || pfn > VPN_SIZE){ 54 | perror("VPN_TABLE TOO SMALL"); 55 | break; 56 | } else 57 | va_tab[pfn] = index / sizeof(data) * PAGE_SIZE; 58 | } 59 | } 60 | 61 | unsigned long * 62 | pa_to_va(unsigned long pa) 63 | { 64 | unsigned long va_off = pa % PAGE_SIZE; 65 | unsigned long va_pfn = pa / PAGE_SIZE; 66 | if (va_tab[va_pfn] == 0) 67 | return 0; 68 | else 69 | return (unsigned long *)(va_tab[va_pfn] + va_off); 70 | } 71 | 72 | struct attkr_t * 73 | generate_addr_list(char *fname) 74 | { 75 | FILE *f_in = fopen(fname, "r"); 76 | char str[999]; 77 | unsigned long attk_pa1, attk_pa2, attk_pfn1, attk_pfn2, init_val; 78 | struct attkr_t *head, *curr, *prev; 79 | head = NULL; 80 | curr = head; 81 | while (fscanf(f_in, "%s", str) != EOF){ 82 | attk_pa1 = (unsigned long)strtol(str, NULL, 16); 83 | fscanf(f_in, "%s", str); 84 | attk_pa2 = (unsigned long)strtol(str, NULL, 16); 85 | fscanf(f_in, "%s", str); 86 | init_val = (unsigned long)(-strtol(str, NULL, 10)); 87 | attk_pfn1 = attk_pa1 / PAGE_SIZE; 88 | attk_pfn2 = attk_pa2 / PAGE_SIZE; 89 | 90 | curr = (struct attkr_t *)malloc(sizeof(struct attkr_t)); 91 | curr->pa1 = attk_pa1; 92 | curr->pa2 = attk_pa2; 93 | curr->va1 = (unsigned long)pa_to_va(attk_pa1); 94 | curr->va2 = (unsigned long)pa_to_va(attk_pa2); 95 | curr->vctm_base = (attk_pfn1 + attk_pfn2) / 2 * PAGE_SIZE; 96 | curr->init_val = init_val; 97 | curr->next = NULL; 98 | 99 | if (curr->va1 == 0 || curr->va2 == 0){ 100 | free(curr); 101 | continue; 102 | } else if (head == NULL){ 103 | head = curr; 104 | prev = head; 105 | } else { 106 | prev->next = curr; 107 | prev = prev->next; 108 | } 109 | } 110 | fclose(f_in); 111 | return head; 112 | } 113 | 114 | int 115 | main(int argc, char **argv) 116 | { 117 | unsigned i, j; 118 | unsigned long addr1, addr2; 119 | unsigned long temp = -1; 120 | FILE *fp, *fcnt; 121 | char path[200]; 122 | sprintf(path, "/proc/%u/pagemap", getpid()); 123 | int pgmp = open(path, O_RDONLY); 124 | unsigned long vctm_pa, *vctm_va, val; 125 | char str[999]; 126 | struct attkr_t *head, *curr; 127 | // initialize chunk 128 | for (i = 0; i < CHUNK_SIZE / VAL_SIZE; ++i) 129 | chunk[i] = -1; 130 | // generate pa-va mapping 131 | generate_va_table(pgmp); 132 | head = generate_addr_list(INPUT_FILE); 133 | 134 | // START CIVAC + STR without DSB 135 | fp = fopen("results/addr_civac_ldr_wo.txt", "w"); 136 | fcnt = fopen("results/cnt_civac_ldr_wo.txt","w"); 137 | printf("civac_ldr_wo\n"); 138 | i = 0; 139 | cnt = 0; 140 | for(curr = head; curr != NULL; curr = curr->next){ 141 | addr1 = curr->va1; 142 | addr2 = curr->va2; 143 | if (addr1 == 0 || addr2 == 0) 144 | continue; 145 | i++; 146 | memset(chunk, curr->init_val, CHUNK_SIZE); 147 | temp = curr->init_val; 148 | // DIFFERENT INSTRUCTIONS 149 | for (j = 0; j < HAMMER_ROUND; ++j) { 150 | asm volatile( 151 | "ldr %2, [%0]\n\t" 152 | "ldr %2, [%1]\n\t" 153 | "dc civac, %0\n\t" 154 | "dc civac, %1\n\t" 155 | //"dsb 0xb" 156 | ::"r" (addr1), "r" (addr2), "r" (temp) 157 | ); 158 | } 159 | // DIFFERENT INSTRUCTIONS 160 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 161 | // check victim row only 162 | vctm_pa = curr->vctm_base + j; 163 | vctm_va = pa_to_va(vctm_pa); 164 | if (vctm_va == 0) 165 | continue; 166 | val = *vctm_va; 167 | if (val != curr->init_val) { 168 | cnt++; 169 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 170 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 171 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 172 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 173 | } 174 | *vctm_va = curr->init_val; 175 | } 176 | if (i % OUT_INTERVAL == 0 ) 177 | printf("round:%u\tcount:%u\n\n", i, cnt); 178 | } 179 | fclose(fp); 180 | fclose(fcnt); 181 | // END CIVAC + STR without DSB 182 | 183 | // repeat the previous operations with different instructions for the rest 184 | 185 | // START 186 | fp = fopen("results/addr_civac_ldr_w.txt", "w"); 187 | fcnt = fopen("results/cnt_civac_ldr_w.txt","w"); 188 | i = 0; 189 | cnt = 0; 190 | printf("civac_ldr_w\n"); 191 | for(curr = head; curr != NULL; curr = curr->next){ 192 | addr1 = curr->va1; 193 | addr2 = curr->va2; 194 | if (addr1 == 0 || addr2 == 0) 195 | continue; 196 | i++; 197 | memset(chunk, curr->init_val, CHUNK_SIZE); 198 | temp = curr->init_val; 199 | // DIFF 200 | for (j = 0; j < HAMMER_ROUND; ++j) { 201 | asm volatile( 202 | "ldr %2, [%0]\n\t" 203 | "ldr %2, [%1]\n\t" 204 | "dc civac, %0\n\t" 205 | "dc civac, %1\n\t" 206 | "dsb 0xb" 207 | ::"r" (addr1), "r" (addr2), "r" (temp) 208 | ); 209 | } 210 | // DIFF 211 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 212 | // check victim row only 213 | vctm_pa = curr->vctm_base + j; 214 | vctm_va = pa_to_va(vctm_pa); 215 | if (vctm_va == 0) 216 | continue; 217 | val = *vctm_va; 218 | if (val != curr->init_val) { 219 | cnt++; 220 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 221 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 222 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 223 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 224 | } 225 | *vctm_va = curr->init_val; 226 | } 227 | if (i % OUT_INTERVAL == 0 ) 228 | printf("round:%u\tcount:%u\n\n", i, cnt); 229 | } 230 | fclose(fp); 231 | fclose(fcnt); 232 | // END 233 | 234 | // START 235 | fp = fopen("results/addr_civac_str_wo.txt", "w"); 236 | fcnt = fopen("results/cnt_civac_str_wo.txt","w"); 237 | i = 0; 238 | cnt = 0; 239 | printf("civac_str_wo\n"); 240 | for(curr = head; curr != NULL; curr = curr->next){ 241 | addr1 = curr->va1; 242 | addr2 = curr->va2; 243 | if (addr1 == 0 || addr2 == 0) 244 | continue; 245 | i++; 246 | memset(chunk, curr->init_val, CHUNK_SIZE); 247 | temp = curr->init_val; 248 | // DIFF 249 | for (j = 0; j < HAMMER_ROUND; ++j) { 250 | asm volatile( 251 | "str %2, [%0]\n\t" 252 | "str %2, [%1]\n\t" 253 | "dc civac, %0\n\t" 254 | "dc civac, %1\n\t" 255 | //"dsb 0xb" 256 | ::"r" (addr1), "r" (addr2), "r" (temp) 257 | ); 258 | } 259 | // DIFF 260 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 261 | // check victim row only 262 | vctm_pa = curr->vctm_base + j; 263 | vctm_va = pa_to_va(vctm_pa); 264 | if (vctm_va == 0) 265 | continue; 266 | val = *vctm_va; 267 | if (val != curr->init_val) { 268 | cnt++; 269 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 270 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 271 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 272 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 273 | } 274 | *vctm_va = curr->init_val; 275 | } 276 | if (i % OUT_INTERVAL == 0 ) 277 | printf("round:%u\tcount:%u\n\n", i, cnt); 278 | } 279 | fclose(fp); 280 | fclose(fcnt); 281 | // END 282 | 283 | // START 284 | fp = fopen("results/addr_civac_str_w.txt", "w"); 285 | fcnt = fopen("results/cnt_civac_str_w.txt","w"); 286 | i = 0; 287 | cnt = 0; 288 | printf("civac_str_w\n"); 289 | for(curr = head; curr != NULL; curr = curr->next){ 290 | addr1 = curr->va1; 291 | addr2 = curr->va2; 292 | if (addr1 == 0 || addr2 == 0) 293 | continue; 294 | i++; 295 | memset(chunk, curr->init_val, CHUNK_SIZE); 296 | temp = curr->init_val; 297 | // DIFF 298 | for (j = 0; j < HAMMER_ROUND; ++j) { 299 | asm volatile( 300 | "str %2, [%0]\n\t" 301 | "str %2, [%1]\n\t" 302 | "dc civac, %0\n\t" 303 | "dc civac, %1\n\t" 304 | "dsb 0xb" 305 | ::"r" (addr1), "r" (addr2), "r" (temp) 306 | ); 307 | } 308 | // DIFF 309 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 310 | // check victim row only 311 | vctm_pa = curr->vctm_base + j; 312 | vctm_va = pa_to_va(vctm_pa); 313 | if (vctm_va == 0) 314 | continue; 315 | val = *vctm_va; 316 | if (val != curr->init_val) { 317 | cnt++; 318 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 319 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 320 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 321 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 322 | } 323 | *vctm_va = curr->init_val; 324 | } 325 | if (i % OUT_INTERVAL == 0 ) 326 | printf("round:%u\tcount:%u\n\n", i, cnt); 327 | } 328 | fclose(fp); 329 | fclose(fcnt); 330 | // END 331 | 332 | // START 333 | fp = fopen("results/addr_cvac_str_wo.txt", "w"); 334 | fcnt = fopen("results/cnt_cvac_str_wo.txt","w"); 335 | i = 0; 336 | cnt = 0; 337 | printf("cvac_str_wo\n"); 338 | for(curr = head; curr != NULL; curr = curr->next){ 339 | addr1 = curr->va1; 340 | addr2 = curr->va2; 341 | if (addr1 == 0 || addr2 == 0) 342 | continue; 343 | i++; 344 | memset(chunk, curr->init_val, CHUNK_SIZE); 345 | temp = curr->init_val; 346 | // DIFF 347 | for (j = 0; j < HAMMER_ROUND; ++j) { 348 | asm volatile( 349 | "str %2, [%0]\n\t" 350 | "str %2, [%1]\n\t" 351 | "dc cvac, %0\n\t" 352 | "dc cvac, %1\n\t" 353 | //"dsb 0xb" 354 | ::"r" (addr1), "r" (addr2), "r" (temp) 355 | ); 356 | } 357 | // DIFF 358 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 359 | // check victim row only 360 | vctm_pa = curr->vctm_base + j; 361 | vctm_va = pa_to_va(vctm_pa); 362 | if (vctm_va == 0) 363 | continue; 364 | val = *vctm_va; 365 | if (val != curr->init_val) { 366 | cnt++; 367 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 368 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 369 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 370 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 371 | } 372 | *vctm_va = curr->init_val; 373 | } 374 | if (i % OUT_INTERVAL == 0 ) 375 | printf("round:%u\tcount:%u\n\n", i, cnt); 376 | } 377 | fclose(fp); 378 | fclose(fcnt); 379 | // END 380 | 381 | // START 382 | fp = fopen("results/addr_cvac_str_w.txt", "w"); 383 | fcnt = fopen("results/cnt_cvac_str_w.txt","w"); 384 | i = 0; 385 | cnt = 0; 386 | printf("cvac_str_w\n"); 387 | for(curr = head; curr != NULL; curr = curr->next){ 388 | addr1 = curr->va1; 389 | addr2 = curr->va2; 390 | if (addr1 == 0 || addr2 == 0) 391 | continue; 392 | i++; 393 | memset(chunk, curr->init_val, CHUNK_SIZE); 394 | temp = curr->init_val; 395 | // DIFF 396 | for (j = 0; j < HAMMER_ROUND; ++j) { 397 | asm volatile( 398 | "str %2, [%0]\n\t" 399 | "str %2, [%1]\n\t" 400 | "dc cvac, %0\n\t" 401 | "dc cvac, %1\n\t" 402 | "dsb 0xb" 403 | ::"r" (addr1), "r" (addr2), "r" (temp) 404 | ); 405 | } 406 | // DIFF 407 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 408 | // check victim row only 409 | vctm_pa = curr->vctm_base + j; 410 | vctm_va = pa_to_va(vctm_pa); 411 | if (vctm_va == 0) 412 | continue; 413 | val = *vctm_va; 414 | if (val != curr->init_val) { 415 | cnt++; 416 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 417 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 418 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 419 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 420 | } 421 | *vctm_va = curr->init_val; 422 | } 423 | if (i % OUT_INTERVAL == 0 ) 424 | printf("round:%u\tcount:%u\n\n", i, cnt); 425 | } 426 | fclose(fp); 427 | fclose(fcnt); 428 | // END 429 | 430 | // START DC ZVA W/O DSB 431 | fp = fopen("results/addr_zva_wo.txt", "w"); 432 | fcnt = fopen("results/cnt_zva_wo.txt","w"); 433 | i = 0; 434 | cnt = 0; 435 | printf("zva_wo\n"); 436 | for(curr = head; curr != NULL; curr = curr->next){ 437 | addr1 = curr->va1; 438 | addr2 = curr->va2; 439 | if (addr1 == 0 || addr2 == 0) 440 | continue; 441 | i++; 442 | memset(chunk, curr->init_val, CHUNK_SIZE); 443 | temp = curr->init_val; 444 | // DIFF 445 | asm volatile( 446 | "dc civac, %0\n\t" 447 | "dc civac, %1\n\t" 448 | ::"r" (addr1), "r" (addr2) 449 | ); 450 | for (j = 0; j < HAMMER_ROUND; ++j) { 451 | asm volatile( 452 | "dc zva, %0\n\t" 453 | "dc zva, %1\n\t" 454 | //"dsb 0xb" 455 | ::"r" (addr1), "r" (addr2) 456 | ); 457 | } 458 | // DIFF 459 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 460 | // check victim row only 461 | vctm_pa = curr->vctm_base + j; 462 | vctm_va = pa_to_va(vctm_pa); 463 | if (vctm_va == 0) 464 | continue; 465 | val = *vctm_va; 466 | if (val != curr->init_val) { 467 | cnt++; 468 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 469 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 470 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 471 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 472 | } 473 | *vctm_va = curr->init_val; 474 | } 475 | if (i % OUT_INTERVAL == 0 ) 476 | printf("round:%u\tcount:%u\n\n", i, cnt); 477 | } 478 | fclose(fp); 479 | fclose(fcnt); 480 | // END 481 | 482 | // START DC ZVA W/ DSB 483 | fp = fopen("results/addr_zva_w.txt", "w"); 484 | fcnt = fopen("results/cnt_zva_w.txt","w"); 485 | i = 0; 486 | cnt = 0; 487 | printf("zva_w\n"); 488 | for(curr = head; curr != NULL; curr = curr->next){ 489 | addr1 = curr->va1; 490 | addr2 = curr->va2; 491 | if (addr1 == 0 || addr2 == 0) 492 | continue; 493 | i++; 494 | memset(chunk, curr->init_val, CHUNK_SIZE); 495 | temp = curr->init_val; 496 | // DIFF 497 | asm volatile( 498 | "dc civac, %0\n\t" 499 | "dc civac, %1\n\t" 500 | ::"r" (addr1), "r" (addr2) 501 | ); 502 | for (j = 0; j < HAMMER_ROUND; ++j) { 503 | asm volatile( 504 | "dc zva, %0\n\t" 505 | "dc zva, %1\n\t" 506 | "dsb 0xb" 507 | ::"r" (addr1), "r" (addr2) 508 | ); 509 | } 510 | // DIFF 511 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 512 | // check victim row only 513 | vctm_pa = curr->vctm_base + j; 514 | vctm_va = pa_to_va(vctm_pa); 515 | if (vctm_va == 0) 516 | continue; 517 | val = *vctm_va; 518 | if (val != curr->init_val) { 519 | cnt++; 520 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 521 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 522 | fprintf(fp,"%lx\t%lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 523 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 524 | } 525 | *vctm_va = curr->init_val; 526 | } 527 | if (i % OUT_INTERVAL == 0 ) 528 | printf("round:%u\tcount:%u\n\n", i, cnt); 529 | } 530 | fclose(fp); 531 | fclose(fcnt); 532 | // END 533 | 534 | close(pgmp); 535 | } 536 | 537 | -------------------------------------------------------------------------------- /4_experiments/compare_all_instr/input/flippable_all: -------------------------------------------------------------------------------- 1 | 2582000 2592000 0 2 | 2a63000 2a73000 0 3 | 3ec5000 3ed5000 0 4 | 3f69000 3f79000 0 5 | 478d000 479d000 0 6 | 486b000 487b000 0 7 | 5783000 5793000 0 8 | 5c22000 5c32000 0 9 | 6040000 6050000 0 10 | 6140000 6150000 0 11 | 6ac3000 6ad3000 0 12 | 9468000 9478000 0 13 | aa07000 aa17000 0 14 | b349000 b359000 0 15 | dc8e000 dc9e000 0 16 | 10908000 10918000 0 17 | 10924000 10934000 0 18 | 10ae6000 10af6000 0 19 | 11bcb000 11bdb000 0 20 | 120aa000 120ba000 0 21 | 12464000 12474000 0 22 | 12a61000 12a71000 0 23 | 12d06000 12d16000 0 24 | 134ec000 134fc000 0 25 | 13aa0000 13ab0000 0 26 | 146ef000 146ff000 0 27 | 14fec000 14ffc000 0 28 | 1542c000 1543c000 0 29 | 154c8000 154d8000 0 30 | 15fcd000 15fdd000 0 31 | 16540000 16550000 0 32 | 16724000 16734000 0 33 | 1808f000 1809f000 0 34 | 18d20000 18d30000 0 35 | 1e18b000 1e19b000 0 36 | 1e228000 1e238000 0 37 | 1e604000 1e614000 0 38 | 1eea2000 1eeb2000 0 39 | 1f6a7000 1f6b7000 0 40 | 2014d000 2015d000 0 41 | 21c06000 21c16000 0 42 | 2220c000 2221c000 0 43 | 22e42000 22e52000 0 44 | 23ee3000 23ef3000 0 45 | 24dc0000 24dd0000 0 46 | 24fe3000 24ff3000 0 47 | 25240000 25250000 0 48 | 26340000 26350000 0 49 | 26388000 26398000 0 50 | 275a3000 275b3000 0 51 | 275c5000 275d5000 0 52 | 28f43000 28f53000 0 53 | 29aae000 29abe000 0 54 | 2d306000 2d316000 0 55 | 2da6f000 2da7f000 0 56 | 2dbc0000 2dbd0000 0 57 | 2e4c5000 2e4d5000 0 58 | 309c3000 309d3000 0 59 | 32243000 32253000 0 60 | 32343000 32353000 0 61 | 7326b000 7327b000 0 62 | 2a64000 2a74000 1 63 | 2a8b000 2a9b000 1 64 | 376f000 377f000 1 65 | 3ac0000 3ad0000 1 66 | 44ae000 44be000 1 67 | 44c9000 44d9000 1 68 | 478e000 479e000 1 69 | 4ae9000 4af9000 1 70 | 5968000 5978000 1 71 | 686b000 687b000 1 72 | 6b84000 6b94000 1 73 | 7b21000 7b31000 1 74 | 850c000 851c000 1 75 | 88c7000 88d7000 1 76 | 8e49000 8e59000 1 77 | 8f42000 8f52000 1 78 | 922e000 923e000 1 79 | 94c9000 94d9000 1 80 | 97a0000 97b0000 1 81 | 9908000 9918000 1 82 | a38b000 a39b000 1 83 | b0ec000 b0fc000 1 84 | b145000 b155000 1 85 | cae3000 caf3000 1 86 | d609000 d619000 1 87 | d806000 d816000 1 88 | 1056f000 1057f000 1 89 | 10b29000 10b39000 1 90 | 1168c000 1169c000 1 91 | 12742000 12752000 1 92 | 13162000 13172000 1 93 | 1438e000 1439e000 1 94 | 14b42000 14b52000 1 95 | 14e04000 14e14000 1 96 | 16da1000 16db1000 1 97 | 1718d000 1719d000 1 98 | 17964000 17974000 1 99 | 19064000 19074000 1 100 | 1958f000 1959f000 1 101 | 1aeeb000 1aefb000 1 102 | 1b22e000 1b23e000 1 103 | 1b34b000 1b35b000 1 104 | 1bbec000 1bbfc000 1 105 | 1c1a3000 1c1b3000 1 106 | 1d823000 1d833000 1 107 | 1d8ad000 1d8bd000 1 108 | 1e68f000 1e69f000 1 109 | 1f168000 1f178000 1 110 | 1ffa7000 1ffb7000 1 111 | 200c4000 200d4000 1 112 | 21244000 21254000 1 113 | 21b04000 21b14000 1 114 | 22307000 22317000 1 115 | 22469000 22479000 1 116 | 22922000 22932000 1 117 | 22c88000 22c98000 1 118 | 22dab000 22dbb000 1 119 | 22dca000 22dda000 1 120 | 255a4000 255b4000 1 121 | 255c2000 255d2000 1 122 | 25760000 25770000 1 123 | 25960000 25970000 1 124 | 27f84000 27f94000 1 125 | 28aa2000 28ab2000 1 126 | 29e64000 29e74000 1 127 | 29fa2000 29fb2000 1 128 | 2a20f000 2a21f000 1 129 | 2ac80000 2ac90000 1 130 | 2ccaa000 2ccba000 1 131 | 30c0c000 30c1c000 1 132 | 31aeb000 31afb000 1 133 | 32ce3000 32cf3000 1 134 | 79d07000 79d17000 1 135 | 7a780000 7a790000 1 136 | 7c408000 7c418000 1 137 | 138 | -------------------------------------------------------------------------------- /4_experiments/compare_all_instr/input/input0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x5ec1ab/rowhammer_armv8/8e60cf3091798da8990e131574dac940415848fc/4_experiments/compare_all_instr/input/input0 -------------------------------------------------------------------------------- /4_experiments/disable_cachemaint/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += disable_cache_maint.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | 9 | test: 10 | sudo dmesg -C 11 | sudo insmod disable_cache_maint.ko 12 | sudo rmmod disable_cache_maint.ko 13 | dmesg 14 | -------------------------------------------------------------------------------- /4_experiments/disable_cachemaint/README.md: -------------------------------------------------------------------------------- 1 | # Disable cache maitenance instructions 2 | Bit 26 of SCTLR_EL1 controls enable/disable of cache maintenance instructions 3 | 4 | Bit 14 of SCTLR_EL1 controls enable/disable of DC ZVA instruction 5 | 6 | Every time the kernel module will modify system control register in one core. 7 | Use execute.sh to install and remove the kernel module 100 times to ensure 8 | These instructions are disabled in all cores. 9 | 10 | -------------------------------------------------------------------------------- /4_experiments/disable_cachemaint/disable_cache_maint.c: -------------------------------------------------------------------------------- 1 | /** 2 | * disable_cachemaint -- disable cache maitenance instructions and DC ZVA 3 | * By VandySec Group 4 | **/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int 11 | disable_cache(void) 12 | { 13 | unsigned long reg_value = 0; 14 | printk(KERN_INFO "Disable cache maintenance instructions and DC ZVA\n"); 15 | // check original systemcontrol values 16 | asm volatile("mrs %0, SCTLR_EL1":"=r" (reg_value)); 17 | printk("SCTLR_EL1 is 0x%lx\n", reg_value); 18 | // disable cache maintenance instructions 19 | reg_value &= ~(1 << 26); 20 | // disable DC ZVA 21 | reg_value &= ~(1 << 14); 22 | // write the modified value back to SCTLR_EL1 register 23 | asm volatile("msr SCTLR_EL1, %0"::"r" (reg_value)); 24 | return 0; 25 | } 26 | 27 | void 28 | enable_cache(void) 29 | { 30 | printk(KERN_INFO "Instructions disabled \n"); 31 | } 32 | 33 | module_init(disable_cache); 34 | module_exit(enable_cache); 35 | 36 | MODULE_LICENSE("GPL"); 37 | MODULE_AUTHOR("VandySec Group"); 38 | MODULE_DESCRIPTION("Disable cache maintenance instructions and DC ZVA"); 39 | MODULE_VERSION("0.01"); 40 | 41 | -------------------------------------------------------------------------------- /4_experiments/disable_cachemaint/execute.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | for i in {1..100}; 3 | do 4 | make test 5 | done 6 | -------------------------------------------------------------------------------- /4_experiments/multi_thread/Makefile: -------------------------------------------------------------------------------- 1 | FNAME = rowhammer_instr_cmp 2 | ROUNDS = 500 3 | 4 | all : 5 | gcc multi_thread.c -lrowhammer -pthread 6 | 7 | run : 8 | sudo ./a.out 9 | clean : 10 | rm a.out 11 | 12 | -------------------------------------------------------------------------------- /4_experiments/multi_thread/input/flippable_all: -------------------------------------------------------------------------------- 1 | 2582000 2592000 0 2 | 2a63000 2a73000 0 3 | 3ec5000 3ed5000 0 4 | 3f69000 3f79000 0 5 | 478d000 479d000 0 6 | 486b000 487b000 0 7 | 5783000 5793000 0 8 | 5c22000 5c32000 0 9 | 6040000 6050000 0 10 | 6140000 6150000 0 11 | 6ac3000 6ad3000 0 12 | 9468000 9478000 0 13 | aa07000 aa17000 0 14 | b349000 b359000 0 15 | dc8e000 dc9e000 0 16 | 10908000 10918000 0 17 | 10924000 10934000 0 18 | 10ae6000 10af6000 0 19 | 11bcb000 11bdb000 0 20 | 120aa000 120ba000 0 21 | 12464000 12474000 0 22 | 12a61000 12a71000 0 23 | 12d06000 12d16000 0 24 | 134ec000 134fc000 0 25 | 13aa0000 13ab0000 0 26 | 146ef000 146ff000 0 27 | 14fec000 14ffc000 0 28 | 1542c000 1543c000 0 29 | 154c8000 154d8000 0 30 | 15fcd000 15fdd000 0 31 | 16540000 16550000 0 32 | 16724000 16734000 0 33 | 1808f000 1809f000 0 34 | 18d20000 18d30000 0 35 | 1e18b000 1e19b000 0 36 | 1e228000 1e238000 0 37 | 1e604000 1e614000 0 38 | 1eea2000 1eeb2000 0 39 | 1f6a7000 1f6b7000 0 40 | 2014d000 2015d000 0 41 | 21c06000 21c16000 0 42 | 2220c000 2221c000 0 43 | 22e42000 22e52000 0 44 | 23ee3000 23ef3000 0 45 | 24dc0000 24dd0000 0 46 | 24fe3000 24ff3000 0 47 | 25240000 25250000 0 48 | 26340000 26350000 0 49 | 26388000 26398000 0 50 | 275a3000 275b3000 0 51 | 275c5000 275d5000 0 52 | 28f43000 28f53000 0 53 | 29aae000 29abe000 0 54 | 2d306000 2d316000 0 55 | 2da6f000 2da7f000 0 56 | 2dbc0000 2dbd0000 0 57 | 2e4c5000 2e4d5000 0 58 | 309c3000 309d3000 0 59 | 32243000 32253000 0 60 | 32343000 32353000 0 61 | 7326b000 7327b000 0 62 | 2a64000 2a74000 1 63 | 2a8b000 2a9b000 1 64 | 376f000 377f000 1 65 | 3ac0000 3ad0000 1 66 | 44ae000 44be000 1 67 | 44c9000 44d9000 1 68 | 478e000 479e000 1 69 | 4ae9000 4af9000 1 70 | 5968000 5978000 1 71 | 686b000 687b000 1 72 | 6b84000 6b94000 1 73 | 7b21000 7b31000 1 74 | 850c000 851c000 1 75 | 88c7000 88d7000 1 76 | 8e49000 8e59000 1 77 | 8f42000 8f52000 1 78 | 922e000 923e000 1 79 | 94c9000 94d9000 1 80 | 97a0000 97b0000 1 81 | 9908000 9918000 1 82 | a38b000 a39b000 1 83 | b0ec000 b0fc000 1 84 | b145000 b155000 1 85 | cae3000 caf3000 1 86 | d609000 d619000 1 87 | d806000 d816000 1 88 | 1056f000 1057f000 1 89 | 10b29000 10b39000 1 90 | 1168c000 1169c000 1 91 | 12742000 12752000 1 92 | 13162000 13172000 1 93 | 1438e000 1439e000 1 94 | 14b42000 14b52000 1 95 | 14e04000 14e14000 1 96 | 16da1000 16db1000 1 97 | 1718d000 1719d000 1 98 | 17964000 17974000 1 99 | 19064000 19074000 1 100 | 1958f000 1959f000 1 101 | 1aeeb000 1aefb000 1 102 | 1b22e000 1b23e000 1 103 | 1b34b000 1b35b000 1 104 | 1bbec000 1bbfc000 1 105 | 1c1a3000 1c1b3000 1 106 | 1d823000 1d833000 1 107 | 1d8ad000 1d8bd000 1 108 | 1e68f000 1e69f000 1 109 | 1f168000 1f178000 1 110 | 1ffa7000 1ffb7000 1 111 | 200c4000 200d4000 1 112 | 21244000 21254000 1 113 | 21b04000 21b14000 1 114 | 22307000 22317000 1 115 | 22469000 22479000 1 116 | 22922000 22932000 1 117 | 22c88000 22c98000 1 118 | 22dab000 22dbb000 1 119 | 22dca000 22dda000 1 120 | 255a4000 255b4000 1 121 | 255c2000 255d2000 1 122 | 25760000 25770000 1 123 | 25960000 25970000 1 124 | 27f84000 27f94000 1 125 | 28aa2000 28ab2000 1 126 | 29e64000 29e74000 1 127 | 29fa2000 29fb2000 1 128 | 2a20f000 2a21f000 1 129 | 2ac80000 2ac90000 1 130 | 2ccaa000 2ccba000 1 131 | 30c0c000 30c1c000 1 132 | 31aeb000 31afb000 1 133 | 32ce3000 32cf3000 1 134 | 79d07000 79d17000 1 135 | 7a780000 7a790000 1 136 | 7c408000 7c418000 1 137 | 138 | -------------------------------------------------------------------------------- /4_experiments/multi_thread/input/input0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x5ec1ab/rowhammer_armv8/8e60cf3091798da8990e131574dac940415848fc/4_experiments/multi_thread/input/input0 -------------------------------------------------------------------------------- /4_experiments/multi_thread/multi_thread.c: -------------------------------------------------------------------------------- 1 | /** 2 | * multi_thread -- show effectiveness of multi thread 3 | * By VandySec Group 4 | **/ 5 | #define _GNU_SOURCE 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define CHUNK_SIZE 0x40000000 19 | #define VPN_SIZE 0x80000 20 | #define PAGE_SIZE 4096 21 | #define ROW_SIZE 8192 22 | #define VAL_SIZE sizeof(unsigned long) 23 | #define HAMMER_ROUND 5000000 24 | 25 | #define INPUT_FILE "input/flippable_all" 26 | #define OUT_INTERVAL 1 27 | 28 | // input arguments for thread routine 29 | // address to be hammered 30 | // the core on which the thread runs 31 | struct thr_arg { 32 | unsigned long addr; 33 | unsigned long core; 34 | }; 35 | // linked list for storing attacker addresses 36 | struct attkr_t{ 37 | unsigned long pa1; 38 | unsigned long pa2; 39 | unsigned long va1; 40 | unsigned long va2; 41 | unsigned long vctm_base; 42 | unsigned long init_val; 43 | struct attkr_t *next; 44 | }; 45 | 46 | unsigned long chunk[CHUNK_SIZE / VAL_SIZE]; 47 | unsigned long va_tab[VPN_SIZE]; 48 | unsigned cnt = 0; 49 | struct unibit_t *bit_head = NULL; 50 | pthread_cond_t cv; 51 | pthread_mutex_t mtx; 52 | int status_arr[4]; 53 | unsigned long temp = -1; 54 | 55 | void 56 | generate_va_table(int pgmp) 57 | { 58 | for (int i = 0; i < CHUNK_SIZE / VAL_SIZE; i += PAGE_SIZE / VAL_SIZE){ 59 | unsigned long data; 60 | unsigned long index = (unsigned long)&chunk[i] / PAGE_SIZE * sizeof(data); 61 | if (pread(pgmp, &data, sizeof(data), index) != sizeof(data)) { 62 | perror("pread"); 63 | break; 64 | } 65 | unsigned long pfn = data & 0x7fffffffffffff; 66 | if (pfn <= 0 || pfn > VPN_SIZE){ 67 | perror("VPN_TABLE TOO SMALL"); 68 | break; 69 | } else 70 | va_tab[pfn] = index / sizeof(data) * PAGE_SIZE; 71 | } 72 | } 73 | 74 | unsigned long * 75 | pa_to_va(unsigned long pa) 76 | { 77 | unsigned long va_off = pa % PAGE_SIZE; 78 | unsigned long va_pfn = pa / PAGE_SIZE; 79 | if (va_tab[va_pfn] == 0) 80 | return 0; 81 | else 82 | return (unsigned long *)(va_tab[va_pfn] + va_off); 83 | } 84 | 85 | struct attkr_t * 86 | generate_addr_list(char *fname) 87 | { 88 | FILE *f_in = fopen(fname, "r"); 89 | char str[999]; 90 | unsigned long attk_pa1, attk_pa2, attk_pfn1, attk_pfn2, init_val; 91 | struct attkr_t *head, *curr, *prev; 92 | head = NULL; 93 | curr = head; 94 | while (fscanf(f_in, "%s", str) != EOF){ 95 | attk_pa1 = (unsigned long)strtol(str, NULL, 16); 96 | fscanf(f_in, "%s", str); 97 | attk_pa2 = (unsigned long)strtol(str, NULL, 16); 98 | fscanf(f_in, "%s", str); 99 | init_val = (unsigned long)(-strtol(str, NULL, 10)); 100 | attk_pfn1 = attk_pa1 / PAGE_SIZE; 101 | attk_pfn2 = attk_pa2 / PAGE_SIZE; 102 | 103 | curr = (struct attkr_t *)malloc(sizeof(struct attkr_t)); 104 | curr->pa1 = attk_pa1; 105 | curr->pa2 = attk_pa2; 106 | curr->va1 = (unsigned long)pa_to_va(attk_pa1); 107 | curr->va2 = (unsigned long)pa_to_va(attk_pa2); 108 | curr->vctm_base = (attk_pfn1 + attk_pfn2) / 2 * PAGE_SIZE; 109 | curr->init_val = init_val; 110 | curr->next = NULL; 111 | 112 | if (curr->va1 == 0 || curr->va2 == 0){ 113 | free(curr); 114 | continue; 115 | } else if (head == NULL){ 116 | head = curr; 117 | prev = head; 118 | } else { 119 | prev->next = curr; 120 | prev = prev->next; 121 | } 122 | } 123 | fclose(f_in); 124 | return head; 125 | } 126 | 127 | // thread entry 128 | void * 129 | civac_str_wo(void *argp) 130 | { 131 | struct thr_arg data = *(struct thr_arg *)argp; 132 | int addr = data.addr; 133 | int core = data.core; 134 | cpu_set_t cs; 135 | pthread_t tself; 136 | // set core affinity 137 | CPU_ZERO(&cs); 138 | CPU_SET(core, &cs); 139 | tself = pthread_self(); 140 | pthread_setaffinity_np(tself, sizeof(cpu_set_t), &cs); 141 | 142 | pthread_mutex_lock(&mtx); 143 | // ready to begin 144 | status_arr[core] = 1; 145 | pthread_cond_wait(&cv, &mtx); 146 | pthread_mutex_unlock(&mtx); 147 | status_arr[core] = 0; 148 | // begin hammering 149 | for (int i = 0; i < HAMMER_ROUND; ++i) { 150 | asm volatile( 151 | "str %1, [%0]\n\t" 152 | "dc civac, %0\n\t" 153 | ::"r" (addr), "r" (temp) 154 | ); 155 | } 156 | } 157 | void * 158 | civac_ldr_wo(void *argp) 159 | { 160 | struct thr_arg data = *(struct thr_arg *)argp; 161 | int addr = data.addr; 162 | int core = data.core; 163 | cpu_set_t cs; 164 | pthread_t tself; 165 | // set core affinity 166 | CPU_ZERO(&cs); 167 | CPU_SET(core, &cs); 168 | tself = pthread_self(); 169 | pthread_setaffinity_np(tself, sizeof(cpu_set_t), &cs); 170 | 171 | pthread_mutex_lock(&mtx); 172 | // ready to begin 173 | status_arr[core] = 1; 174 | pthread_cond_wait(&cv, &mtx); 175 | pthread_mutex_unlock(&mtx); 176 | status_arr[core] = 0; 177 | // begin hammering 178 | for (int i = 0; i < HAMMER_ROUND; ++i) { 179 | asm volatile( 180 | "ldr %1, [%0]\n\t" 181 | "dc civac, %0\n\t" 182 | ::"r" (addr), "r" (temp) 183 | ); 184 | } 185 | } 186 | 187 | int 188 | main(int argc, char **argv) 189 | { unsigned i, j; 190 | unsigned flips = 0; 191 | unsigned long addr1, addr2; 192 | FILE *fp, *fcnt; 193 | char path[200]; 194 | sprintf(path, "/proc/%u/pagemap", getpid()); 195 | int pgmp = open(path, O_RDONLY); 196 | unsigned long vctm_pa, *vctm_va, val; 197 | char str[999]; 198 | struct attkr_t *head, *curr; 199 | unsigned long prev_init = -1; 200 | 201 | pthread_t tid0, tid1, tid2, tid3, tself; 202 | struct thr_arg arg0, arg1, arg2, arg3; 203 | cpu_set_t cs; 204 | arg0.core = 0; 205 | arg1.core = 1; 206 | arg2.core = 2; 207 | arg3.core = 3; 208 | CPU_ZERO(&cs); 209 | CPU_SET(0, &cs); 210 | tself = pthread_self(); 211 | pthread_setaffinity_np(tself, sizeof(cpu_set_t), &cs); 212 | pthread_cond_init(&cv, NULL); 213 | pthread_mutex_init(&mtx, NULL); 214 | 215 | // initialize chunk 216 | for (i = 0; i < CHUNK_SIZE / VAL_SIZE; ++i) 217 | chunk[i] = -1; 218 | // generate pa-va mapping 219 | generate_va_table(pgmp); 220 | head = generate_addr_list(INPUT_FILE); 221 | // START 222 | fp = fopen("results/addr_civac_ldr_2.txt", "w"); 223 | fcnt = fopen("results/cnt_civac_ldr_2.txt","w"); 224 | printf("civac_ldr_2\n"); 225 | i = 0; 226 | cnt = 0; 227 | for(curr = head; curr != NULL; curr = curr->next){ 228 | addr1 = curr->va1; 229 | addr2 = curr->va2; 230 | if (addr1 == 0 || addr2 == 0) 231 | continue; 232 | i++; 233 | if (prev_init != curr->init_val){ 234 | printf("change check bit to %lx\n", curr->init_val); 235 | memset(chunk, curr->init_val, CHUNK_SIZE); 236 | prev_init = curr->init_val; 237 | } 238 | temp = curr->init_val; 239 | // DIFF 240 | arg1.addr = addr1; 241 | arg2.addr = addr2; 242 | pthread_create(&tid1, NULL, civac_ldr_wo, &arg1); 243 | pthread_create(&tid2, NULL, civac_ldr_wo, &arg2); 244 | while(status_arr[1] != 1 || status_arr[2] !=1) 245 | { 246 | // spinlock 247 | } 248 | while(status_arr[1] == 1 || status_arr[2] ==1) 249 | pthread_cond_broadcast(&cv); 250 | pthread_join(tid1, NULL); 251 | pthread_join(tid2, NULL); 252 | // DIFF 253 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 254 | // check victim row only 255 | vctm_pa = curr->vctm_base + j; vctm_va = pa_to_va(vctm_pa); 256 | if (vctm_va == 0) 257 | continue; 258 | val = *vctm_va; 259 | if (val != curr->init_val) { 260 | cnt++; 261 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 262 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 263 | fprintf(fp,"%8lx %8lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 264 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 265 | } 266 | *vctm_va = curr->init_val; 267 | } 268 | if (i % OUT_INTERVAL == 0 ) 269 | printf("round:%u\tcount:%u\n\n", i, cnt); 270 | } 271 | fclose(fp); 272 | fclose(fcnt); 273 | // END 274 | // START 275 | fp = fopen("results/addr_civac_str_2.txt", "w"); 276 | fcnt = fopen("results/cnt_civac_str_2.txt","w"); 277 | printf("civac_str_2\n"); 278 | i = 0; 279 | cnt = 0; 280 | for(curr = head; curr != NULL; curr = curr->next){ 281 | addr1 = curr->va1; 282 | addr2 = curr->va2; 283 | if (addr1 == 0 || addr2 == 0) 284 | continue; 285 | i++; 286 | if (prev_init != curr->init_val){ 287 | printf("change check bit to %lx\n", curr->init_val); 288 | memset(chunk, curr->init_val, CHUNK_SIZE); 289 | prev_init = curr->init_val; 290 | } 291 | temp = curr->init_val; 292 | // DIFF 293 | arg1.addr = addr1; 294 | arg2.addr = addr2; 295 | pthread_create(&tid1, NULL, civac_str_wo, &arg1); 296 | pthread_create(&tid2, NULL, civac_str_wo, &arg2); 297 | while(status_arr[1] != 1 || status_arr[2] !=1); 298 | while(status_arr[1] == 1 || status_arr[2] ==1) 299 | pthread_cond_broadcast(&cv); 300 | pthread_join(tid1, NULL); 301 | pthread_join(tid2, NULL); 302 | // DIFF 303 | for (j = 0; j < ROW_SIZE; j += VAL_SIZE) { 304 | // check victim row only 305 | vctm_pa = curr->vctm_base + j; vctm_va = pa_to_va(vctm_pa); 306 | if (vctm_va == 0) 307 | continue; 308 | val = *vctm_va; 309 | if (val != curr->init_val) { 310 | cnt++; 311 | printf("attkr1:%lx\tattkr2:%lx\n", curr->pa1, curr->pa2); 312 | printf("rnd:%u\tcnt:%u\tvctm:%lx to %lx\n", i, cnt, vctm_pa, val); 313 | fprintf(fp,"%8lx %8lx\t%lu\n", curr->pa1, curr->pa2, -(curr->init_val)); 314 | fprintf(fcnt,"%u\t%u\n\n", i, cnt); 315 | } 316 | *vctm_va = curr->init_val; 317 | } 318 | if (i % OUT_INTERVAL == 0 ) 319 | printf("round:%u\tcount:%u\n\n", i, cnt); 320 | } 321 | fclose(fp); 322 | fclose(fcnt); 323 | 324 | close(pgmp); 325 | } 326 | 327 | -------------------------------------------------------------------------------- /4_experiments/time_measure/Makefile: -------------------------------------------------------------------------------- 1 | all : 2 | gcc time_measure.c -lrowhammer -pthread 3 | 4 | run : 5 | sudo ./a.out > results 6 | cat results 7 | clean : 8 | rm ./a.out 9 | -------------------------------------------------------------------------------- /4_experiments/time_measure/time_measure.c: -------------------------------------------------------------------------------- 1 | /** 2 | * time_measure -- measure execution time of different approaches 3 | * By VandySec Group 4 | **/ 5 | #define _GNU_SOURCE 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define CHUNK_SIZE 0x40000000 20 | #define VPN_SIZE 0x80000 21 | #define PAGE_SIZE 4096 22 | #define VAL_SIZE sizeof(unsigned long) 23 | #define TIMES 1000 24 | #define HAMMER_ROUND 2000 25 | #define DISABLE 0 26 | 27 | // argument for thread routine 28 | // address to be hammered 29 | // the core on which the thread runs 30 | struct thr_arg { 31 | unsigned long addr; 32 | unsigned long core; 33 | }; 34 | 35 | unsigned long chunk[CHUNK_SIZE / VAL_SIZE]; 36 | pthread_cond_t cv; 37 | pthread_mutex_t mtx; 38 | int status_arr[4]; 39 | 40 | // thread routines 41 | void * 42 | civac_str_wo(void *argp) 43 | { 44 | struct thr_arg data = *(struct thr_arg *)argp; 45 | int addr = data.addr; 46 | int core = data.core; 47 | unsigned long temp = -1; 48 | // set core affinity 49 | cpu_set_t cs; 50 | pthread_t tself; 51 | CPU_ZERO(&cs); 52 | CPU_SET(core, &cs); 53 | tself = pthread_self(); 54 | pthread_setaffinity_np(tself, sizeof(cpu_set_t), &cs); 55 | // synchronization 56 | pthread_mutex_lock(&mtx); 57 | status_arr[core] = 1; 58 | pthread_cond_wait(&cv, &mtx); 59 | pthread_mutex_unlock(&mtx); 60 | status_arr[core] = 0; 61 | // repeately access and flush the same memory location 62 | for (int i = 0; i < HAMMER_ROUND; ++i) { 63 | asm volatile( 64 | "str %1, [%0]\n\t" 65 | "dc civac, %0\n\t" 66 | ::"r" (addr), "r" (temp) 67 | ); 68 | } 69 | } 70 | void * 71 | civac_str_w(void *argp) 72 | { 73 | struct thr_arg data = *(struct thr_arg *)argp; 74 | int addr = data.addr; 75 | int core = data.core; 76 | unsigned long temp = -1; 77 | cpu_set_t cs; 78 | pthread_t tself; 79 | CPU_ZERO(&cs); 80 | CPU_SET(core, &cs); 81 | tself = pthread_self(); 82 | pthread_setaffinity_np(tself, sizeof(cpu_set_t), &cs); 83 | 84 | pthread_mutex_lock(&mtx); 85 | status_arr[core] = 1; 86 | pthread_cond_wait(&cv, &mtx); 87 | pthread_mutex_unlock(&mtx); 88 | status_arr[core] = 0; 89 | for (int i = 0; i < HAMMER_ROUND; ++i) { 90 | asm volatile( 91 | "str %1, [%0]\n\t" 92 | "dc civac, %0\n\t" 93 | "dsb 0xb" 94 | ::"r" (addr), "r" (temp) 95 | ); 96 | } 97 | } 98 | void * 99 | civac_ldr_wo(void *argp) 100 | { 101 | struct thr_arg data = *(struct thr_arg *)argp; 102 | int addr = data.addr; 103 | int core = data.core; 104 | unsigned long temp = -1; 105 | cpu_set_t cs; 106 | pthread_t tself; 107 | CPU_ZERO(&cs); 108 | CPU_SET(core, &cs); 109 | tself = pthread_self(); 110 | pthread_setaffinity_np(tself, sizeof(cpu_set_t), &cs); 111 | 112 | pthread_mutex_lock(&mtx); 113 | status_arr[core] = 1; 114 | pthread_cond_wait(&cv, &mtx); 115 | pthread_mutex_unlock(&mtx); 116 | status_arr[core] = 0; 117 | for (int i = 0; i < HAMMER_ROUND; ++i) { 118 | asm volatile( 119 | "ldr %1, [%0]\n\t" 120 | "dc civac, %0\n\t" 121 | ::"r" (addr), "r" (temp) 122 | ); 123 | } 124 | } 125 | void * 126 | civac_ldr_w(void *argp) 127 | { 128 | struct thr_arg data = *(struct thr_arg *)argp; 129 | int addr = data.addr; 130 | int core = data.core; 131 | unsigned long temp = -1; 132 | cpu_set_t cs; 133 | pthread_t tself; 134 | CPU_ZERO(&cs); 135 | CPU_SET(core, &cs); 136 | tself = pthread_self(); 137 | pthread_setaffinity_np(tself, sizeof(cpu_set_t), &cs); 138 | 139 | pthread_mutex_lock(&mtx); 140 | status_arr[core] = 1; 141 | pthread_cond_wait(&cv, &mtx); 142 | pthread_mutex_unlock(&mtx); 143 | status_arr[core] = 0; 144 | for (int i = 0; i < HAMMER_ROUND; ++i) { 145 | asm volatile( 146 | "ldr %1, [%0]\n\t" 147 | "dc civac, %0\n\t" 148 | "dsb 0xb" 149 | ::"r" (addr), "r" (temp) 150 | ); 151 | } 152 | } 153 | int 154 | main(int argc, char **argv) 155 | { 156 | unsigned i, j; 157 | unsigned long addr1, addr2; 158 | unsigned long temp = -1; 159 | candidate_t *head, *curr; 160 | char path[200]; 161 | unsigned long bgn, end; 162 | struct timespec ts1, ts2; 163 | unsigned long td; 164 | 165 | pthread_t tid0, tid1, tid2, tid3, tself; 166 | struct thr_arg arg0, arg1, arg2, arg3; 167 | cpu_set_t cs; 168 | arg0.core = 0; 169 | arg1.core = 1; 170 | arg2.core = 2; 171 | arg3.core = 3; 172 | // assign main thread on core 0 173 | CPU_ZERO(&cs); 174 | CPU_SET(0, &cs); 175 | tself = pthread_self(); 176 | pthread_setaffinity_np(tself, sizeof(cpu_set_t), &cs); 177 | 178 | // initialize chunk 179 | for (i = 0; i < CHUNK_SIZE / VAL_SIZE; ++i) 180 | chunk[i] = -1; 181 | bgn = (unsigned long) chunk; 182 | end = bgn + CHUNK_SIZE; 183 | head = find_candidates(bgn, end, 12, 16); 184 | // measure execution time per loop for 6 methods with/without memory barrier 185 | // DC ZVA 186 | // DC CVAC + STR 187 | // DC CIVAC + STR 188 | // DC CIVAC + LDR 189 | // DC CIVAC + STR 2 thread 190 | // DC CIVAC + LDR 2 thread 191 | 192 | // DC ZVA can't work when it's disabled 193 | #if !DISABLE 194 | td = 0; 195 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 196 | // two addresses to be hammered 197 | addr1 = curr->va1; 198 | addr2 = curr->va2; 199 | // flush two aggressor rows 200 | asm volatile( 201 | "dc civac, %0\n\t" 202 | "dc civac, %1\n\t" 203 | ::"r" (addr1), "r" (addr2) 204 | ); 205 | // get time stamp before hammering 206 | clock_gettime(CLOCK_MONOTONIC, &ts1); 207 | for (j = 0; j < HAMMER_ROUND; ++j) { 208 | // use dc zva to access target rows 209 | asm volatile( 210 | "dc zva, %0\n\t" 211 | "dc zva, %1\n\t" 212 | ::"r" (addr1), "r" (addr2) 213 | ); 214 | } 215 | // get time stamp after hammering 216 | clock_gettime(CLOCK_MONOTONIC, &ts2); 217 | // compute execution time per loop 218 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 219 | } 220 | printf("dc zva w/o\t%lu\n", td / HAMMER_ROUND / TIMES); 221 | // same operations for remaining 11 measurements 222 | td = 0; 223 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 224 | addr1 = curr->va1; 225 | addr2 = curr->va2; 226 | asm volatile( 227 | "dc civac, %0\n\t" 228 | "dc civac, %1\n\t" 229 | ::"r" (addr1), "r" (addr2) 230 | ); 231 | clock_gettime(CLOCK_MONOTONIC, &ts1); 232 | for (j = 0; j < HAMMER_ROUND; ++j) { 233 | asm volatile( 234 | "dc zva, %0\n\t" 235 | "dc zva, %1\n\t" 236 | "dsb 0xb" 237 | ::"r" (addr1), "r" (addr2) 238 | ); 239 | } 240 | clock_gettime(CLOCK_MONOTONIC, &ts2); 241 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 242 | } 243 | printf("dc zva w/ \t%lu\n", td / HAMMER_ROUND / TIMES); 244 | #endif 245 | 246 | td = 0; 247 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 248 | addr1 = curr->va1; 249 | addr2 = curr->va2; 250 | clock_gettime(CLOCK_MONOTONIC, &ts1); 251 | for (j = 0; j < HAMMER_ROUND; ++j) { 252 | asm volatile( 253 | "str %2, [%0]\n\t" 254 | "str %2, [%1]\n\t" 255 | "dc cvac, %0\n\t" 256 | "dc cvac, %1\n\t" 257 | ::"r" (addr1), "r" (addr2), "r" (temp) 258 | ); 259 | } 260 | clock_gettime(CLOCK_MONOTONIC, &ts2); 261 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 262 | } 263 | printf("dc cvac w/o\t%lu\n", td / HAMMER_ROUND / TIMES); 264 | td = 0; 265 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 266 | addr1 = curr->va1; 267 | addr2 = curr->va2; 268 | clock_gettime(CLOCK_MONOTONIC, &ts1); 269 | for (j = 0; j < HAMMER_ROUND; ++j) { 270 | asm volatile( 271 | "str %2, [%0]\n\t" 272 | "str %2, [%1]\n\t" 273 | "dc cvac, %0\n\t" 274 | "dc cvac, %1\n\t" 275 | "dsb 0xb" 276 | ::"r" (addr1), "r" (addr2), "r" (temp) 277 | ); 278 | } 279 | clock_gettime(CLOCK_MONOTONIC, &ts2); 280 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 281 | } 282 | printf("dc cvac w/ \t%lu\n", td / HAMMER_ROUND / TIMES); 283 | 284 | td = 0; 285 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 286 | addr1 = curr->va1; 287 | addr2 = curr->va2; 288 | clock_gettime(CLOCK_MONOTONIC, &ts1); 289 | for (j = 0; j < HAMMER_ROUND; ++j) { 290 | asm volatile( 291 | "str %2, [%0]\n\t" 292 | "str %2, [%1]\n\t" 293 | "dc civac, %0\n\t" 294 | "dc civac, %1\n\t" 295 | ::"r" (addr1), "r" (addr2), "r" (temp) 296 | ); 297 | } 298 | clock_gettime(CLOCK_MONOTONIC, &ts2); 299 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 300 | } 301 | printf("dc civac str w/o\t%lu\n", td / HAMMER_ROUND / TIMES); 302 | td = 0; 303 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 304 | addr1 = curr->va1; 305 | addr2 = curr->va2; 306 | clock_gettime(CLOCK_MONOTONIC, &ts1); 307 | for (j = 0; j < HAMMER_ROUND; ++j) { 308 | asm volatile( 309 | "str %2, [%0]\n\t" 310 | "str %2, [%1]\n\t" 311 | "dc civac, %0\n\t" 312 | "dc civac, %1\n\t" 313 | "dsb 0xb" 314 | ::"r" (addr1), "r" (addr2), "r" (temp) 315 | ); 316 | } 317 | clock_gettime(CLOCK_MONOTONIC, &ts2); 318 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 319 | } 320 | printf("dc civac str w/ \t%lu\n", td / HAMMER_ROUND / TIMES); 321 | 322 | td = 0; 323 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 324 | addr1 = curr->va1; 325 | addr2 = curr->va2; 326 | clock_gettime(CLOCK_MONOTONIC, &ts1); 327 | for (j = 0; j < HAMMER_ROUND; ++j) { 328 | asm volatile( 329 | "ldr %2, [%0]\n\t" 330 | "ldr %2, [%1]\n\t" 331 | "dc civac, %0\n\t" 332 | "dc civac, %1\n\t" 333 | ::"r" (addr1), "r" (addr2), "r" (temp) 334 | ); 335 | } 336 | clock_gettime(CLOCK_MONOTONIC, &ts2); 337 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 338 | } 339 | printf("dc civac ldr w/o\t%lu\n", td / HAMMER_ROUND / TIMES); 340 | td = 0; 341 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 342 | addr1 = curr->va1; 343 | addr2 = curr->va2; 344 | clock_gettime(CLOCK_MONOTONIC, &ts1); 345 | for (j = 0; j < HAMMER_ROUND; ++j) { 346 | asm volatile( 347 | "ldr %2, [%0]\n\t" 348 | "ldr %2, [%1]\n\t" 349 | "dc civac, %0\n\t" 350 | "dc civac, %1\n\t" 351 | "dsb 0xb" 352 | ::"r" (addr1), "r" (addr2), "r" (temp) 353 | ); 354 | } 355 | clock_gettime(CLOCK_MONOTONIC, &ts2); 356 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 357 | } 358 | printf("dc civac ldr w/ \t%lu\n", td / HAMMER_ROUND / TIMES); 359 | 360 | td = 0; 361 | pthread_cond_init(&cv, NULL); 362 | pthread_mutex_init(&mtx, NULL); 363 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 364 | addr1 = curr->va1; 365 | addr2 = curr->va2; 366 | arg1.addr = addr1; 367 | arg2.addr = addr2; 368 | pthread_create(&tid1, NULL, civac_str_wo, &arg1); 369 | pthread_create(&tid2, NULL, civac_str_wo, &arg2); 370 | while(status_arr[1] != 1 || status_arr[2] != 1); 371 | while(status_arr[1] == 1 || status_arr[2] == 1) 372 | pthread_cond_broadcast(&cv); 373 | clock_gettime(CLOCK_MONOTONIC, &ts1); 374 | pthread_join(tid1, NULL); 375 | pthread_join(tid2, NULL); 376 | clock_gettime(CLOCK_MONOTONIC, &ts2); 377 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 378 | } 379 | printf("dc civac str w/o\t%lu\tparallel\n", td / HAMMER_ROUND / TIMES); 380 | td = 0; 381 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 382 | addr1 = curr->va1; 383 | addr2 = curr->va2; 384 | arg1.addr = addr1; 385 | arg2.addr = addr2; 386 | pthread_create(&tid1, NULL, civac_str_w, &arg1); 387 | pthread_create(&tid2, NULL, civac_str_w, &arg2); 388 | while(status_arr[1] != 1 || status_arr[2] != 1); 389 | while(status_arr[1] == 1 || status_arr[2] == 1) 390 | pthread_cond_broadcast(&cv); 391 | clock_gettime(CLOCK_MONOTONIC, &ts1); 392 | pthread_join(tid1, NULL); 393 | pthread_join(tid2, NULL); 394 | clock_gettime(CLOCK_MONOTONIC, &ts2); 395 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 396 | } 397 | printf("dc civac str w \t%lu\tparallel\n", td / HAMMER_ROUND / TIMES); 398 | 399 | td = 0; 400 | pthread_cond_init(&cv, NULL); 401 | pthread_mutex_init(&mtx, NULL); 402 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 403 | addr1 = curr->va1; 404 | addr2 = curr->va2; 405 | arg1.addr = addr1; 406 | arg2.addr = addr2; 407 | pthread_create(&tid1, NULL, civac_ldr_wo, &arg1); 408 | pthread_create(&tid2, NULL, civac_ldr_wo, &arg2); 409 | while(status_arr[1] != 1 || status_arr[2] != 1); 410 | while(status_arr[1] == 1 || status_arr[2] == 1) 411 | pthread_cond_broadcast(&cv); 412 | clock_gettime(CLOCK_MONOTONIC, &ts1); 413 | pthread_join(tid1, NULL); 414 | pthread_join(tid2, NULL); 415 | clock_gettime(CLOCK_MONOTONIC, &ts2); 416 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 417 | } 418 | printf("dc civac ldr w/o\t%lu\tparallel\n", td / HAMMER_ROUND / TIMES); 419 | td = 0; 420 | for (i = 0, curr = head; i < TIMES && curr != NULL; ++i, curr = curr->next) { 421 | addr1 = curr->va1; 422 | addr2 = curr->va2; 423 | arg1.addr = addr1; 424 | arg2.addr = addr2; 425 | pthread_create(&tid1, NULL, civac_ldr_w, &arg1); 426 | pthread_create(&tid2, NULL, civac_ldr_w, &arg2); 427 | while(status_arr[1] != 1 || status_arr[2] != 1); 428 | while(status_arr[1] == 1 || status_arr[2] == 1) 429 | pthread_cond_broadcast(&cv); 430 | clock_gettime(CLOCK_MONOTONIC, &ts1); 431 | pthread_join(tid1, NULL); 432 | pthread_join(tid2, NULL); 433 | clock_gettime(CLOCK_MONOTONIC, &ts2); 434 | td += (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); 435 | } 436 | printf("dc civac ldr w \t%lu\tparallel\n", td / HAMMER_ROUND / TIMES); 437 | 438 | } 439 | 440 | -------------------------------------------------------------------------------- /5_modify_refresh_rate/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += sysreg.o 2 | 3 | all: 4 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 5 | 6 | clean: 7 | make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean 8 | 9 | test: 10 | sudo dmesg -C 11 | sudo insmod sysreg.ko 12 | sudo rmmod sysreg.ko 13 | dmesg 14 | -------------------------------------------------------------------------------- /5_modify_refresh_rate/README.md: -------------------------------------------------------------------------------- 1 | # Modify Refresh Interval 2 | Used for AML-S905X-CC only 3 | 4 | Modify the least significant 16 bits of register 0x24 to change DRAM refresh ] 5 | rate 6 | * bits 0~7 t100ns 7 | * bits 8~15 tREFI 8 | * Increasing these two values can increase refresh interval, making bits easier 9 | to be flipped. Note: This modification is only used for find relatively 10 | vulnerable bits and the refresh rate should not be modified while doing the 11 | evaluations 12 | 13 | -------------------------------------------------------------------------------- /5_modify_refresh_rate/sysreg.c: -------------------------------------------------------------------------------- 1 | /** 2 | * systemreg -- modify DRAM refresh interval on AML-S905-CC 3 | * By VandySec Group 4 | **/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define BASE_ADDR 0xC8838000 11 | #define REG_NUM 0x000000FE 12 | #define REG_SIZE 4 13 | 14 | int 15 | sysreg_start(void) 16 | { 17 | int i; 18 | void __iomem *regPtr; 19 | unsigned regVal; 20 | printk(KERN_INFO "Insert module \n"); 21 | 22 | // map physical addresses of regs to kernel's address space 23 | regPtr = ioremap(BASE_ADDR, REG_NUM * REG_SIZE); 24 | 25 | 26 | // reset the refresh interval 27 | //iowrite32(0x20104C33, regPtr + 0x24 * REG_SIZE); 28 | 29 | // change the refresh interval (least significant 16 bits) 30 | //iowrite32(0x20104e5D, regPtr + 0x24 * REG_SIZE); 31 | 32 | for (i = 0; i < REG_NUM; i++) { 33 | regVal = ioread32(regPtr + i * REG_SIZE); 34 | printk("regVal 0x%04x is 0x%08x\n", i, regVal); 35 | } 36 | 37 | // unmap this address region 38 | iounmap(regPtr); 39 | 40 | return 0; 41 | } 42 | 43 | void 44 | sysreg_end(void) 45 | { 46 | printk(KERN_INFO "Remove module \n"); 47 | } 48 | 49 | module_init(sysreg_start); 50 | module_exit(sysreg_end); 51 | 52 | MODULE_LICENSE("GPL"); 53 | MODULE_AUTHOR("VandySec Group"); 54 | MODULE_DESCRIPTION("Modify DRAM refresh interval"); 55 | MODULE_VERSION("0.01"); 56 | 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rowhammer_armv8 2 | 3 | The preliminary results are published in our paper "**Triggering Rowhammer Hardware Faults on ARM: A Revisit**". 4 | 5 | This code works on board AML-S905X-CC(Le Potato). 6 | To use it on other boards, some minor modifications may be needed. 7 | 8 | **NOTE:** 9 | As our focus is on how to trigger the rowhammer bug on ARMv8-A platforms, some of the technical challenges like obtaining the physical-to-DRAM address mapping and finding appropriate aggressor rows are solved directly by leveraging some privileged interfaces/methods. 10 | However, after pairs of aggressor rows are acquired, the hammering process is unprivileged. 11 | 12 | # How to run our experiments 13 | ### Get mapping from physical address to DRAM 14 | 15 | We implement this in a kernel module. 16 | To perform double-sided hammering, we are interested in the second lowest row bit. 17 | (We found the second lowest row bit is bit 16 of the physical address on AML-S905X-CC.) 18 | 19 | ``` 20 | cd 1_phy2dram_mapping 21 | make 22 | make test 23 | ``` 24 | 25 | 26 | ### Install pagemap lib 27 | 28 | This library can be used to read "/proc/\/pagemap" file and find candidate aggressor pairs 29 | 30 | ``` 31 | cd 2_find_aggressors 32 | make 33 | make install 34 | ``` 35 | 36 | ### Start rowhammer test 37 | 38 | Run rowhammer program and output flippable bits 39 | 40 | ``` 41 | cd 3_rowhammer_test 42 | make 43 | make run 44 | ``` 45 | 46 | Sending output as input of experiments 47 | 48 | ``` 49 | make send 50 | ``` 51 | 52 | ### Experiments 53 | 54 | * Experiment 1: Finding relationships between the number of iterations and the number of bit flips 55 | 56 | * Experiment 2: Measuring the execution time of different apporaches 57 | 58 | * Experiment 3: Comparing the effectiveness of different approaches 59 | 60 | * Experiment 4: Measuring the performance of multi-threaded hammering 61 | - You can also disable cache maintenance instructions 62 | 63 | ### Modify refresh rate (optional) 64 | 65 | * Applicable on AML-S905X-CC(Le Potato) only 66 | 67 | * Can modify refresh interval of DRAM 68 | 69 | * Only used to quickly find potential aggressor rows 70 | --------------------------------------------------------------------------------