Commit 227c9f39 by Thomas Lively

Inserted local redzones.

BUG=chromium:https://bugs.chromium.org/p/nativeclient/issues/detail?id=4374 R=kschimpf@google.com, stichnot@chromium.org Review URL: https://codereview.chromium.org/2086593002 .
parent 2943d77c
...@@ -27,7 +27,3 @@ AddressSanitizer and properly linked into a final executable using ...@@ -27,7 +27,3 @@ AddressSanitizer and properly linked into a final executable using
subzero/pydir/szbuild.py with the --fsanitize-address flag, i.e.:: subzero/pydir/szbuild.py with the --fsanitize-address flag, i.e.::
pydir/szbuild.py --fsanitize-address hello.pexe pydir/szbuild.py --fsanitize-address hello.pexe
...@@ -15,26 +15,49 @@ ...@@ -15,26 +15,49 @@
/// ///
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include <assert.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
static __thread int behind_malloc = 0;
// TODO(tlively): Define and implement this library // TODO(tlively): Define and implement this library
void __asan_init(void) { void __asan_init(void) {
printf("Set up shadow memory here\n"); if (behind_malloc == 0)
return; printf("set up shadow memory here\n");
} }
void __asan_check(void *addr, int size) { void __asan_check(void *addr, int size) {
printf("Check %d bytes at %p\n", size, addr); if (behind_malloc == 0)
return; printf("check %d bytes at %p\n", size, addr);
} }
void *__asan_malloc(size_t size) { void *__asan_malloc(size_t size) {
printf("malloc() called with size %d\n", size); if (behind_malloc == 0)
return malloc(size); printf("malloc() called with size %d\n", size);
++behind_malloc;
void *ret = malloc(size);
--behind_malloc;
assert(behind_malloc >= 0);
return ret;
} }
void __asan_free(void *ptr) { void __asan_free(void *ptr) {
printf("free() called on %p\n", ptr); if (behind_malloc == 0)
printf("free() called on %p\n", ptr);
++behind_malloc;
free(ptr); free(ptr);
--behind_malloc;
assert(behind_malloc >= 0);
}
void __asan_alloca(void *ptr, int size) {
if (behind_malloc == 0)
printf("alloca of %d bytes at %p\n", size, ptr);
}
void __asan_unalloca(void *ptr, int size) {
if (behind_malloc == 0)
printf("unalloca of %d bytes as %p\n", size, ptr);
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "IceASanInstrumentation.h" #include "IceASanInstrumentation.h"
#include "IceBuildDefs.h" #include "IceBuildDefs.h"
#include "IceCfg.h"
#include "IceCfgNode.h" #include "IceCfgNode.h"
#include "IceGlobalInits.h" #include "IceGlobalInits.h"
#include "IceInst.h" #include "IceInst.h"
...@@ -122,6 +123,43 @@ ASanInstrumentation::createRz(VariableDeclarationList *List, ...@@ -122,6 +123,43 @@ ASanInstrumentation::createRz(VariableDeclarationList *List,
return Rz; return Rz;
} }
// Check for an alloca signaling the presence of local variables and add a
// redzone if it is found
void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) {
auto *FirstAlloca = llvm::dyn_cast<InstAlloca>(Context.getCur());
if (FirstAlloca == nullptr)
return;
constexpr SizeT Alignment = 4;
InstAlloca *RzAlloca = createLocalRz(Context, RzSize, Alignment);
// insert before the current instruction
InstList::iterator Next = Context.getNext();
Context.setInsertPoint(Context.getCur());
Context.insert(RzAlloca);
Context.setNext(Next);
}
void ASanInstrumentation::instrumentAlloca(LoweringContext &Context,
InstAlloca *Instr) {
auto *VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Instr->getSizeInBytes());
SizeT VarSize = (VarSizeOp == nullptr) ? RzSize : VarSizeOp->getValue();
SizeT Padding = Utils::OffsetToAlignment(VarSize, RzSize);
constexpr SizeT Alignment = 1;
InstAlloca *Rz = createLocalRz(Context, RzSize + Padding, Alignment);
Context.insert(Rz);
}
InstAlloca *ASanInstrumentation::createLocalRz(LoweringContext &Context,
SizeT Size, SizeT Alignment) {
Cfg *Func = Context.getNode()->getCfg();
Variable *Rz = Func->makeVariable(IceType_i32);
Rz->setName(Func, nextRzName());
auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, Size);
auto *RzAlloca = InstAlloca::create(Func, Rz, ByteCount, Alignment);
return RzAlloca;
}
void ASanInstrumentation::instrumentCall(LoweringContext &Context, void ASanInstrumentation::instrumentCall(LoweringContext &Context,
InstCall *Instr) { InstCall *Instr) {
auto *CallTarget = auto *CallTarget =
......
...@@ -31,7 +31,7 @@ class ASanInstrumentation : public Instrumentation { ...@@ -31,7 +31,7 @@ class ASanInstrumentation : public Instrumentation {
ASanInstrumentation &operator=(const ASanInstrumentation &) = delete; ASanInstrumentation &operator=(const ASanInstrumentation &) = delete;
public: public:
ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx) {} ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx), RzNum(0) {}
void instrumentGlobals(VariableDeclarationList &Globals) override; void instrumentGlobals(VariableDeclarationList &Globals) override;
private: private:
...@@ -40,13 +40,17 @@ private: ...@@ -40,13 +40,17 @@ private:
VariableDeclaration *RzArray, VariableDeclaration *RzArray,
SizeT &RzArraySize, SizeT &RzArraySize,
VariableDeclaration *Global); VariableDeclaration *Global);
InstAlloca *createLocalRz(LoweringContext &Context, SizeT Size,
SizeT Alignment);
void instrumentFuncStart(LoweringContext &Context) override;
void instrumentAlloca(LoweringContext &Context, InstAlloca *Instr) override;
void instrumentCall(LoweringContext &Context, InstCall *Instr) override; void instrumentCall(LoweringContext &Context, InstCall *Instr) override;
void instrumentLoad(LoweringContext &Context, InstLoad *Instr) override; void instrumentLoad(LoweringContext &Context, InstLoad *Instr) override;
void instrumentStore(LoweringContext &Context, InstStore *Instr) override; void instrumentStore(LoweringContext &Context, InstStore *Instr) override;
void instrumentAccess(LoweringContext &Context, Operand *Op, SizeT Size); void instrumentAccess(LoweringContext &Context, Operand *Op, SizeT Size);
void instrumentStart(Cfg *Func) override; void instrumentStart(Cfg *Func) override;
bool DidInsertRedZones = false; bool DidInsertRedZones = false;
uint32_t RzNum = 0; std::atomic<uint32_t> RzNum;
}; };
} // end of namespace Ice } // end of namespace Ice
......
...@@ -31,12 +31,16 @@ void Instrumentation::instrumentFunc(Cfg *Func) { ...@@ -31,12 +31,16 @@ void Instrumentation::instrumentFunc(Cfg *Func) {
// TODO(tlively): More selectively instrument functions so that shadow memory // TODO(tlively): More selectively instrument functions so that shadow memory
// represents user accessibility more and library accessibility less. // represents user accessibility more and library accessibility less.
bool DidInstrumentStart = false;
LoweringContext Context; LoweringContext Context;
Context.init(Func->getNodes().front()); Context.init(Func->getNodes().front());
instrumentFuncStart(Context);
for (CfgNode *Node : Func->getNodes()) { for (CfgNode *Node : Func->getNodes()) {
Context.init(Node); Context.init(Node);
while (!Context.atEnd()) { while (!Context.atEnd()) {
if (!DidInstrumentStart) {
instrumentFuncStart(Context);
DidInstrumentStart = true;
}
instrumentInst(Context); instrumentInst(Context);
// go to next undeleted instruction // go to next undeleted instruction
Context.advanceCur(); Context.advanceCur();
......
...@@ -47,7 +47,7 @@ public: ...@@ -47,7 +47,7 @@ public:
private: private:
void instrumentInst(LoweringContext &Context); void instrumentInst(LoweringContext &Context);
virtual void instrumentFuncStart(LoweringContext &) {} virtual void instrumentFuncStart(LoweringContext &) {}
virtual void instrumentAlloca(LoweringContext &, const class InstAlloca *) {} virtual void instrumentAlloca(LoweringContext &, class InstAlloca *) {}
virtual void instrumentArithmetic(LoweringContext &, class InstArithmetic *) { virtual void instrumentArithmetic(LoweringContext &, class InstArithmetic *) {
} }
virtual void instrumentBr(LoweringContext &, class InstBr *) {} virtual void instrumentBr(LoweringContext &, class InstBr *) {}
......
...@@ -69,12 +69,7 @@ define internal void @doLoads() { ...@@ -69,12 +69,7 @@ define internal void @doLoads() {
; DUMP-LABEL: ================ Instrumented CFG ================ ; DUMP-LABEL: ================ Instrumented CFG ================
; DUMP-NEXT: define internal void @doLoads() { ; DUMP-NEXT: define internal void @doLoads() {
; DUMP-NEXT: __0: ; DUMP-NEXT: __0:
; DUMP-NEXT: %srcLocal8 = alloca i8, i32 1, align 4 ; DUMP: call void @__asan_check(i32 @srcConst8, i32 1)
; DUMP-NEXT: %srcLocal16 = alloca i8, i32 2, align 4
; DUMP-NEXT: %srcLocal32 = alloca i8, i32 4, align 4
; DUMP-NEXT: %srcLocal64 = alloca i8, i32 8, align 4
; DUMP-NEXT: %srcLocal128 = alloca i8, i32 16, align 4
; DUMP-NEXT: call void @__asan_check(i32 @srcConst8, i32 1)
; DUMP-NEXT: %dest1 = load i8, i8* @srcConst8, align 1 ; DUMP-NEXT: %dest1 = load i8, i8* @srcConst8, align 1
; DUMP-NEXT: call void @__asan_check(i32 @srcConst16, i32 2) ; DUMP-NEXT: call void @__asan_check(i32 @srcConst16, i32 2)
; DUMP-NEXT: %dest2 = load i16, i16* @srcConst16, align 1 ; DUMP-NEXT: %dest2 = load i16, i16* @srcConst16, align 1
......
; Test for insertion of redzones around global variables
; REQUIRES: allow_dump
; RUN: %p2i -i %s --args -verbose=inst -threads=0 -fsanitize-address \
; RUN: | FileCheck --check-prefix=DUMP %s
; Function with local variables to be instrumented
define internal void @func() {
%local0 = alloca i8, i32 4, align 4
%local1 = alloca i8, i32 32, align 4
%local2 = alloca i8, i32 13, align 4
%local3 = alloca i8, i32 75, align 4
%local4 = alloca i8, i32 64, align 4
%local5 = alloca i8, i32 4, align 1
%local6 = alloca i8, i32 32, align 1
%local7 = alloca i8, i32 13, align 1
%local8 = alloca i8, i32 75, align 1
%local9 = alloca i8, i32 64, align 1
ret void
}
; DUMP-LABEL: ================ Instrumented CFG ================
; DUMP-NEXT: define internal void @func() {
; DUMP-NEXT: __0:
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 4
; DUMP-NEXT: %local0 = alloca i8, i32 4, align 4
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 60, align 1
; DUMP-NEXT: %local1 = alloca i8, i32 32, align 4
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 1
; DUMP-NEXT: %local2 = alloca i8, i32 13, align 4
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 51, align 1
; DUMP-NEXT: %local3 = alloca i8, i32 75, align 4
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 53, align 1
; DUMP-NEXT: %local4 = alloca i8, i32 64, align 4
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 1
; DUMP-NEXT: %local5 = alloca i8, i32 4, align 1
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 60, align 1
; DUMP-NEXT: %local6 = alloca i8, i32 32, align 1
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 1
; DUMP-NEXT: %local7 = alloca i8, i32 13, align 1
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 51, align 1
; DUMP-NEXT: %local8 = alloca i8, i32 75, align 1
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 53, align 1
; DUMP-NEXT: %local9 = alloca i8, i32 64, align
; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 1
; DUMP-NEXT: ret void
; DUMP-NEXT: }
...@@ -50,12 +50,7 @@ define internal void @doStores(<4 x i32> %vecSrc) { ...@@ -50,12 +50,7 @@ define internal void @doStores(<4 x i32> %vecSrc) {
; DUMP-LABEL: ================ Instrumented CFG ================ ; DUMP-LABEL: ================ Instrumented CFG ================
; DUMP-NEXT: define internal void @doStores(<4 x i32> %vecSrc) { ; DUMP-NEXT: define internal void @doStores(<4 x i32> %vecSrc) {
; DUMP-NEXT: __0: ; DUMP-NEXT: __0:
; DUMP-NEXT: %destLocal8 = alloca i8, i32 1, align 4 ; DUMP: call void @__asan_check(i32 @destGlobal8, i32 1)
; DUMP-NEXT: %destLocal16 = alloca i8, i32 2, align 4
; DUMP-NEXT: %destLocal32 = alloca i8, i32 4, align 4
; DUMP-NEXT: %destLocal64 = alloca i8, i32 8, align 4
; DUMP-NEXT: %destLocal128 = alloca i8, i32 16, align 4
; DUMP-NEXT: call void @__asan_check(i32 @destGlobal8, i32 1)
; DUMP-NEXT: store i8 42, i8* @destGlobal8, align 1 ; DUMP-NEXT: store i8 42, i8* @destGlobal8, align 1
; DUMP-NEXT: call void @__asan_check(i32 @destGlobal16, i32 2) ; DUMP-NEXT: call void @__asan_check(i32 @destGlobal16, i32 2)
; DUMP-NEXT: store i16 42, i16* @destGlobal16, align 1 ; DUMP-NEXT: store i16 42, i16* @destGlobal16, align 1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment