[PATCH] Protection against stack-based memory corruption errors using SafeStack

JF Bastien jfb at chromium.org
Fri May 29 09:57:18 PDT 2015


I like the technical approach overall, but the testing strategy worries me. Specifically, this is now at the IR level and I have a hard time convincing myself that the safe stack's location isn't moved to other registers, or stored on the unsafe stack or heap. This isn't just about the current implementation: I worry of breaking safe stack as LLVM gains new features (e.g. GC roots breaks it, adding similar features would silently do the same), or with different runtimes.

The only way I can think of convincing myself is by using binary instrumentation: keep track of safe stack ranges for each thread at runtime, and use QEMU/Pin/Valgrind/... to find any leaks. This will have false positives, but assuming there's no stack-cookie-like leaks then the lack of any warnings would mean that the safe stacks' locations aren't leaking. This tool could be run on the test suite.

I don't want to block checking in safe stack on such a tool, but I would be wary of using it as a security feature without having tested it.

Thoughts?


================
Comment at: lib/Transforms/Instrumentation/SafeStack.cpp:340
@@ +339,3 @@
+    // throughout the function. For now we store it in an alloca.
+    DynamicTop = IRB.CreateAlloca(StackPtrTy, 0, "unsafe_stack_dynamic_ptr");
+
----------------
`/* ArraySize= */ nullptr`

================
Comment at: lib/Transforms/Instrumentation/SafeStack.cpp:426
@@ +425,3 @@
+    StaticOffset += Size;
+    StaticOffset = (StaticOffset + Align - 1) / Align * Align;
+
----------------
Use `alignAddr` from `MathExtras.h` instead.

================
Comment at: lib/Transforms/Instrumentation/SafeStack.cpp:444
@@ +443,3 @@
+  StaticOffset =
+      (StaticOffset + StackAlignment - 1) / StackAlignment * StackAlignment;
+
----------------
`alignAddr`

================
Comment at: lib/Transforms/Instrumentation/SafeStack.cpp:129
@@ +128,3 @@
+        // exception or not depending on the input value).
+        if (CS.onlyReadsMemory() && I->getType()->isVoidTy())
+          continue;
----------------
pcc wrote:
> jfb wrote:
> > Are there any read-only functions with no return value? I'm not sure that makes much sense, and I don't see a test fo it.
> > Are there any read-only functions with no return value?
> 
> `void noop() {}` ? :)
> 
> > I don't see a test fo it.
> 
> Added.
I asked the wrong question :-)

Are there any read-only functions with no return value which also capture pointers? The example you added looks like what I expected... but I don't get what such a function could do. It seems pretty useless! If so then it doesn't seem worth handling it specially here (why optimize something nobody in their right mind would do?).

================
Comment at: lib/Transforms/Instrumentation/SafeStack.cpp:147
@@ +146,3 @@
+
+      default:
+        // The object is unsafe if it is used in any other way.
----------------
pcc wrote:
> jfb wrote:
> > Don't you end up seeing uses of alloca through intrinsics such as `memset` and `memcpy`? They can be added if needed, but since these two act the same as load/store I'd think that they are safe.
> Yes, but let's add support for these intrinsics in a separate change.
Sounds good. Could you add a FIXME for this?

http://reviews.llvm.org/D6094

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/






More information about the llvm-commits mailing list