2024 release
This commit is contained in:
parent
3e503fa7b2
commit
8544adc054
|
@ -0,0 +1 @@
|
||||||
|
._*
|
|
@ -0,0 +1,3 @@
|
||||||
|
/*.o
|
||||||
|
/sender
|
||||||
|
/receiver
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
#include"util.h"
|
||||||
|
// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// [Bonus] TODO: Put your covert channel setup code here
|
||||||
|
|
||||||
|
printf("Please press enter.\n");
|
||||||
|
|
||||||
|
char text_buf[2];
|
||||||
|
fgets(text_buf, sizeof(text_buf), stdin);
|
||||||
|
|
||||||
|
printf("Receiver now listening.\n");
|
||||||
|
|
||||||
|
bool listening = true;
|
||||||
|
while (listening) {
|
||||||
|
|
||||||
|
// [Bonus] TODO: Put your covert channel code here
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Receiver finished.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
#include"util.h"
|
||||||
|
// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only)
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
// [Bonus] TODO: define your own buffer size
|
||||||
|
#define BUFF_SIZE (1<<21)
|
||||||
|
//#define BUFF_SIZE TODO
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// Allocate a buffer using huge page
|
||||||
|
// See the handout for details about hugepage management
|
||||||
|
void *buf= mmap(NULL, BUFF_SIZE, PROT_READ | PROT_WRITE, MAP_POPULATE |
|
||||||
|
MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -1, 0);
|
||||||
|
|
||||||
|
if (buf == (void*) - 1) {
|
||||||
|
perror("mmap() error\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
// The first access to a page triggers overhead associated with
|
||||||
|
// page allocation, TLB insertion, etc.
|
||||||
|
// Thus, we use a dummy write here to trigger page allocation
|
||||||
|
// so later access will not suffer from such overhead.
|
||||||
|
*((char *)buf) = 1; // dummy write to trigger page allocation
|
||||||
|
|
||||||
|
|
||||||
|
// [Bonus] TODO:
|
||||||
|
// Put your covert channel setup code here
|
||||||
|
|
||||||
|
printf("Please type a message.\n");
|
||||||
|
|
||||||
|
bool sending = true;
|
||||||
|
while (sending) {
|
||||||
|
char text_buf[128];
|
||||||
|
fgets(text_buf, sizeof(text_buf), stdin);
|
||||||
|
|
||||||
|
// [Bonus] TODO:
|
||||||
|
// Put your covert channel code here
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Sender finished.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/* Measure the time it takes to access a block with virtual address addr. */
|
||||||
|
CYCLES measure_one_block_access_time(ADDR_PTR addr)
|
||||||
|
{
|
||||||
|
CYCLES cycles;
|
||||||
|
|
||||||
|
asm volatile("mov %1, %%r8\n\t"
|
||||||
|
"lfence\n\t"
|
||||||
|
"rdtsc\n\t"
|
||||||
|
"mov %%eax, %%edi\n\t"
|
||||||
|
"mov (%%r8), %%r8\n\t"
|
||||||
|
"lfence\n\t"
|
||||||
|
"rdtsc\n\t"
|
||||||
|
"sub %%edi, %%eax\n\t"
|
||||||
|
: "=a"(cycles) /*output*/
|
||||||
|
: "r"(addr)
|
||||||
|
: "r8", "edi");
|
||||||
|
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CLFlushes the given address.
|
||||||
|
*
|
||||||
|
* Note: clflush is provided to help you debug and should not be used in your
|
||||||
|
* final submission
|
||||||
|
*/
|
||||||
|
void clflush(ADDR_PTR addr)
|
||||||
|
{
|
||||||
|
asm volatile ("clflush (%0)"::"r"(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Converts a string to its binary representation.
|
||||||
|
*/
|
||||||
|
char *string_to_binary(char *s)
|
||||||
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
return 0; /* no input string */
|
||||||
|
|
||||||
|
size_t len = strlen(s);
|
||||||
|
|
||||||
|
// Each char is one byte (8 bits) and + 1 at the end for null terminator
|
||||||
|
char *binary = malloc(len * 8 + 1);
|
||||||
|
binary[len] = '\0';
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
char ch = s[i];
|
||||||
|
for (int j = 7; j >= 0; --j)
|
||||||
|
{
|
||||||
|
if (ch & (1 << j))
|
||||||
|
{
|
||||||
|
strcat(binary, "1");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcat(binary, "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return binary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Converts a binary string to its ASCII representation.
|
||||||
|
*/
|
||||||
|
char *binary_to_string(char *data)
|
||||||
|
{
|
||||||
|
// Each char is 8 bits
|
||||||
|
size_t msg_len = strlen(data) / 8;
|
||||||
|
|
||||||
|
// Add one for null terminator at the end
|
||||||
|
char *msg = malloc(msg_len + 1);
|
||||||
|
msg[msg_len] = '\0';
|
||||||
|
|
||||||
|
for (int i = 0; i < msg_len; i++)
|
||||||
|
{
|
||||||
|
char tmp[8];
|
||||||
|
int k = 0;
|
||||||
|
|
||||||
|
for (int j = i * 8; j < ((i + 1) * 8); j++)
|
||||||
|
{
|
||||||
|
tmp[k++] = data[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
msg[i] = strtol(tmp, 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Converts a string to integer
|
||||||
|
*/
|
||||||
|
int string_to_int(char* s)
|
||||||
|
{
|
||||||
|
return atoi(s);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
/main
|
||||||
|
/main-visual
|
||||||
|
/data
|
|
@ -1,16 +1,19 @@
|
||||||
include ../cpu.mk
|
include ../cpu.mk
|
||||||
|
|
||||||
all: main
|
all: main main-visual
|
||||||
|
|
||||||
run: main
|
run: main
|
||||||
@taskset -c $(SENDER_CPU) ./main
|
@taskset -c $(SENDER_CPU) ./main
|
||||||
|
|
||||||
run-reference: reference
|
run-visual: main-visual
|
||||||
@taskset -c $(SENDER_CPU) ./reference
|
@taskset -c $(SENDER_CPU) ./main-visual
|
||||||
|
|
||||||
main: main.c Makefile
|
main: main.c Makefile
|
||||||
@gcc main.c -o main
|
@gcc main.c -o main
|
||||||
|
|
||||||
|
main-visual: main.c Makefile
|
||||||
|
@gcc main.c -DVISUAL -o main-visual
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
// TODO: Uncomment the following lines and fill in the correct size
|
#ifndef VISUAL
|
||||||
//#define L1_SIZE [TODO]
|
#define PRINT_FUNC print_results_plaintext
|
||||||
//#define L2_SIZE [TODO]
|
#else
|
||||||
//#define L3_SIZE [TODO]
|
#define PRINT_FUNC print_results_for_visualization
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LINE_SIZE 64
|
||||||
|
// [1.2] TODO: Uncomment the following lines and fill in the correct size
|
||||||
|
//#define L1_SIZE TODO
|
||||||
|
//#define L2_SIZE TODO
|
||||||
|
//#define L3_SIZE TODO
|
||||||
|
//#define BUFF_SIZE TODO
|
||||||
|
|
||||||
int main (int ac, char **av) {
|
int main (int ac, char **av) {
|
||||||
|
|
||||||
|
@ -15,14 +23,12 @@ int main (int ac, char **av) {
|
||||||
uint64_t l3_latency[SAMPLES] = {0};
|
uint64_t l3_latency[SAMPLES] = {0};
|
||||||
|
|
||||||
// A temporary variable we can use to load addresses
|
// A temporary variable we can use to load addresses
|
||||||
// The volatile keyword tells the compiler to not put this variable into a
|
uint8_t tmp;
|
||||||
// register- it should always try to load from memory/ cache.
|
|
||||||
volatile char tmp;
|
|
||||||
|
|
||||||
// Allocate a buffer of 64 Bytes
|
// Allocate a buffer of LINE_SIZE Bytes
|
||||||
// the size of an unsigned integer (uint64_t) is 8 Bytes
|
// The volatile keyword tells the compiler to not put this variable into a
|
||||||
// Therefore, we request 8 * 8 Bytes
|
// register -- it should always try to be loaded from memory / cache.
|
||||||
uint64_t *target_buffer = (uint64_t *)malloc(8*sizeof(uint64_t));
|
volatile uint8_t *target_buffer = (uint8_t *)malloc(LINE_SIZE);
|
||||||
|
|
||||||
if (NULL == target_buffer) {
|
if (NULL == target_buffer) {
|
||||||
perror("Unable to malloc");
|
perror("Unable to malloc");
|
||||||
|
@ -31,11 +37,12 @@ int main (int ac, char **av) {
|
||||||
|
|
||||||
// [1.2] TODO: Uncomment the following line to allocate a buffer of a size
|
// [1.2] TODO: Uncomment the following line to allocate a buffer of a size
|
||||||
// of your chosing. This will help you measure the latencies at L2 and L3.
|
// of your chosing. This will help you measure the latencies at L2 and L3.
|
||||||
//uint64_t *eviction_buffer = (uint64_t)malloc(TODO);
|
//volatile uint8_t *eviction_buffer = (uint8_t *)malloc(BUFF_SIZE);
|
||||||
|
|
||||||
// Example: Measure L1 access latency, store results in l1_latency array
|
// Example: Measure L1 access latency, store results in l1_latency array
|
||||||
for (int i=0; i<SAMPLES; i++){
|
for (int i=0; i<SAMPLES; i++){
|
||||||
// Step 1: bring the target cache line into L1 by simply accessing the line
|
// Step 1: bring the target cache line into L1 by simply accessing
|
||||||
|
// the line
|
||||||
tmp = target_buffer[0];
|
tmp = target_buffer[0];
|
||||||
|
|
||||||
// Step 2: measure the access latency
|
// Step 2: measure the access latency
|
||||||
|
@ -59,14 +66,17 @@ int main (int ac, char **av) {
|
||||||
|
|
||||||
|
|
||||||
// Print the results to the screen
|
// Print the results to the screen
|
||||||
// [1.5] Change print_results to print_results_for_python so that your code will work
|
// When compile to main and used by `make run`,
|
||||||
// with the python plotter software
|
// it uses print_results_plaintext
|
||||||
print_results(dram_latency, l1_latency, l2_latency, l3_latency);
|
// When compile to main-visual and used by `run.py`,
|
||||||
|
// it uses print_results_for_visualization
|
||||||
|
PRINT_FUNC(dram_latency, l1_latency, l2_latency, l3_latency);
|
||||||
|
|
||||||
free(target_buffer);
|
free((uint8_t *)target_buffer);
|
||||||
|
|
||||||
// [1.2] TODO: Uncomment this line once you uncomment the eviction_buffer creation line
|
// [1.2] TODO: Uncomment this line once you uncomment the eviction_buffer
|
||||||
//free(eviction_buffer);
|
// creation line
|
||||||
|
//free((uint8_t *)eviction_buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -7,11 +7,8 @@ from tqdm import tqdm
|
||||||
|
|
||||||
|
|
||||||
# Run your code:
|
# Run your code:
|
||||||
# Make sure that your code is using print_results_for_python
|
# Make sure that your code is using print_results_for_visualization
|
||||||
#executable_filename = ['make', 'run']
|
executable_filename = ['make', 'run-visual']
|
||||||
|
|
||||||
# Run reference code:
|
|
||||||
executable_filename = ['make', 'run-reference']
|
|
||||||
|
|
||||||
num_runs = 100
|
num_runs = 100
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
// Function to read the time stamp counter, which is called tsc for short
|
// Function to read the time stamp counter, which is called tsc for short
|
||||||
// "rdtscpp" returns a 32bit unsigned integer
|
// "rdtscpp" returns a 32bit unsigned integer
|
||||||
// "rdtscpp64" return a 64 bit unsigned integer
|
// "rdtscpp64" return a 64 bit unsigned integer
|
||||||
// Details in https://www.felixcloutier.com/x86/rdtscpp
|
// Details in https://www.felixcloutier.com/x86/rdtscp
|
||||||
static inline uint32_t rdtscpp() {
|
static inline uint32_t rdtscpp() {
|
||||||
uint32_t rv;
|
uint32_t rv;
|
||||||
asm volatile ("rdtscpp": "=a" (rv) :: "edx", "ecx");
|
asm volatile ("rdtscpp": "=a" (rv) :: "edx", "ecx");
|
||||||
|
@ -98,7 +98,7 @@ int compare(const void *p1, const void *p2) {
|
||||||
|
|
||||||
|
|
||||||
// Print out the latencies you measured
|
// Print out the latencies you measured
|
||||||
void print_results(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3) {
|
void print_results_plaintext(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3) {
|
||||||
qsort(dram, SAMPLES, sizeof(uint64_t), compare);
|
qsort(dram, SAMPLES, sizeof(uint64_t), compare);
|
||||||
qsort(l1, SAMPLES, sizeof(uint64_t), compare);
|
qsort(l1, SAMPLES, sizeof(uint64_t), compare);
|
||||||
qsort(l2, SAMPLES, sizeof(uint64_t), compare);
|
qsort(l2, SAMPLES, sizeof(uint64_t), compare);
|
||||||
|
@ -120,7 +120,7 @@ void print_results(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the latencies for part 1.5
|
// Format the latencies for part 1.5
|
||||||
void print_results_for_python(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3)
|
void print_results_for_visualization(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3)
|
||||||
{
|
{
|
||||||
qsort(dram, SAMPLES, sizeof(uint64_t), compare);
|
qsort(dram, SAMPLES, sizeof(uint64_t), compare);
|
||||||
qsort(l1, SAMPLES, sizeof(uint64_t), compare);
|
qsort(l1, SAMPLES, sizeof(uint64_t), compare);
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
|
|
||||||
#include"util.h"
|
|
||||||
// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only)
|
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
// Put your covert channel setup code here
|
|
||||||
|
|
||||||
printf("Please press enter.\n");
|
|
||||||
|
|
||||||
char text_buf[2];
|
|
||||||
fgets(text_buf, sizeof(text_buf), stdin);
|
|
||||||
|
|
||||||
printf("Receiver now listening.\n");
|
|
||||||
|
|
||||||
bool listening = true;
|
|
||||||
while (listening) {
|
|
||||||
|
|
||||||
// Put your covert channel code here
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Receiver finished.\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
|
|
||||||
#include"util.h"
|
|
||||||
// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only)
|
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
// TODO: define your own buffer size
|
|
||||||
#define BUFF_SIZE (1<<21)
|
|
||||||
//#define BUFF_SIZE [TODO]
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
// Allocate a buffer using huge page
|
|
||||||
// See the handout for details about hugepage management
|
|
||||||
void *buf= mmap(NULL, BUFF_SIZE, PROT_READ | PROT_WRITE, MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -1, 0);
|
|
||||||
|
|
||||||
if (buf == (void*) - 1) {
|
|
||||||
perror("mmap() error\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
// The first access to a page triggers overhead associated with
|
|
||||||
// page allocation, TLB insertion, etc.
|
|
||||||
// Thus, we use a dummy write here to trigger page allocation
|
|
||||||
// so later access will not suffer from such overhead.
|
|
||||||
//*((char *)buf) = 1; // dummy write to trigger page allocation
|
|
||||||
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// Put your covert channel setup code here
|
|
||||||
|
|
||||||
printf("Please type a message.\n");
|
|
||||||
|
|
||||||
bool sending = true;
|
|
||||||
while (sending) {
|
|
||||||
char text_buf[128];
|
|
||||||
fgets(text_buf, sizeof(text_buf), stdin);
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// Put your covert channel code here
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Sender finished.\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
/* Measure the time it takes to access a block with virtual address addr. */
|
|
||||||
CYCLES measure_one_block_access_time(ADDR_PTR addr)
|
|
||||||
{
|
|
||||||
CYCLES cycles;
|
|
||||||
|
|
||||||
asm volatile("mov %1, %%r8\n\t"
|
|
||||||
"lfence\n\t"
|
|
||||||
"rdtsc\n\t"
|
|
||||||
"mov %%eax, %%edi\n\t"
|
|
||||||
"mov (%%r8), %%r8\n\t"
|
|
||||||
"lfence\n\t"
|
|
||||||
"rdtsc\n\t"
|
|
||||||
"sub %%edi, %%eax\n\t"
|
|
||||||
: "=a"(cycles) /*output*/
|
|
||||||
: "r"(addr)
|
|
||||||
: "r8", "edi");
|
|
||||||
|
|
||||||
return cycles;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CLFlushes the given address.
|
|
||||||
*
|
|
||||||
* Note: clflush is provided to help you debug and should not be used in your
|
|
||||||
* final submission
|
|
||||||
*/
|
|
||||||
void clflush(ADDR_PTR addr)
|
|
||||||
{
|
|
||||||
asm volatile ("clflush (%0)"::"r"(addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Converts a string to its binary representation.
|
|
||||||
*/
|
|
||||||
char *string_to_binary(char *s)
|
|
||||||
{
|
|
||||||
if (s == NULL)
|
|
||||||
return 0; /* no input string */
|
|
||||||
|
|
||||||
size_t len = strlen(s);
|
|
||||||
|
|
||||||
// Each char is one byte (8 bits) and + 1 at the end for null terminator
|
|
||||||
char *binary = malloc(len * 8 + 1);
|
|
||||||
binary[len] = '\0';
|
|
||||||
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
char ch = s[i];
|
|
||||||
for (int j = 7; j >= 0; --j)
|
|
||||||
{
|
|
||||||
if (ch & (1 << j))
|
|
||||||
{
|
|
||||||
strcat(binary, "1");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
strcat(binary, "0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return binary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Converts a binary string to its ASCII representation.
|
|
||||||
*/
|
|
||||||
char *binary_to_string(char *data)
|
|
||||||
{
|
|
||||||
// Each char is 8 bits
|
|
||||||
size_t msg_len = strlen(data) / 8;
|
|
||||||
|
|
||||||
// Add one for null terminator at the end
|
|
||||||
char *msg = malloc(msg_len + 1);
|
|
||||||
msg[msg_len] = '\0';
|
|
||||||
|
|
||||||
for (int i = 0; i < msg_len; i++)
|
|
||||||
{
|
|
||||||
char tmp[8];
|
|
||||||
int k = 0;
|
|
||||||
|
|
||||||
for (int j = i * 8; j < ((i + 1) * 8); j++)
|
|
||||||
{
|
|
||||||
tmp[k++] = data[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
msg[i] = strtol(tmp, 0, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Converts a string to integer
|
|
||||||
*/
|
|
||||||
int string_to_int(char* s)
|
|
||||||
{
|
|
||||||
return atoi(s);
|
|
||||||
}
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
/shared_file
|
||||||
|
/*.o
|
||||||
|
/attacker
|
|
@ -0,0 +1,26 @@
|
||||||
|
include ../cpu.mk
|
||||||
|
|
||||||
|
TARGETS=attacker
|
||||||
|
UTILS=util.o
|
||||||
|
|
||||||
|
all: $(TARGETS)
|
||||||
|
|
||||||
|
$(UTILS): %.o: %.c %.h
|
||||||
|
$(CC) $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
%.o: %.c util.h
|
||||||
|
$(CC) $(CFLAGS) -c $<
|
||||||
|
|
||||||
|
$(TARGETS): %:%.o util.o
|
||||||
|
$(CC) $(CFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
run_victim:
|
||||||
|
taskset -c $(SENDER_CPU) ./victim
|
||||||
|
|
||||||
|
run_attacker: attacker
|
||||||
|
taskset -c $(RECEIVER_CPU) ./attacker
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) *.o $(HELPERS) $(TARGETS)
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int flag = -1;
|
||||||
|
|
||||||
|
// buf is shared between the attacker and the victim
|
||||||
|
char *buf = allocate_shared_buffer();
|
||||||
|
|
||||||
|
// [2.1] TODO: Put your capture-the-flag code here
|
||||||
|
|
||||||
|
printf("Flag: %d\n", flag);
|
||||||
|
|
||||||
|
deallocate_shared_buffer(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
out_path = Path("shared_file")
|
||||||
|
with out_path.open(mode="wb"):
|
||||||
|
out_path.write_bytes(bytearray([0] * 1024 * 128))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -0,0 +1,98 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/* Measure the time it takes to access a block with virtual address addr. */
|
||||||
|
CYCLES measure_one_block_access_time(ADDR_PTR addr)
|
||||||
|
{
|
||||||
|
CYCLES cycles;
|
||||||
|
|
||||||
|
asm volatile("mov %1, %%r8\n\t"
|
||||||
|
"lfence\n\t"
|
||||||
|
"rdtsc\n\t"
|
||||||
|
"mov %%eax, %%edi\n\t"
|
||||||
|
"mov (%%r8), %%r8\n\t"
|
||||||
|
"lfence\n\t"
|
||||||
|
"rdtsc\n\t"
|
||||||
|
"sub %%edi, %%eax\n\t"
|
||||||
|
: "=a"(cycles) /*output*/
|
||||||
|
: "r"(addr)
|
||||||
|
: "r8", "edi");
|
||||||
|
|
||||||
|
return cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CLFlushes the given address.
|
||||||
|
*
|
||||||
|
* Note: clflush is provided to help you debug and should not be used in your
|
||||||
|
* final submission
|
||||||
|
*/
|
||||||
|
void clflush(ADDR_PTR addr)
|
||||||
|
{
|
||||||
|
asm volatile ("clflush (%0)"::"r"(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
size_t file_size;
|
||||||
|
|
||||||
|
char *allocate_shared_buffer() {
|
||||||
|
const char *filepath = "shared_file";
|
||||||
|
|
||||||
|
int fd = open(filepath, O_RDONLY, (mode_t)0600);
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
perror("Error opening file for writing, please run `python3 gen_file.py` to get the file for shared buf");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat fileInfo = {0};
|
||||||
|
|
||||||
|
if (fstat(fd, &fileInfo) == -1)
|
||||||
|
{
|
||||||
|
perror("Error getting the file size");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileInfo.st_size == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: File is empty, nothing to do\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileInfo.st_size < SEC_RANGE * ALIGN) {
|
||||||
|
close(fd);
|
||||||
|
perror("File is too small\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *buf = mmap(0, fileInfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
if (buf == MAP_FAILED)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
perror("Error mmapping the file");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
file_size = fileInfo.st_size;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate_shared_buffer(char *buf) {
|
||||||
|
// Don't forget to free the mmapped memory
|
||||||
|
if (munmap(buf, file_size) == -1)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
perror("Error un-mmapping the file");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Un-mmaping doesn't close the file, so we still need to do that.
|
||||||
|
close(fd);
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
// You may only use fgets() to pull input from stdin
|
||||||
|
// You may use any print function to stdout to print
|
||||||
|
// out chat messages
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// You may use memory allocators and helper functions
|
||||||
|
// (e.g., rand()). You may not use system().
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifndef UTIL_H_
|
||||||
|
#define UTIL_H_
|
||||||
|
|
||||||
|
#define SEC_RANGE 1024
|
||||||
|
#define ALIGN 128
|
||||||
|
|
||||||
|
#define ADDR_PTR uint64_t
|
||||||
|
#define CYCLES uint32_t
|
||||||
|
|
||||||
|
CYCLES measure_one_block_access_time(ADDR_PTR addr);
|
||||||
|
|
||||||
|
void clflush(ADDR_PTR addr);
|
||||||
|
|
||||||
|
char *allocate_shared_buffer();
|
||||||
|
void deallocate_shared_buffer(char *buf);
|
||||||
|
|
||||||
|
#endif
|
Binary file not shown.
|
@ -0,0 +1,2 @@
|
||||||
|
/*.o
|
||||||
|
/attacker
|
|
@ -23,6 +23,9 @@ run_victim-3:
|
||||||
run_victim-4:
|
run_victim-4:
|
||||||
taskset -c $(SENDER_CPU) ./victim-4
|
taskset -c $(SENDER_CPU) ./victim-4
|
||||||
|
|
||||||
|
run_victim-16:
|
||||||
|
taskset -c $(SENDER_CPU) ./victim-16
|
||||||
|
|
||||||
run_attacker: attacker
|
run_attacker: attacker
|
||||||
taskset -c $(RECEIVER_CPU) ./attacker
|
taskset -c $(RECEIVER_CPU) ./attacker
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
int main(int argc, char const *argv[]) {
|
int main(int argc, char const *argv[]) {
|
||||||
int flag = -1;
|
int flag = -1;
|
||||||
|
|
||||||
// Put your capture-the-flag code here
|
// [3.2] TODO: Put your capture-the-flag code here
|
||||||
|
|
||||||
printf("Flag: %d\n", flag);
|
printf("Flag: %d\n", flag);
|
||||||
return 0;
|
return 0;
|
Binary file not shown.
|
@ -4,6 +4,6 @@ This repository contains all the starting code you will need for the lab.
|
||||||
|
|
||||||
## Starting the Lab
|
## Starting the Lab
|
||||||
|
|
||||||
As stated on the lab handout, you must first change the `SENDER_CPU` and `RECEIVER_CPU` variables in the Makefile to your assigned CPUs. These will be emailed to you along with your lab machine password when the lab is released. **Double check that you have set these values correctly.**
|
As stated on the lab handout, you must first change the `SENDER_CPU` and `RECEIVER_CPU` variables in the `cpu.mk` to your assigned CPUs. **Double check that you have set these values correctly.**
|
||||||
|
|
||||||
After completing these steps, you are now ready to start the lab. Good luck!
|
After completing these steps, you are now ready to start the lab. Good luck!
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
## 1-1
|
||||||
|
|
||||||
|
**Fill in the blanks in the following table using the information you gathered about the cache configuration of the lab machine.**
|
||||||
|
|
||||||
|
| Cache | Cache Line Size | Total Size | Associativity | Number of Sets | Raw Latency |
|
||||||
|
| ----- | --------------- | ---------- | ------------- | -------------- | ----------- |
|
||||||
|
| L1-D | 64 | | | | |
|
||||||
|
| L2 | | | | | |
|
||||||
|
| L3 | | | | | |
|
||||||
|
|
||||||
|
## 1-3
|
||||||
|
|
||||||
|
**After completing your code, generate the histogram pdf file and include it in the lab report.**
|
||||||
|
|
||||||
|
<!-- ![Histogram](./Part1-Timing/Histogram.pdf) -->
|
||||||
|
|
||||||
|
## 1-4
|
||||||
|
|
||||||
|
**Based on the generated histogram, report two thresholds, one to distinguish between L2 and L3 latency and the other to distinguish between L3 and DRAM latency.**
|
||||||
|
|
||||||
|
L2-L3 threshold:
|
||||||
|
|
||||||
|
L3-DRAM threshold:
|
||||||
|
|
||||||
|
## 2-2
|
||||||
|
|
||||||
|
**If the victim want to read the kth byte of a file, where k is a secret, how can he/she avoid leaking the secret to the attacker?**
|
||||||
|
|
||||||
|
## 3-1
|
||||||
|
|
||||||
|
**Given a 64-bit virtual address, fill in the table below.**
|
||||||
|
|
||||||
|
| Page Size | 4KB | 2MB |
|
||||||
|
| ------------------------------------- | ------- | ------- |
|
||||||
|
| Page Offset Bits | | |
|
||||||
|
| Page Number Bits | | |
|
||||||
|
| L2 Set Index Bits | | |
|
||||||
|
| L2 Set Index Bits Fully Under Control | | |
|
48
update.sh
48
update.sh
|
@ -1,48 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
# Updates repository to latest starter code
|
|
||||||
#
|
|
||||||
# Adapted from Oliver Beckstein's ASU-CompMethodsPhysics-PHY494 course 2016-2020 placed into the public domain
|
|
||||||
|
|
||||||
# With GitHub template repositories one needs to use --allow-unrelated-histories
|
|
||||||
# at least once. https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template
|
|
||||||
|
|
||||||
progname="$0"
|
|
||||||
REMOTE_NAME="startercode"
|
|
||||||
REMOTE_URL="https://github.com/CSAIL-Arch-Sec/SHD-CacheAttackLab.git"
|
|
||||||
|
|
||||||
# progname, from top dir
|
|
||||||
UPDATESH="./deploy/$(basename $progname)"
|
|
||||||
|
|
||||||
CONTACT_MESSAGE="Contact the instructor and TA with a screen shot of ALL output from running $0."
|
|
||||||
|
|
||||||
function die () {
|
|
||||||
local msg="$1" err=${2:-1}
|
|
||||||
echo "ERROR: ${msg}."
|
|
||||||
exit $err
|
|
||||||
}
|
|
||||||
|
|
||||||
# ensure everything relative to top dir
|
|
||||||
topdir="$(git rev-parse --show-toplevel)" || die "Failed to get rootdir"
|
|
||||||
cd "${topdir}" || die "Failed to get to the git root dir ${rootdir}"
|
|
||||||
|
|
||||||
|
|
||||||
# first time
|
|
||||||
# 1. set remote repo
|
|
||||||
# 2. merge histories between student (template) and remote skeleton
|
|
||||||
|
|
||||||
if ! git remote get-url ${REMOTE_NAME} >/dev/null 2>&1; then
|
|
||||||
echo "Adding remote repository '${REMOTE_NAME}'."
|
|
||||||
git remote add ${REMOTE_NAME} ${REMOTE_URL}
|
|
||||||
|
|
||||||
echo "Merging histories for the first time..."
|
|
||||||
set -x
|
|
||||||
git pull --allow-unrelated-histories -s recursive -X theirs --no-edit ${REMOTE_NAME} main || \
|
|
||||||
{ git rev-list -1 MERGE_HEAD >/dev/null 2>&1 && git merge --abort ; \
|
|
||||||
git remote rm ${REMOTE_NAME}; \
|
|
||||||
die "Failed to merge histories. ${CONTACT_MESSAGE}" $?; }
|
|
||||||
|
|
||||||
set +x
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "updating repository... git pull from ${REMOTE_NAME}"
|
|
||||||
git pull --no-edit ${REMOTE_NAME} main || die "Failed to pull from ${REMOTE_NAME}. ${CONTACT_MESSAGE}"
|
|
Loading…
Reference in New Issue