#include<stdio.h> #include<stdint.h> #ifdef _MSC_VER #include<intrin.h>/* for rdtscp and clflush */ #pragma optimize("gt",on) #else #include<x86intrin.h>/* for rdtscp and clflush */ #endif
int p[64 * 10 + 1];
intmain(){ for(int i = 0; i < 10; i++) _mm_clflush(&p[i * 64]); }
这段代码在电脑上可以运行,但是在gem5上会报错(clflush由CleanupSpec实现)
💡Idea
在cleanupSpec的攻击代码中,在flush array2之前,用了如下代码
for (i = 0; i < sizeof(array2); i++) array2[i] = 1; /* write to array2 so in RAM not copy-on-write zero pages */
#include<stdio.h> #include<stdint.h> #ifdef _MSC_VER #include<intrin.h>/* for rdtscp and clflush */ #pragma optimize("gt",on) #else #include<x86intrin.h>/* for rdtscp and clflush */ #endif
int p[64 * 10 + 1];
intmain(){ p[0] = 1; for(int i = 0; i < 2; i++) _mm_clflush(&p[i * 64]); }
25274500: system.ruby.l2_cntrl0: MESI_Two_Level-L2cache.sm:440: Addr: 0xcdd40 is Dirty, Flush Invalidate in L2
25299000: system.ruby.l1_cntrl0: MESI_Two_Level-L1cache.sm:683: RubyRequest FLUSH received at L1 for Addr 0xcde40 25299000: system.ruby.l1_cntrl0.L1Dcache: No tag match for address: 0
25301000: system.ruby.l2_cntrl0: MESI_Two_Level-L2cache.sm:448: Addr: 0xcde40: not present on Flush Invalidate in L2
好家伙,那这不是跟cow一点关系都没有吗😅。纯粹就是cache中没有这个数据就会报错吧
继续验证
现在的猜想是cache中没有要flush的数据就会报错。
根据这个猜想写出了两份代码
code1
这份代码没有给p赋值,p数组仍然是0,把他读到cache中,然后flush,结果!不报错!
#include<stdio.h> #include<stdint.h> #ifdef _MSC_VER #include<intrin.h>/* for rdtscp and clflush */ #pragma optimize("gt",on) #else #include<x86intrin.h>/* for rdtscp and clflush */ #endif
int p[64 * 10 + 1];
intmain(){ int a = p[0], b = p[64]; for(int i = 0; i < 2; i++) _mm_clflush(&p[i * 64]); }
code2
这份代码对p[0] flush了两次,第二次flush时,p[0]不在cache中,结果!报错!
#include<stdio.h> #include<stdint.h> #ifdef _MSC_VER #include<intrin.h>/* for rdtscp and clflush */ #pragma optimize("gt",on) #else #include<x86intrin.h>/* for rdtscp and clflush */ #endif
int p[64 * 10 + 1];
intmain(){ int a = p[0], b = p[64]; for(int i = 0; i < 2; i++) _mm_clflush(&p[i * 64]); _mm_clflush(&p[0]); }