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
ODIR=src/.obj
CFLAGS=-I$(IDIR) -O3 #-ggdb
CFLAGS=-I$(IDIR) #-ggdb
# CXX=g++
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 <fcntl.h>
#include <inttypes.h>
#include <sched.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <vector>
#include <set>
#include <functional>
#include <algorithm>
#include <bitset>
#include <functional>
#include <set>
#include <vector>
#include "rev-mc.h"
#define BOOL_XOR(a, b) ((a) != (b))
#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 SET_SIZE 40 // elements per set
@ -29,11 +29,14 @@
#define BITSET_SIZE 256 // bitset used to exploit bitwise operations
#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, ...) \
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;
@ -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);
//-------------------------------------------
#pragma push_options
#pragma optimize("O0")
static std::vector<uint64_t> time_vals;
uint64_t time_tuple(volatile char *a1, volatile char *a2, size_t rounds) {
// uint64_t* time_vals = (uint64_t*) calloc(rounds, sizeof(uint64_t));
if (rounds > time_vals.size())
time_vals.resize(rounds);
uint64_t t0;
sched_yield();
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();
clflush(a1);
clflush(a2);
}
uint64_t mdn = median(time_vals.data(), rounds);
// free(time_vals);
return mdn;
}
#pragma pop_options
//----------------------------------------------------------
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);
}
//----------------------------------------------------------
uint64_t get_pfn(uint64_t entry) {
return ((entry) & 0x3fffffffffffff);
return (char *)ALIGN_TO((uint64_t)base, (uint64_t)align) +
ALIGN_TO(rand() % m_size, (uint64_t)align);
}
//----------------------------------------------------------
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 offset = (v_addr / 4096) * sizeof(entry);
uint64_t pfn;
@ -97,19 +98,15 @@ uint64_t get_phys_addr(uint64_t v_addr)
assert(bytes_read == 8);
assert(entry & (1ULL << 63));
pfn = get_pfn(entry);
assert(pfn != 0);
assert(pfn != 0 && "pfn is zero !!!!!");
return (pfn * 4096) | (v_addr & 4095);
}
//----------------------------------------------------------
addr_tuple gen_addr_tuple(char *v_addr) {
return (addr_tuple){v_addr, get_phys_addr((uint64_t)v_addr)};
}
//----------------------------------------------------------
// https://www.cs.umd.edu/~gasarch/TOPICS/factoring/fastgauss.pdf
// 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++) {
mtx_t[r][c] = BOOL_XOR(mtx_t[r][c], mtx_t[r][pvt_col]);
}
}
break;
}
@ -169,11 +165,8 @@ std::vector<uint64_t> reduce_masks(std::vector<uint64_t> masks) {
}
return filtered_masks;
}
//----------------------------------------------------------
// from https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
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));
}
//----------------------------------------------------------
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;
verbose_printerr("~~~~~~~~~~ Candidate functions ~~~~~~~~~~\n");
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));
fn_mask <<= CL_SHIFT;
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);
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);
if (flags & F_VERBOSE) {
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) {
fprintf(stdout, "0x%lx\n", m);
}
return masks;
}
std::vector<int> find_set_bits(uint64_t val) {
std::vector<int> set_bits;
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;
for (auto fn : fn_masks) {
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.
@TODO still need to figure out which bits are used for the row addressing and which
are from the bank selection. This is currently done manually
@TODO still need to figure out which bits are used for the row addressing and
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));
std::vector<set_t> same_row_sets;
verbose_printerr("~~~~~~~~~~ Looking for row bits ~~~~~~~~~~\n");
for (int i = 0; i < 2; i++) {
verbose_printerr("[LOG] - Set #%d\n", i);
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});
uint64_t cnt = 0;
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)
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)
continue;
verbose_printerr("[LOG] - %lx - %lx\t Time: %ld <== GOTCHA\n", base_addr.p_addr, tmp.p_addr, time);
verbose_printerr("[LOG] - %lx - %lx\t Time: %ld <== GOTCHA\n",
base_addr.p_addr, tmp.p_addr, time);
same_row_sets[i].push_back(tmp);
cnt++;
}
}
uint64_t row_mask = LS_BITMASK(16); // use 16 bits for the row
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) {
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;
}
}
}
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));
}
}
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);
}
//----------------------------------------------------------
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;
@ -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);
while (!found_enough(sets, sets_cnt, SET_SIZE)) {
char *rnd_addr = get_rnd_addr(mem.buffer, mem.size, CL_SHIFT);
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++) {
uint64_t time = 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) {
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) {
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);
found_set = true;
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) {
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);
#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);
fprintf(stderr, "[ LOG ] - Done\n");
#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);
}
// 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) {
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);
}
return (found_sets >= (set_cnt * SET_THRESH)) ? true : false;
}
void filter_sets(std::vector<set_t> &sets, size_t set_size) {
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) {
for (int idx = 0; idx < sets.size(); idx++) {
fprintf(stderr, "[LOG] - Set: %d\tSize: %ld\n", idx, sets[idx].size());
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)
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) {
conflicts += 1;
}
@ -509,4 +507,3 @@ void verify_sets(std::vector<set_t>& sets, uint64_t threshold, size_t rounds) {
}
#endif