[PATCH] Implement NaCl sandboxing of function calls
Sasa Stankovic
Sasa.Stankovic at imgtec.com
Mon Mar 10 14:00:34 PDT 2014
Hi mseaborn,
[mips] Implement NaCl sandboxing of function calls:
* Add masking instructions before indirect calls (in MC layer).
* Align call + branch delay to the bundle end (in MC layer).
http://llvm-reviews.chandlerc.com/D3032
Files:
lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
test/MC/Mips/nacl-mask.s
Index: lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
===================================================================
--- lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
+++ lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
@@ -12,7 +12,8 @@
// before dangerous control-flow and memory access instructions. It inserts
// address-masking instructions after instructions that change the stack
// pointer. It ensures that the mask and the dangerous instruction are always
-// emitted in the same bundle.
+// emitted in the same bundle. It aligns call + branch delay to the bundle end,
+// so that return address is always aligned to the start of next bundle.
//
//===----------------------------------------------------------------------===//
@@ -36,11 +37,15 @@
public:
MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS,
MCCodeEmitter *Emitter)
- : MCELFStreamer(Context, TAB, OS, Emitter) {}
+ : MCELFStreamer(Context, TAB, OS, Emitter), SandboxingCall(false) {}
~MipsNaClELFStreamer() {}
private:
+ MCInst Call;
+ bool SandboxingCall;
+ bool IsIndirectCall;
+
bool isIndirectJump(const MCInst &MI) {
return MI.getOpcode() == Mips::JR || MI.getOpcode() == Mips::RET;
}
@@ -50,6 +55,25 @@
&& MI.getOperand(0).getReg() == Mips::SP);
}
+ bool isCall(unsigned Opcode, bool *IsIndirectCall) {
+ *IsIndirectCall = false;
+
+ switch (Opcode) {
+ default:
+ return false;
+
+ case Mips::JAL:
+ case Mips::BAL_BR:
+ case Mips::BLTZAL:
+ case Mips::BGEZAL:
+ return true;
+
+ case Mips::JALR:
+ *IsIndirectCall = true;
+ return true;
+ }
+ }
+
void emitMask(unsigned AddrReg, unsigned MaskReg,
const MCSubtargetInfo &STI) {
MCInst MaskInst;
@@ -92,6 +116,20 @@
EmitBundleUnlock();
}
+ // Sandbox calls by aligning call and branch delay to the bundle end.
+ // For indirect calls, emit the mask before the call.
+ void sandboxCall(const MCInst &Call, const MCInst &BranchDelay,
+ const MCSubtargetInfo &STI, bool IsIndirectCall) {
+ EmitBundleLock(true);
+ if (IsIndirectCall) {
+ unsigned TargetReg = Call.getOperand(1).getReg();
+ emitMask(TargetReg, IndirectBranchMaskReg, STI);
+ }
+ MCELFStreamer::EmitInstruction(Call, STI);
+ MCELFStreamer::EmitInstruction(BranchDelay, STI);
+ EmitBundleUnlock();
+ }
+
public:
/// This function is the one used to emit instruction data into the ELF
/// streamer. We override it to mask dangerous instructions.
@@ -120,6 +158,17 @@
return;
}
+ // Sandbox calls.
+ if (SandboxingCall) {
+ sandboxCall(Call, Inst, STI, IsIndirectCall);
+ SandboxingCall = false;
+ return;
+ } else if (isCall(Inst.getOpcode(), &IsIndirectCall)) {
+ Call = Inst;
+ SandboxingCall = true;
+ return;
+ }
+
// None of the sandboxing applies, just emit the instruction.
MCELFStreamer::EmitInstruction(Inst, STI);
}
Index: test/MC/Mips/nacl-mask.s
===================================================================
--- test/MC/Mips/nacl-mask.s
+++ test/MC/Mips/nacl-mask.s
@@ -9,6 +9,7 @@
# Test that address-masking sandboxing is added before indirect branches and
# returns.
+ .align 4
test1:
.set noreorder
@@ -35,6 +36,7 @@
# Test that address-masking sandboxing is added before load instructions.
+ .align 4
test2:
.set noreorder
@@ -104,6 +106,7 @@
# Test that address-masking sandboxing is added before store instructions.
+ .align 4
test3:
.set noreorder
@@ -166,6 +169,7 @@
# Test that address-masking sandboxing is added after instructions that change
# stack pointer.
+ .align 4
test4:
.set noreorder
@@ -217,3 +221,65 @@
# CHECK-NOT: and
# CHECK: sw $sp, 123($sp)
# CHECK-NOT: and
+
+
+
+# Test that call + branch delay is aligned at bundle end. Test that mask is
+# added before indirect calls.
+
+ .align 4
+test5:
+ .set noreorder
+
+ jal func1
+ addiu $4, $zero, 1
+
+ nop
+ bal func2
+ addiu $4, $zero, 2
+
+ nop
+ nop
+ bltzal $t1, func3
+ addiu $4, $zero, 3
+
+ nop
+ nop
+ nop
+ bgezal $t2, func4
+ addiu $4, $zero, 4
+
+ jalr $t9
+ addiu $4, $zero, 5
+
+# CHECK-LABEL: test5:
+
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: jal
+# CHECK-NEXT: addiu $4, $zero, 1
+
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: bal
+# CHECK-NEXT: addiu $4, $zero, 2
+
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: bltzal
+# CHECK-NEXT: addiu $4, $zero, 3
+
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: bgezal
+# CHECK-NEXT: addiu $4, $zero, 4
+
+# CHECK-NEXT: nop
+# CHECK-NEXT: and $25, $25, $14
+# CHECK-NEXT: jalr $25
+# CHECK-NEXT: addiu $4, $zero, 5
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3032.1.patch
Type: text/x-patch
Size: 5169 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140310/3c0751b4/attachment.bin>
More information about the llvm-commits
mailing list