[llvm] r325047 - [LLD] Implement /guard:[no]longjmp

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 13 12:32:53 PST 2018


Author: rnk
Date: Tue Feb 13 12:32:53 2018
New Revision: 325047

URL: http://llvm.org/viewvc/llvm-project?rev=325047&view=rev
Log:
[LLD] Implement /guard:[no]longjmp

Summary:
This protects calls to longjmp from transferring control to arbitrary
program points. Instead, longjmp calls are limited to the set of
registered setjmp return addresses.

This also implements /guard:nolongjmp to allow users to link in object
files that call setjmp that weren't compiled with /guard:cf. In this
case, the linker will approximate the set of address taken functions,
but it will leave longjmp unprotected.

I used the following program to test, compiling it with different -guard
flags:
  $ cl -c t.c -guard:cf
  $ lld-link t.obj -guard:cf

  #include <setjmp.h>
  #include <stdio.h>
  jmp_buf buf;
  void g() {
    printf("before longjmp\n");
    fflush(stdout);
    longjmp(buf, 1);
  }
  void f() {
    if (setjmp(buf)) {
      printf("setjmp returned non-zero\n");
      return;
    }
    g();
  }
  int main() {
    f();
    printf("hello world\n");
  }

In particular, the program aborts when the code is compiled *without*
-guard:cf and linked with -guard:cf. That indicates that longjmps are
protected.

Reviewers: ruiu, inglorion, amccarth

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D43217

Modified:
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp

Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=325047&r1=325046&r2=325047&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Tue Feb 13 12:32:53 2018
@@ -67,6 +67,8 @@ struct LoadConfigTables {
   uint32_t GuardFlags = 0;
   uint64_t GuardFidTableVA = 0;
   uint64_t GuardFidTableCount = 0;
+  uint64_t GuardLJmpTableVA = 0;
+  uint64_t GuardLJmpTableCount = 0;
 };
 
 class COFFDumper : public ObjDumper {
@@ -800,6 +802,11 @@ void COFFDumper::printCOFFLoadConfig() {
       printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 4);
     }
   }
+
+  if (Tables.GuardLJmpTableVA) {
+    ListScope LS(W, "GuardLJmpTable");
+    printRVATable(Tables.GuardLJmpTableVA, Tables.GuardLJmpTableCount, 4);
+  }
 }
 
 template <typename T>
@@ -879,6 +886,9 @@ void COFFDumper::printCOFFLoadConfig(con
   W.printHex("GuardRFVerifyStackPointerFunctionPointer",
              Conf->GuardRFVerifyStackPointerFunctionPointer);
   W.printHex("HotPatchTableOffset", Conf->HotPatchTableOffset);
+
+  Tables.GuardLJmpTableVA = Conf->GuardLongJumpTargetTable;
+  Tables.GuardLJmpTableCount = Conf->GuardLongJumpTargetCount;
 }
 
 void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {




More information about the llvm-commits mailing list