Initial cache attack lab commit
This commit is contained in:
commit
70fb4e150a
|
@ -0,0 +1,17 @@
|
|||
include ../cpu.mk
|
||||
|
||||
all: main
|
||||
|
||||
run: main
|
||||
@taskset -c $(SENDER_CPU) ./main
|
||||
|
||||
run-reference: reference
|
||||
@taskset -c $(SENDER_CPU) ./reference
|
||||
|
||||
main: main.c Makefile
|
||||
@gcc main.c -o main
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f main
|
|
@ -0,0 +1,49 @@
|
|||
import os
|
||||
import json
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from tqdm import tqdm
|
||||
from datetime import datetime
|
||||
|
||||
num_runs = 100
|
||||
dict_of_dict_of_lists = dict()
|
||||
|
||||
graph_repo="data"
|
||||
os.makedirs(graph_repo, exist_ok=True)
|
||||
|
||||
fancy_num_runs = range(0, num_runs, 1)
|
||||
for run_id in tqdm(fancy_num_runs):
|
||||
filename = graph_repo+"/run"+str(run_id)+".json"
|
||||
with open(filename) as f:
|
||||
dict_of_dict_of_lists[run_id] = json.load(f)
|
||||
|
||||
l1_all = []
|
||||
l2_all = []
|
||||
l3_all = []
|
||||
mem_all = []
|
||||
|
||||
for run_id in tqdm(fancy_num_runs):
|
||||
l1_all += dict_of_dict_of_lists[run_id]['1']
|
||||
l2_all += dict_of_dict_of_lists[run_id]['2']
|
||||
l3_all += dict_of_dict_of_lists[run_id]['3']
|
||||
mem_all += dict_of_dict_of_lists[run_id]['4']
|
||||
|
||||
#
|
||||
# MAX 300
|
||||
#
|
||||
fig_all = plt.figure(figsize=(11.25, 7.5))
|
||||
ax_all = fig_all.add_subplot(1,1,1)
|
||||
ax_all.set_xlabel("Access Time")
|
||||
ax_all.set_ylabel("Number of Samples")
|
||||
|
||||
ax_all.hist(l1_all, label="L1", bins=np.arange(0, 300 ), alpha=0.5)
|
||||
ax_all.hist(l2_all, label="L2", bins=np.arange(0, 300 ), alpha=0.5)
|
||||
ax_all.hist(l3_all, label="L3", bins=np.arange(0, 300 ), alpha=0.5)
|
||||
ax_all.hist(mem_all, label="DRAM", bins=np.arange(0, 300 ), alpha=0.5)
|
||||
fig_all.legend()
|
||||
|
||||
os.makedirs("graphs", exist_ok=True)
|
||||
now = datetime.now()
|
||||
date_time = now.strftime("%m:%d:%Y_%H:%M:%S")
|
||||
fig_all.savefig(str("graphs/"+date_time+".pdf"))
|
||||
plt.close(fig_all)
|
|
@ -0,0 +1,72 @@
|
|||
#include "utility.h"
|
||||
|
||||
// TODO: Uncomment the following lines and fill in the correct size
|
||||
//#define L1_SIZE [TODO]
|
||||
//#define L2_SIZE [TODO]
|
||||
//#define L3_SIZE [TODO]
|
||||
|
||||
int main (int ac, char **av) {
|
||||
|
||||
// create 4 arrays to store the latency numbers
|
||||
// the arrays are initialized to 0
|
||||
uint64_t dram_latency[SAMPLES] = {0};
|
||||
uint64_t l1_latency[SAMPLES] = {0};
|
||||
uint64_t l2_latency[SAMPLES] = {0};
|
||||
uint64_t l3_latency[SAMPLES] = {0};
|
||||
|
||||
// A temporary variable we can use to load addresses
|
||||
// The volatile keyword tells the compiler to not put this variable into a
|
||||
// register- it should always try to load from memory/ cache.
|
||||
volatile char tmp;
|
||||
|
||||
// Allocate a buffer of 64 Bytes
|
||||
// the size of an unsigned integer (uint64_t) is 8 Bytes
|
||||
// Therefore, we request 8 * 8 Bytes
|
||||
uint64_t *target_buffer = (uint64_t *)malloc(8*sizeof(uint64_t));
|
||||
|
||||
if (NULL == target_buffer) {
|
||||
perror("Unable to malloc");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// [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.
|
||||
//uint64_t *eviction_buffer = (uint64_t)malloc(TODO);
|
||||
|
||||
// Example: Measure L1 access latency, store results in l1_latency array
|
||||
for (int i=0; i<SAMPLES; i++){
|
||||
// Step 1: bring the target cache line into L1 by simply accessing the line
|
||||
tmp = target_buffer[0];
|
||||
|
||||
// Step 2: measure the access latency
|
||||
l1_latency[i] = measure_one_block_access_time((uint64_t)target_buffer);
|
||||
}
|
||||
|
||||
// ======
|
||||
// [1.2] TODO: Measure DRAM Latency, store results in dram_latency array
|
||||
// ======
|
||||
//
|
||||
|
||||
// ======
|
||||
// [1.2] TODO: Measure L2 Latency, store results in l2_latency array
|
||||
// ======
|
||||
//
|
||||
|
||||
// ======
|
||||
// [1.2] TODO: Measure L3 Latency, store results in l3_latency array
|
||||
// ======
|
||||
//
|
||||
|
||||
|
||||
// Print the results to the screen
|
||||
// [1.5] Change print_results to print_results_for_python so that your code will work
|
||||
// with the python plotter software
|
||||
print_results(dram_latency, l1_latency, l2_latency, l3_latency);
|
||||
|
||||
free(target_buffer);
|
||||
|
||||
// [1.2] TODO: Uncomment this line once you uncomment the eviction_buffer creation line
|
||||
//free(eviction_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
Binary file not shown.
|
@ -0,0 +1,44 @@
|
|||
import json
|
||||
import os
|
||||
import matplotlib.pyplot as plt
|
||||
import subprocess
|
||||
import csv
|
||||
from tqdm import tqdm
|
||||
|
||||
|
||||
# Run your code:
|
||||
# Make sure that your code is using print_results_for_python
|
||||
#executable_filename = ['make', 'run']
|
||||
|
||||
# Run reference code:
|
||||
executable_filename = ['make', 'run-reference']
|
||||
|
||||
num_runs = 100
|
||||
|
||||
graph_repo = "data"
|
||||
os.makedirs(graph_repo, exist_ok=True)
|
||||
|
||||
fancy_num_runs = range(0, num_runs, 1)
|
||||
for run_id in tqdm(fancy_num_runs):
|
||||
p = subprocess.run(executable_filename,
|
||||
stdout=subprocess.PIPE, universal_newlines=True)
|
||||
|
||||
reader = csv.reader(p.stdout.splitlines())
|
||||
|
||||
dict_of_lists = dict()
|
||||
|
||||
for store_lev in range(1, 4+1, 1):
|
||||
dict_of_lists[store_lev] = []
|
||||
|
||||
store_level = 1
|
||||
for row in reader:
|
||||
temp = row[0].split(' ')[:-1]
|
||||
dict_of_lists[store_level] = list(map(int, temp))
|
||||
store_level+=1
|
||||
|
||||
#print(dict_of_lists)
|
||||
filename = graph_repo+"/run"+str(run_id)+".json"
|
||||
jsonFile = open(filename, "w")
|
||||
jsonFile.write(json.dumps(dict_of_lists))
|
||||
jsonFile.close()
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef __UTILITY_H__
|
||||
#define __UTILITY_H__
|
||||
|
||||
#define SAMPLES 10
|
||||
|
||||
|
||||
// Function to read the time stamp counter, which is called tsc for short
|
||||
// "rdtscpp" returns a 32bit unsigned integer
|
||||
// "rdtscpp64" return a 64 bit unsigned integer
|
||||
// Details in https://www.felixcloutier.com/x86/rdtscpp
|
||||
static inline uint32_t rdtscpp() {
|
||||
uint32_t rv;
|
||||
asm volatile ("rdtscpp": "=a" (rv) :: "edx", "ecx");
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline uint64_t rdtscpp64() {
|
||||
uint32_t low, high;
|
||||
asm volatile ("rdtscpp": "=a" (low), "=d" (high) :: "ecx");
|
||||
return (((uint64_t)high) << 32) | low;
|
||||
}
|
||||
|
||||
// Function "lfence" wrap the assembly instruction lfence
|
||||
// This function performs a serializing operation which ensures that
|
||||
// the instructions after "lfence" start execution after
|
||||
// all the instructions before "lfence" complete
|
||||
// Details in https://www.felixcloutier.com/x86/lfence
|
||||
static inline void lfence() {
|
||||
asm volatile("lfence");
|
||||
}
|
||||
|
||||
// Here is an example of using "rdtscp" and "mfence" to
|
||||
// measure the time it takes to access a block specified by its virtual address
|
||||
// The corresponding pseudo code is
|
||||
// =========
|
||||
// t1 = rdtscp
|
||||
// load addr
|
||||
// t2 = rdtscp
|
||||
// cycles = t2 - t1
|
||||
// return cycles
|
||||
// =========
|
||||
static inline uint64_t measure_one_block_access_time(uint64_t addr)
|
||||
{
|
||||
uint64_t cycles;
|
||||
|
||||
asm volatile("mov %1, %%r8\n\t"
|
||||
"mfence\n\t"
|
||||
"lfence\n\t"
|
||||
"rdtscp\n\t"
|
||||
"mov %%eax, %%edi\n\t"
|
||||
"mov (%%r8), %%r8\n\t"
|
||||
"rdtscp\n\t"
|
||||
"sub %%edi, %%eax\n\t"
|
||||
: "=a"(cycles) /*output*/
|
||||
: "r"(addr) /*input*/
|
||||
: "r8", "edi"); /*reserved register*/
|
||||
|
||||
return cycles;
|
||||
}
|
||||
|
||||
static inline uint64_t one_block_access(uint64_t addr)
|
||||
{
|
||||
asm volatile("mov (%0), %%r8\n\t"
|
||||
: /*output*/
|
||||
: "r"(addr) /*input*/
|
||||
: "r8"); /*reserved register*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
// A wrapper function of the clflush instruction
|
||||
// The instruction evict the given address from the cache to DRAM
|
||||
// so that the next time the line is accessed, it will be fetched from DRAM
|
||||
// Details in https://www.felixcloutier.com/x86/clflush
|
||||
static inline void clflush(void *v) {
|
||||
asm volatile ("clflush 0(%0)": : "r" (v):);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Supporting functions for printing results in different formats
|
||||
// Function "compare" is used in the priting functions and you do not need it
|
||||
int compare(const void *p1, const void *p2) {
|
||||
uint64_t u1 = *(uint64_t *)p1;
|
||||
uint64_t u2 = *(uint64_t *)p2;
|
||||
|
||||
return (int)u1 - (int)u2;
|
||||
}
|
||||
|
||||
|
||||
// Print out the latencies you measured
|
||||
void print_results(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3) {
|
||||
qsort(dram, SAMPLES, sizeof(uint64_t), compare);
|
||||
qsort(l1, SAMPLES, sizeof(uint64_t), compare);
|
||||
qsort(l2, SAMPLES, sizeof(uint64_t), compare);
|
||||
qsort(l3, SAMPLES, sizeof(uint64_t), compare);
|
||||
printf(" : L1 L2 L3 Mem \n");
|
||||
printf("Minimum : %5ld %5ld %5ld %5ld\n", l1[0], l2[0], l3[0], dram[0]);
|
||||
|
||||
printf("Bottom decile: %5ld %5ld %5ld %5ld\n", l1[SAMPLES/10], l2[SAMPLES/10],
|
||||
l3[SAMPLES/10], dram[SAMPLES/10]);
|
||||
|
||||
printf("Median : %5ld %5ld %5ld %5ld\n", l1[SAMPLES/2], l2[SAMPLES/2],
|
||||
l3[SAMPLES/2], dram[SAMPLES/2]);
|
||||
|
||||
printf("Top decile : %5ld %5ld %5ld %5ld\n", l1[(SAMPLES * 9)/10], l2[(SAMPLES * 9)/10],
|
||||
l3[(SAMPLES * 9)/10], dram[(SAMPLES * 9)/10]);
|
||||
|
||||
printf("Maximum : %5ld %5ld %5ld %5ld\n", l1[SAMPLES-1], l2[SAMPLES-1],
|
||||
l3[SAMPLES-1], dram[SAMPLES-1]);
|
||||
}
|
||||
|
||||
// Format the latencies for part 1.5
|
||||
void print_results_for_python(uint64_t* dram, uint64_t* l1, uint64_t* l2, uint64_t* l3)
|
||||
{
|
||||
qsort(dram, SAMPLES, sizeof(uint64_t), compare);
|
||||
qsort(l1, SAMPLES, sizeof(uint64_t), compare);
|
||||
qsort(l2, SAMPLES, sizeof(uint64_t), compare);
|
||||
qsort(l3, SAMPLES, sizeof(uint64_t), compare);
|
||||
|
||||
for (int i = 0; i < SAMPLES; i++) {
|
||||
printf("%ld ", l1[i]);
|
||||
}
|
||||
printf("\n");
|
||||
for (int i = 0; i < SAMPLES; i++) {
|
||||
printf("%ld ", l2[i]);
|
||||
}
|
||||
printf("\n");
|
||||
for (int i = 0; i < SAMPLES; i++) {
|
||||
printf("%ld ", l3[i]);
|
||||
}
|
||||
printf("\n");
|
||||
for (int i = 0; i < SAMPLES; i++) {
|
||||
printf("%ld ", dram[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#endif // _UTILITY_H__
|
|
@ -0,0 +1,26 @@
|
|||
include ../cpu.mk
|
||||
|
||||
TARGETS=receiver sender
|
||||
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_sender: sender
|
||||
taskset -c $(SENDER_CPU) ./sender
|
||||
|
||||
run_receiver: receiver
|
||||
taskset -c $(RECEIVER_CPU) ./receiver
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o $(HELPERS) $(TARGETS)
|
|
@ -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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
@ -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,33 @@
|
|||
|
||||
// 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>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef UTIL_H_
|
||||
#define UTIL_H_
|
||||
|
||||
#define ADDR_PTR uint64_t
|
||||
#define CYCLES uint32_t
|
||||
|
||||
CYCLES measure_one_block_access_time(ADDR_PTR addr);
|
||||
|
||||
// You Should Not Use clflush in your final submission
|
||||
// It is only used for debug
|
||||
void clflush(ADDR_PTR addr);
|
||||
|
||||
char *string_to_binary(char *s);
|
||||
char *binary_to_string(char *data);
|
||||
|
||||
int string_to_int(char* s);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
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-2:
|
||||
taskset -c $(SENDER_CPU) ./victim-2
|
||||
|
||||
run_victim-3:
|
||||
taskset -c $(SENDER_CPU) ./victim-3
|
||||
|
||||
run_victim-4:
|
||||
taskset -c $(SENDER_CPU) ./victim-4
|
||||
|
||||
run_attacker: attacker
|
||||
taskset -c $(RECEIVER_CPU) ./attacker
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
$(RM) *.o $(HELPERS) $(TARGETS)
|
|
@ -0,0 +1,12 @@
|
|||
#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 const *argv[]) {
|
||||
int flag = -1;
|
||||
|
||||
// Put your capture-the-flag code here
|
||||
|
||||
printf("Flag: %d\n", flag);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
#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));
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
// 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 ADDR_PTR uint64_t
|
||||
#define CYCLES uint32_t
|
||||
|
||||
CYCLES measure_one_block_access_time(ADDR_PTR addr);
|
||||
|
||||
void clflush(ADDR_PTR addr);
|
||||
|
||||
#endif
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,11 @@
|
|||
# Hands-On Hardware Side Channels Lab
|
||||
|
||||
This repository contains all the starting code you will need for the lab.
|
||||
|
||||
A randomly-generated password will be emailed to you when the lab is released. Please log in and change your password immediately to something secure using the `passwd` command. Please note that your account will be deleted at the end of this course.
|
||||
|
||||
## 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.**
|
||||
|
||||
After completing these steps, you are now ready to start the lab. Good luck!
|
|
@ -0,0 +1,6 @@
|
|||
CC=gcc
|
||||
CFLAGS=-O0 -I /usr/local
|
||||
$(error Please set SENDER_CPU and RECEIVER_CPU to your assigned values)
|
||||
SENDER_CPU=
|
||||
RECEIVER_CPU=
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#!/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