Factoring out signal handling. (#84)
diff --git a/demos/l1tf.cc b/demos/l1tf.cc
index 6fc7593..65c245e 100644
--- a/demos/l1tf.cc
+++ b/demos/l1tf.cc
@@ -37,6 +37,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
#include "utils.h"
char *private_page = nullptr;
@@ -99,34 +100,8 @@
}
}
-static void Sigsegv(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGSEGV signal handler.
- // Moves the instruction pointer to the "afterspeculation" label.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_X64
- ucontext->uc_mcontext.gregs[REG_RIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_IA32
- ucontext->uc_mcontext.gregs[REG_EIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_PPC
- ucontext->uc_mcontext.regs->nip =
- reinterpret_cast<size_t>(afterspeculation);
-#else
-# error Unsupported CPU.
-#endif
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = Sigsegv;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGSEGV, &act, NULL);
-}
-
int main() {
- SetSignal();
+ OnSignalMoveRipToAfterspeculation(SIGSEGV);
private_page = reinterpret_cast<char *>(mmap(nullptr, kPageSizeBytes,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
memcpy(private_page, private_data, strlen(private_data) + 1);
diff --git a/demos/local_content.h b/demos/local_content.h
index f34d355..33aa4c4 100644
--- a/demos/local_content.h
+++ b/demos/local_content.h
@@ -13,11 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef DEMOS_LOCAL_LABELS_H
-#define DEMOS_LOCAL_LABELS_H
-#include "compiler_specifics.h"
-
+#ifndef DEMOS_LOCAL_CONTENT_H
+#define DEMOS_LOCAL_CONTENT_H
// Generic strings used across examples. The public_data is intended to be
// accessed in the C++ execution model. The content of the private_data is
// intended to be leaked outside of the C++ execution model using sidechannels.
@@ -25,23 +23,4 @@
// demonstrating.
const char *public_data = "Hello, world!";
const char *private_data = "It's a s3kr3t!!!";
-
-#if SAFESIDE_ARM64
-// Local handler necessary for avoiding local/global linking mismatches on ARM.
-// When we use extern char[] declaration for a label defined in assembly, the
-// compiler yields this sequence that fails loading the actual address of the
-// label:
-// adrp x0, :got:label
-// ldr x0, [x0, #:got_lo12:label]
-// On the other hand when we use this local handler, the compiler yield this
-// sequence of instructions:
-// adrp x0, label
-// add x0, x0, :lo12:label
-// and that works correctly because it if an effective equivalent of
-// adr x0, label.
-static void LocalHandler() {
- asm volatile("b afterspeculation");
-}
-#endif
-
-#endif // DEMOS_LOCAL_LABELS_H
+#endif // DEMOS_LOCAL_CONTENT_H
diff --git a/demos/meltdown.cc b/demos/meltdown.cc
index 541439a..ebf48ae 100644
--- a/demos/meltdown.cc
+++ b/demos/meltdown.cc
@@ -34,6 +34,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
#include "utils.h"
// Leaks the byte that is physically located at &text[0] + offset, without
@@ -81,32 +82,6 @@
}
}
-static void Sigsegv(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGSEGV signal handler.
- // Moves the instruction pointer to the "afterspeculation" label.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_X64
- ucontext->uc_mcontext.gregs[REG_RIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_IA32
- ucontext->uc_mcontext.gregs[REG_EIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_PPC
- ucontext->uc_mcontext.regs->nip =
- reinterpret_cast<size_t>(afterspeculation);
-#else
-# error Unsupported CPU.
-#endif
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = Sigsegv;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGSEGV, &act, NULL);
-}
-
int main() {
size_t private_data, private_length;
std::ifstream in("/proc/safeside_meltdown/address");
@@ -122,7 +97,7 @@
in >> std::dec >> private_length;
in.close();
- SetSignal();
+ OnSignalMoveRipToAfterspeculation(SIGSEGV);
std::cout << "Leaking the string: ";
std::cout.flush();
const size_t private_offset =
diff --git a/demos/meltdown_ac.cc b/demos/meltdown_ac.cc
index 8624ec1..9051215 100644
--- a/demos/meltdown_ac.cc
+++ b/demos/meltdown_ac.cc
@@ -49,6 +49,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
#include "utils.h"
// Storage for the public data.
@@ -123,30 +124,9 @@
}
}
-static void sigbus(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGBUS signal handler.
- // Moves the instruction pointer to the "afterspeculation" label.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_X64
- ucontext->uc_mcontext.gregs[REG_RIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#else
- ucontext->uc_mcontext.gregs[REG_EIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#endif
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = sigbus;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGBUS, &act, NULL);
-}
-
int main() {
InitializeUnalignedData();
- SetSignal();
+ OnSignalMoveRipToAfterspeculation(SIGBUS);
std::cout << "Leaking the string: ";
std::cout.flush();
size_t private_offset = unaligned_private_data - unaligned_public_data;
diff --git a/demos/meltdown_br.cc b/demos/meltdown_br.cc
index 8d84bc2..ac97256 100644
--- a/demos/meltdown_br.cc
+++ b/demos/meltdown_br.cc
@@ -43,6 +43,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
#include "utils.h"
// ICC requires the offset variable to be volatile. If it isn't, ICC schedules
@@ -99,38 +100,14 @@
}
}
-static void Sigsegv(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGSEGV signal handler.
- // Moves the instruction pointer to the "afterspeculation" label.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_LINUX
- ucontext->uc_mcontext.gregs[REG_EIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_MAC
- ucontext->uc_mcontext->__ss.__eip =
- reinterpret_cast<uintptr_t>(afterspeculation);
-#else
-# error Unsupported OS.
-#endif
-}
-
-static void SetSignal() {
- struct sigaction act;
- memset(&act, 0, sizeof(struct sigaction));
- act.sa_sigaction = Sigsegv;
- act.sa_flags = SA_SIGINFO;
-#if SAFESIDE_LINUX
- sigaction(SIGSEGV, &act, nullptr);
-#elif SAFESIDE_MAC
- sigaction(SIGTRAP, &act, nullptr);
-#else
-# error Unsupported OS.
-#endif
-}
-
int main() {
- SetSignal();
+#if SAFESIDE_LINUX
+ OnSignalMoveRipToAfterspeculation(SIGSEGV);
+#elif SAFESIDE_MAC
+ OnSignalMoveRipToAfterspeculation(SIGTRAP);
+#else
+# error Unsupported OS.
+#endif
std::cout << "Leaking the string: ";
std::cout.flush();
size_t private_offset = private_data - public_data;
diff --git a/demos/meltdown_de.cc b/demos/meltdown_de.cc
index cbbd66d..8ac8cf6 100644
--- a/demos/meltdown_de.cc
+++ b/demos/meltdown_de.cc
@@ -68,6 +68,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
+#include "meltdown_local_content.h"
#include "utils.h"
const char *public_data = "Hello, world!";
@@ -142,31 +143,8 @@
}
}
-static void Sigfpe(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGFPE signal handler.
- // Moves the instruction pointer to the "afterspeculation" label.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_X64
- ucontext->uc_mcontext.gregs[REG_RIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_IA32
- ucontext->uc_mcontext.gregs[REG_EIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#else
-# error Unsupported architecture.
-#endif
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = Sigfpe;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGFPE, &act, NULL);
-}
-
int main() {
- SetSignal();
+ OnSignalMoveRipToAfterspeculation(SIGFPE);
std::cout << "Leaking the string: ";
std::cout.flush();
for (size_t i = 0; i < kPrivateDataLength; ++i) {
diff --git a/demos/meltdown_local_content.h b/demos/meltdown_local_content.h
new file mode 100644
index 0000000..deafa2a
--- /dev/null
+++ b/demos/meltdown_local_content.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef DEMOS_MELTDOWN_LOCAL_CONTENT_H
+#define DEMOS_MELTDOWN_LOCAL_CONTENT_H
+
+#include "compiler_specifics.h"
+
+#if SAFESIDE_LINUX || SAFESIDE_MAC
+#include <signal.h>
+#endif
+
+#if SAFESIDE_ARM64
+// Local handler necessary for avoiding local/global linking mismatches on ARM.
+// When we use extern char[] declaration for a label defined in assembly, the
+// compiler yields this sequence that fails loading the actual address of the
+// label:
+// adrp x0, :got:label
+// ldr x0, [x0, #:got_lo12:label]
+// On the other hand when we use this local handler, the compiler yield this
+// sequence of instructions:
+// adrp x0, label
+// add x0, x0, :lo12:label
+// and that works correctly because it if an effective equivalent of
+// adr x0, label.
+static void LocalHandler() {
+ asm volatile("b afterspeculation");
+}
+#endif
+
+static void SignalHandler(
+ int /* signum */, siginfo_t * /* siginfo */, void *context) {
+ // On IA32, X64 and PPC moves the instruction pointer to the
+ // "afterspeculation" label. On ARM64 moves the instruction pointer to the
+ // "LocalHandler" label.
+ ucontext_t *ucontext = static_cast<ucontext_t *>(context);
+#if SAFESIDE_LINUX && SAFESIDE_IA32
+ ucontext->uc_mcontext.gregs[REG_EIP] =
+ reinterpret_cast<greg_t>(afterspeculation);
+#elif SAFESIDE_LINUX && SAFESIDE_X64
+ ucontext->uc_mcontext.gregs[REG_RIP] =
+ reinterpret_cast<greg_t>(afterspeculation);
+#elif SAFESIDE_LINUX && SAFESIDE_ARM64
+ ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
+#elif SAFESIDE_LINUX && SAFESIDE_PPC
+ ucontext->uc_mcontext.regs->nip =
+ reinterpret_cast<uintptr_t>(afterspeculation);
+#elif SAFESIDE_MAC && SAFESIDE_IA32
+ ucontext->uc_mcontext->__ss.__eip =
+ reinterpret_cast<uintptr_t>(afterspeculation);
+#elif SAFESIDE_MAC && SAFESIDE_X64
+ ucontext->uc_mcontext->__ss.__rip =
+ reinterpret_cast<uintptr_t>(afterspeculation);
+#else
+# error Unsupported OS/CPU combination.
+#endif
+}
+
+// Sets up signal handling that moves the instruction pointer to the
+// afterspeculation (or LocalHandler in case of ARM) label. See the commentary
+// to LocalHandler function why we must treat ARM differently.
+static void OnSignalMoveRipToAfterspeculation(int signal) {
+ struct sigaction act;
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_sigaction = SignalHandler;
+ act.sa_flags = SA_SIGINFO;
+ sigaction(signal, &act, nullptr);
+}
+#endif // DEMOS_MELTDOWN_LOCAL_CONTENT_H
diff --git a/demos/meltdown_of.cc b/demos/meltdown_of.cc
index e5f6173..55c2096 100644
--- a/demos/meltdown_of.cc
+++ b/demos/meltdown_of.cc
@@ -44,6 +44,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
+#include "meltdown_local_content.h"
#include "local_content.h"
static char LeakByte(const char *data, size_t offset) {
@@ -78,9 +79,9 @@
}
// SIGSEGV signal handler moves the instruction pointer to this label.
-#ifdef __linux__
+#if SAFESIDE_LINUX
asm volatile("afterspeculation:");
-#elif defined(__APPLE__)
+#elif SAFESIDE_MAC
asm volatile("_afterspeculation:");
#else
# error Unsupported OS.
@@ -101,37 +102,14 @@
}
}
-static void Sigsegv(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGSEGV signal handler.
- // Moves the instruction pointer to the "afterspeculation" label.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#ifdef __linux__
- ucontext->uc_mcontext.gregs[REG_EIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-#elif defined(__APPLE__)
- ucontext->uc_mcontext->__ss.__eip =
- reinterpret_cast<uintptr_t>(afterspeculation);
-#else
-# error Unsupported OS.
-#endif
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = Sigsegv;
- act.sa_flags = SA_SIGINFO;
-#ifdef __linux__
- sigaction(SIGSEGV, &act, nullptr);
-#elif defined(__APPLE__)
- sigaction(SIGFPE, &act, nullptr);
-#else
-# error Unsupported OS.
-#endif
-}
-
int main() {
- SetSignal();
+#if SAFESIDE_LINUX
+ OnSignalMoveRipToAfterspeculation(SIGSEGV);
+#elif SAFESIDE_MAC
+ OnSignalMoveRipToAfterspeculation(SIGFPE);
+#else
+# error Unsupported OS.
+#endif
std::cout << "Leaking the string: ";
std::cout.flush();
const size_t private_offset = private_data - public_data;
diff --git a/demos/meltdown_ss.cc b/demos/meltdown_ss.cc
index 5ff302f..283a1bc 100644
--- a/demos/meltdown_ss.cc
+++ b/demos/meltdown_ss.cc
@@ -51,6 +51,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
#include "utils.h"
// Sets up a segment descriptor in the local descriptor table.
@@ -154,24 +155,8 @@
}
}
-static void Sigsegv(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGSEGV signal handler.
- // Moves the instruction pointer to the "afterspeculation" label.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
- ucontext->uc_mcontext.gregs[REG_EIP] =
- reinterpret_cast<greg_t>(afterspeculation);
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = Sigsegv;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGSEGV, &act, NULL);
-}
-
int main() {
- SetSignal();
+ OnSignalMoveRipToAfterspeculation(SIGSEGV);
// Setup the public data segment descriptor on index 0. It is always present.
SetupSegment(0, public_data, true);
std::cout << "Leaking the string: ";
diff --git a/demos/meltdown_ud.cc b/demos/meltdown_ud.cc
index ed19dec..6370b55 100644
--- a/demos/meltdown_ud.cc
+++ b/demos/meltdown_ud.cc
@@ -34,6 +34,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
#include "utils.h"
static char LeakByte(const char *data, size_t offset) {
@@ -79,24 +80,8 @@
}
}
-static void Sigill(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGILL signal handler.
- // Moves the instruction pointer to the "afterspeculation" label jumping to
- // the "LocalHandler" function.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
- ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = Sigill;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGILL, &act, NULL);
-}
-
int main() {
- SetSignal();
+ OnSignalMoveRipToAfterspeculation(SIGILL);
std::cout << "Leaking the string: ";
std::cout.flush();
const size_t private_offset = private_data - public_data;
diff --git a/demos/speculation_over_hw_breakpoint.cc b/demos/speculation_over_hw_breakpoint.cc
index 830e9a9..05a87e4 100644
--- a/demos/speculation_over_hw_breakpoint.cc
+++ b/demos/speculation_over_hw_breakpoint.cc
@@ -46,6 +46,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
#include "utils.h"
static char LeakByte(const char *data, size_t data_length, size_t offset) {
diff --git a/demos/speculation_over_sw_breakpoint.cc b/demos/speculation_over_sw_breakpoint.cc
index 3721124..425a9c4 100644
--- a/demos/speculation_over_sw_breakpoint.cc
+++ b/demos/speculation_over_sw_breakpoint.cc
@@ -39,6 +39,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
static char LeakByte(const char *data, size_t offset) {
CacheSideChannel sidechannel;
@@ -87,24 +88,8 @@
}
}
-static void Sigtrap(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGTRAP signal handler.
- // Moves the instruction pointer to the "afterspeculation" label jumping to
- // the "LocalHandler" function.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
- ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = Sigtrap;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGTRAP, &act, NULL);
-}
-
int main() {
- SetSignal();
+ OnSignalMoveRipToAfterspeculation(SIGTRAP);
std::cout << "Leaking the string: ";
std::cout.flush();
const size_t private_offset = private_data - public_data;
diff --git a/demos/speculation_over_syscall.cc b/demos/speculation_over_syscall.cc
index 80c24df..0f81d18 100644
--- a/demos/speculation_over_syscall.cc
+++ b/demos/speculation_over_syscall.cc
@@ -36,6 +36,7 @@
#include "cache_sidechannel.h"
#include "instr.h"
#include "local_content.h"
+#include "meltdown_local_content.h"
#include "utils.h"
static char LeakByte(const char *data, size_t offset) {
@@ -88,24 +89,8 @@
}
}
-static void Sigusr1(
- int /* signum */, siginfo_t * /* siginfo */, void *context) {
- // SIGUSR1 signal handler.
- // Moves the instruction pointer to the "afterspeculation" label jumping to
- // the "LocalHandler" function.
- ucontext_t *ucontext = static_cast<ucontext_t *>(context);
- ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
-}
-
-static void SetSignal() {
- struct sigaction act;
- act.sa_sigaction = Sigusr1;
- act.sa_flags = SA_SIGINFO;
- sigaction(SIGUSR1, &act, NULL);
-}
-
int main() {
- SetSignal();
+ OnSignalMoveRipToAfterspeculation(SIGUSR1);
std::cout << "Leaking the string: ";
std::cout.flush();
const size_t private_offset = private_data - public_data;