feat: add info.

This commit is contained in:
tqcq 2024-10-21 01:33:09 +00:00
parent 686a3664d9
commit b13cd88d57
3 changed files with 378 additions and 377 deletions

4
.gitignore vendored
View File

@ -0,0 +1,4 @@
.cache
compile_commands.json
obj
.obj

View File

@ -4,7 +4,7 @@ LDIR=lib
BUILD=obj BUILD=obj
ODIR=src/.obj ODIR=src/.obj
CFLAGS=-I$(IDIR) -O3 #-ggdb CFLAGS=-I$(IDIR) #-ggdb
# CXX=g++ # CXX=g++
LDFLAGS= LDFLAGS=

View File

@ -1,26 +1,26 @@
#include <stdbool.h>
#include <time.h>
#include <stdlib.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h> #include <assert.h>
#include <fcntl.h>
#include <inttypes.h> #include <inttypes.h>
#include <sched.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <vector>
#include <set>
#include <functional>
#include <algorithm> #include <algorithm>
#include <bitset> #include <bitset>
#include <functional>
#include <set>
#include <vector>
#include "rev-mc.h" #include "rev-mc.h"
#define BOOL_XOR(a, b) ((a) != (b)) #define BOOL_XOR(a, b) ((a) != (b))
#define O_HEADER "base,probe,time\n" #define O_HEADER "base,probe,time\n"
#define ALIGN_TO(X, Y) ((X) & (~((1LL<<(Y))-1LL))) // Mask out the lower Y bits #define ALIGN_TO(X, Y) \
((X) & (~((1LL << (Y)) - 1LL))) // Mask out the lower Y bits
#define LS_BITMASK(X) ((1LL << (X)) - 1LL) // Mask only the lower X bits #define LS_BITMASK(X) ((1LL << (X)) - 1LL) // Mask only the lower X bits
#define SET_SIZE 40 // elements per set #define SET_SIZE 40 // elements per set
@ -29,11 +29,14 @@
#define BITSET_SIZE 256 // bitset used to exploit bitwise operations #define BITSET_SIZE 256 // bitset used to exploit bitwise operations
#define ROW_SET_CNT 5 #define ROW_SET_CNT 5
// from https://stackoverflow.com/questions/1644868/define-macro-for-debug-printing-in-c // from
// https://stackoverflow.com/questions/1644868/define-macro-for-debug-printing-in-c
#define verbose_printerr(fmt, ...) \ #define verbose_printerr(fmt, ...) \
do { if (flags & F_VERBOSE) { fprintf(stderr, fmt, ##__VA_ARGS__); } } while(0) do { \
if (flags & F_VERBOSE) { \
fprintf(stderr, fmt, ##__VA_ARGS__); \
} \
} while (0)
typedef std::vector<addr_tuple> set_t; typedef std::vector<addr_tuple> set_t;
@ -46,11 +49,15 @@ void print_sets(std::vector<set_t> sets);
void verify_sets(std::vector<set_t> &sets, uint64_t threshold, size_t rounds); void verify_sets(std::vector<set_t> &sets, uint64_t threshold, size_t rounds);
//------------------------------------------- //-------------------------------------------
#pragma push_options
#pragma optimize("O0")
static std::vector<uint64_t> time_vals; static std::vector<uint64_t> time_vals;
uint64_t time_tuple(volatile char *a1, volatile char *a2, size_t rounds) { uint64_t time_tuple(volatile char *a1, volatile char *a2, size_t rounds) {
// uint64_t* time_vals = (uint64_t*) calloc(rounds, sizeof(uint64_t)); // uint64_t* time_vals = (uint64_t*) calloc(rounds, sizeof(uint64_t));
if (rounds > time_vals.size())
time_vals.resize(rounds); time_vals.resize(rounds);
uint64_t t0; uint64_t t0;
sched_yield(); sched_yield();
for (size_t i = 0; i < rounds; i++) { for (size_t i = 0; i < rounds; i++) {
@ -62,31 +69,25 @@ uint64_t time_tuple(volatile char* a1, volatile char* a2, size_t rounds) {
lfence(); lfence();
clflush(a1); clflush(a1);
clflush(a2); clflush(a2);
} }
uint64_t mdn = median(time_vals.data(), rounds); uint64_t mdn = median(time_vals.data(), rounds);
// free(time_vals); // free(time_vals);
return mdn; return mdn;
} }
#pragma pop_options
//---------------------------------------------------------- //----------------------------------------------------------
char *get_rnd_addr(char *base, size_t m_size, size_t align) { char *get_rnd_addr(char *base, size_t m_size, size_t align) {
return (char*) ALIGN_TO((uint64_t) base, (uint64_t) align) + ALIGN_TO(rand() % m_size, (uint64_t) align); return (char *)ALIGN_TO((uint64_t)base, (uint64_t)align) +
} ALIGN_TO(rand() % m_size, (uint64_t)align);
//----------------------------------------------------------
uint64_t get_pfn(uint64_t entry) {
return ((entry) & 0x3fffffffffffff);
} }
//---------------------------------------------------------- //----------------------------------------------------------
uint64_t get_phys_addr(uint64_t v_addr) uint64_t get_pfn(uint64_t entry) { return ((entry) & 0x3fffffffffffff); }
{
//----------------------------------------------------------
uint64_t get_phys_addr(uint64_t v_addr) {
uint64_t entry; uint64_t entry;
uint64_t offset = (v_addr / 4096) * sizeof(entry); uint64_t offset = (v_addr / 4096) * sizeof(entry);
uint64_t pfn; uint64_t pfn;
@ -97,19 +98,15 @@ uint64_t get_phys_addr(uint64_t v_addr)
assert(bytes_read == 8); assert(bytes_read == 8);
assert(entry & (1ULL << 63)); assert(entry & (1ULL << 63));
pfn = get_pfn(entry); pfn = get_pfn(entry);
assert(pfn != 0); assert(pfn != 0 && "pfn is zero !!!!!");
return (pfn * 4096) | (v_addr & 4095); return (pfn * 4096) | (v_addr & 4095);
} }
//---------------------------------------------------------- //----------------------------------------------------------
addr_tuple gen_addr_tuple(char *v_addr) { addr_tuple gen_addr_tuple(char *v_addr) {
return (addr_tuple){v_addr, get_phys_addr((uint64_t)v_addr)}; return (addr_tuple){v_addr, get_phys_addr((uint64_t)v_addr)};
} }
//---------------------------------------------------------- //----------------------------------------------------------
// https://www.cs.umd.edu/~gasarch/TOPICS/factoring/fastgauss.pdf // https://www.cs.umd.edu/~gasarch/TOPICS/factoring/fastgauss.pdf
// gaussian elimination in GF2 // gaussian elimination in GF2
@ -160,7 +157,6 @@ std::vector<uint64_t> reduce_masks(std::vector<uint64_t> masks) {
for (size_t r = 0; r < height_t; r++) { for (size_t r = 0; r < height_t; r++) {
mtx_t[r][c] = BOOL_XOR(mtx_t[r][c], mtx_t[r][pvt_col]); mtx_t[r][c] = BOOL_XOR(mtx_t[r][c], mtx_t[r][pvt_col]);
} }
} }
break; break;
} }
@ -169,11 +165,8 @@ std::vector<uint64_t> reduce_masks(std::vector<uint64_t> masks) {
} }
return filtered_masks; return filtered_masks;
} }
//---------------------------------------------------------- //----------------------------------------------------------
// from https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation // from https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
uint64_t next_bit_permutation(uint64_t v) { uint64_t next_bit_permutation(uint64_t v) {
@ -181,16 +174,18 @@ uint64_t next_bit_permutation(uint64_t v) {
return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzl(v) + 1)); return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzl(v) + 1));
} }
//---------------------------------------------------------- //----------------------------------------------------------
std::vector<uint64_t> find_functions(std::vector<set_t> sets, size_t max_fn_bits, size_t msb, uint64_t flags) { std::vector<uint64_t> find_functions(std::vector<set_t> sets,
size_t max_fn_bits, size_t msb,
uint64_t flags) {
std::vector<uint64_t> masks; std::vector<uint64_t> masks;
verbose_printerr("~~~~~~~~~~ Candidate functions ~~~~~~~~~~\n"); verbose_printerr("~~~~~~~~~~ Candidate functions ~~~~~~~~~~\n");
for (size_t bits = 1L; bits <= max_fn_bits; bits++) { for (size_t bits = 1L; bits <= max_fn_bits; bits++) {
uint64_t fn_mask = ((1L<<(bits))-1); // avoid the first 6 bits since they are the cacheline bits uint64_t fn_mask =
((1L << (bits)) -
1); // avoid the first 6 bits since they are the cacheline bits
uint64_t last_mask = (fn_mask << (msb - bits)); uint64_t last_mask = (fn_mask << (msb - bits));
fn_mask <<= CL_SHIFT; fn_mask <<= CL_SHIFT;
verbose_printerr("[ LOG ] - #Bits: %ld \n", bits); verbose_printerr("[ LOG ] - #Bits: %ld \n", bits);
@ -210,7 +205,8 @@ std::vector<uint64_t> find_functions(std::vector<set_t> sets, size_t max_fn_bits
} }
} }
} }
verbose_printerr("\t Candidate: 0x%0lx \t\t bits: %s\n", fn_mask, bit_string(fn_mask)); verbose_printerr("\t Candidate: 0x%0lx \t\t bits: %s\n", fn_mask,
bit_string(fn_mask));
masks.push_back(fn_mask); masks.push_back(fn_mask);
next_mask: next_mask:
@ -221,17 +217,16 @@ std::vector<uint64_t> find_functions(std::vector<set_t> sets, size_t max_fn_bits
masks = reduce_masks(masks); masks = reduce_masks(masks);
if (flags & F_VERBOSE) { if (flags & F_VERBOSE) {
for (auto m : masks) { for (auto m : masks) {
fprintf(stderr, "\t Valid Function: 0x%0lx \t\t bits: %s\n", m, bit_string(m)); fprintf(stderr, "\t Valid Function: 0x%0lx \t\t bits: %s\n", m,
bit_string(m));
} }
} }
for (auto m : masks) { for (auto m : masks) {
fprintf(stdout, "0x%lx\n", m); fprintf(stdout, "0x%lx\n", m);
} }
return masks; return masks;
} }
std::vector<int> find_set_bits(uint64_t val) { std::vector<int> find_set_bits(uint64_t val) {
std::vector<int> set_bits; std::vector<int> set_bits;
for (int i = 0; i < 64; i++) { for (int i = 0; i < 64; i++) {
@ -244,7 +239,8 @@ std::vector<int> find_set_bits(uint64_t val) {
} }
//---------------------------------------------------------- //----------------------------------------------------------
std::vector<uint8_t> get_dram_fn(uint64_t addr, std::vector<uint64_t> fn_masks) { std::vector<uint8_t> get_dram_fn(uint64_t addr,
std::vector<uint64_t> fn_masks) {
std::vector<uint8_t> addr_dram; std::vector<uint8_t> addr_dram;
for (auto fn : fn_masks) { for (auto fn : fn_masks) {
addr_dram.push_back(__builtin_parityl(addr & fn)); addr_dram.push_back(__builtin_parityl(addr & fn));
@ -255,23 +251,22 @@ std::vector<uint8_t> get_dram_fn(uint64_t addr, std::vector<uint64_t> fn_masks)
//---------------------------------------------------------- //----------------------------------------------------------
/* /*
It currently finds some of the interesting bits for the row addressing. It currently finds some of the interesting bits for the row addressing.
@TODO still need to figure out which bits are used for the row addressing and which @TODO still need to figure out which bits are used for the row addressing and
are from the bank selection. This is currently done manually which are from the bank selection. This is currently done manually
*/ */
uint64_t find_row_mask(std::vector<set_t>& sets, std::vector<uint64_t> fn_masks, mem_buff_t mem, uint64_t threshold, uint64_t flags) { uint64_t find_row_mask(std::vector<set_t> &sets, std::vector<uint64_t> fn_masks,
mem_buff_t mem, uint64_t threshold, uint64_t flags) {
addr_tuple base_addr = gen_addr_tuple(get_rnd_addr(mem.buffer, mem.size, 0)); addr_tuple base_addr = gen_addr_tuple(get_rnd_addr(mem.buffer, mem.size, 0));
std::vector<set_t> same_row_sets; std::vector<set_t> same_row_sets;
verbose_printerr("~~~~~~~~~~ Looking for row bits ~~~~~~~~~~\n"); verbose_printerr("~~~~~~~~~~ Looking for row bits ~~~~~~~~~~\n");
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
verbose_printerr("[LOG] - Set #%d\n", i); verbose_printerr("[LOG] - Set #%d\n", i);
addr_tuple base_addr = sets[i][0]; addr_tuple base_addr = sets[i][0];
std::vector<uint8_t> base_dram = get_dram_fn((uint64_t)base_addr.p_addr, fn_masks); std::vector<uint8_t> base_dram =
get_dram_fn((uint64_t)base_addr.p_addr, fn_masks);
same_row_sets.push_back({base_addr}); same_row_sets.push_back({base_addr});
uint64_t cnt = 0; uint64_t cnt = 0;
while (cnt < ROW_SET_CNT) { while (cnt < ROW_SET_CNT) {
@ -280,25 +275,24 @@ uint64_t find_row_mask(std::vector<set_t>& sets, std::vector<uint64_t> fn_masks,
if (get_dram_fn((uint64_t)tmp.p_addr, fn_masks) != base_dram) if (get_dram_fn((uint64_t)tmp.p_addr, fn_masks) != base_dram)
continue; continue;
uint64_t time = time_tuple((volatile char*)base_addr.v_addr, (volatile char*)tmp.v_addr, 1000); uint64_t time = time_tuple((volatile char *)base_addr.v_addr,
(volatile char *)tmp.v_addr, 1000);
if (time > threshold) if (time > threshold)
continue; continue;
verbose_printerr("[LOG] - %lx - %lx\t Time: %ld <== GOTCHA\n",
verbose_printerr("[LOG] - %lx - %lx\t Time: %ld <== GOTCHA\n", base_addr.p_addr, tmp.p_addr, time); base_addr.p_addr, tmp.p_addr, time);
same_row_sets[i].push_back(tmp); same_row_sets[i].push_back(tmp);
cnt++; cnt++;
} }
} }
uint64_t row_mask = LS_BITMASK(16); // use 16 bits for the row uint64_t row_mask = LS_BITMASK(16); // use 16 bits for the row
uint64_t last_mask = (row_mask << (40 - 16)); uint64_t last_mask = (row_mask << (40 - 16));
row_mask <<= CL_SHIFT; // skip the lowest 6 bits since they're used for CL addressing row_mask <<=
CL_SHIFT; // skip the lowest 6 bits since they're used for CL addressing
while (row_mask < last_mask) { while (row_mask < last_mask) {
if (row_mask & LS_BITMASK(CL_SHIFT)) { if (row_mask & LS_BITMASK(CL_SHIFT)) {
@ -314,7 +308,6 @@ uint64_t find_row_mask(std::vector<set_t>& sets, std::vector<uint64_t> fn_masks,
goto next_mask; goto next_mask;
} }
} }
} }
break; break;
@ -331,14 +324,14 @@ uint64_t find_row_mask(std::vector<set_t>& sets, std::vector<uint64_t> fn_masks,
row_mask ^= (1 << __builtin_ctzl(m)); row_mask ^= (1 << __builtin_ctzl(m));
} }
} }
verbose_printerr("[LOG] - Row mask: 0x%0lx \t\t bits: %s\n", row_mask, bit_string(row_mask)); verbose_printerr("[LOG] - Row mask: 0x%0lx \t\t bits: %s\n", row_mask,
bit_string(row_mask));
printf("0x%lx\n", row_mask); printf("0x%lx\n", row_mask);
} }
//---------------------------------------------------------- //----------------------------------------------------------
void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, char* o_file, uint64_t flags) { void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size,
char *o_file, uint64_t flags) {
time_t t; time_t t;
@ -371,7 +364,6 @@ void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, cha
alloc_buffer(&mem); alloc_buffer(&mem);
while (!found_enough(sets, sets_cnt, SET_SIZE)) { while (!found_enough(sets, sets_cnt, SET_SIZE)) {
char *rnd_addr = get_rnd_addr(mem.buffer, mem.size, CL_SHIFT); char *rnd_addr = get_rnd_addr(mem.buffer, mem.size, CL_SHIFT);
if (is_in(rnd_addr, used_addr)) if (is_in(rnd_addr, used_addr))
@ -385,12 +377,15 @@ void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, cha
for (size_t idx = 0; idx < sets.size(); idx++) { for (size_t idx = 0; idx < sets.size(); idx++) {
uint64_t time = 0; uint64_t time = 0;
addr_tuple tmp = sets[idx][0]; addr_tuple tmp = sets[idx][0];
time = time_tuple((volatile char*) tmp.v_addr, (volatile char*)tp.v_addr, rounds); time = time_tuple((volatile char *)tmp.v_addr, (volatile char *)tp.v_addr,
rounds);
if (flags & F_EXPORT) { if (flags & F_EXPORT) {
dprintf(o_fd, "%lx,%lx,%ld\n",(uint64_t) tp.v_addr, (uint64_t) tmp.v_addr,time); dprintf(o_fd, "%lx,%lx,%ld\n", (uint64_t)tp.v_addr,
(uint64_t)tmp.v_addr, time);
} }
if (time > threshold) { if (time > threshold) {
verbose_printerr("[LOG] - [%ld] Set: %03ld -\t %lx - %lx\t Time: %ld\n", used_addr.size(), idx, tp.p_addr, tmp.p_addr, time); verbose_printerr("[LOG] - [%ld] Set: %03ld -\t %lx - %lx\t Time: %ld\n",
used_addr.size(), idx, tp.p_addr, tmp.p_addr, time);
sets[idx].push_back(tp); sets[idx].push_back(tp);
found_set = true; found_set = true;
break; break;
@ -398,15 +393,17 @@ void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, cha
} }
if (!found_set) { if (!found_set) {
sets.push_back({tp}); sets.push_back({tp});
verbose_printerr( "[LOG] - Set: %03ld -\t %p <== NEW!!\n", sets.size(), tp.v_addr); verbose_printerr("[LOG] - Set: %03ld -\t %p "
" <== NEW!!\n",
sets.size(), tp.v_addr);
} }
} }
filter_sets(sets, SET_SIZE); filter_sets(sets, SET_SIZE);
#ifdef DEBUG_SETS #ifdef DEBUG_SETS
fprintf(stderr, "[ LOG ] - Cleansing sets. This may take a while... stay put\n"); fprintf(stderr,
"[ LOG ] - Cleansing sets. This may take a while... stay put\n");
verify_sets(sets, threshold, rounds); verify_sets(sets, threshold, rounds);
fprintf(stderr, "[ LOG ] - Done\n"); fprintf(stderr, "[ LOG ] - Done\n");
#endif #endif
@ -421,8 +418,6 @@ void rev_mc(size_t sets_cnt, size_t threshold, size_t rounds, size_t m_size, cha
free_buffer(&mem); free_buffer(&mem);
} }
// Fin. // Fin.
//---------------------------------------------------------- //----------------------------------------------------------
@ -454,14 +449,16 @@ bool found_enough(std::vector<set_t> sets, uint64_t set_cnt, size_t set_size) {
} }
if (found_sets > set_cnt) { if (found_sets > set_cnt) {
fprintf(stderr, "[ERROR] - Found too many sets. Is %ld the correct number of sets?\n", set_cnt); fprintf(
stderr,
"[ERROR] - Found too many sets. Is %ld the correct number of sets?\n",
set_cnt);
exit(1); exit(1);
} }
return (found_sets >= (set_cnt * SET_THRESH)) ? true : false; return (found_sets >= (set_cnt * SET_THRESH)) ? true : false;
} }
void filter_sets(std::vector<set_t> &sets, size_t set_size) { void filter_sets(std::vector<set_t> &sets, size_t set_size) {
for (auto s = sets.begin(); s < sets.end(); s++) { for (auto s = sets.begin(); s < sets.end(); s++) {
@ -472,13 +469,13 @@ void filter_sets(std::vector<set_t>& sets, size_t set_size) {
} }
} }
void print_sets(std::vector<set_t> sets) { void print_sets(std::vector<set_t> sets) {
for (int idx = 0; idx < sets.size(); idx++) { for (int idx = 0; idx < sets.size(); idx++) {
fprintf(stderr, "[LOG] - Set: %d\tSize: %ld\n", idx, sets[idx].size()); fprintf(stderr, "[LOG] - Set: %d\tSize: %ld\n", idx, sets[idx].size());
for (auto tmp : sets[idx]) { for (auto tmp : sets[idx]) {
fprintf(stderr, "\tv_addr:%p - p_addr:%p\n", tmp.v_addr, (void*) tmp.p_addr); fprintf(stderr, "\tv_addr:%p - p_addr:%p\n", tmp.v_addr,
(void *)tmp.p_addr);
} }
} }
} }
@ -495,7 +492,8 @@ void verify_sets(std::vector<set_t>& sets, uint64_t threshold, size_t rounds) {
if (tp_base == tp_probe) if (tp_base == tp_probe)
continue; continue;
uint64_t time = time_tuple((volatile char*) tp_base->v_addr,(volatile char*) tp_probe->v_addr, rounds); uint64_t time = time_tuple((volatile char *)tp_base->v_addr,
(volatile char *)tp_probe->v_addr, rounds);
if (time > threshold) { if (time > threshold) {
conflicts += 1; conflicts += 1;
} }
@ -509,4 +507,3 @@ void verify_sets(std::vector<set_t>& sets, uint64_t threshold, size_t rounds) {
} }
#endif #endif