[PATCH] D77767: Prevent stack coloring functions whith setjmp / longjmp

Diogo N. Sampaio via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 9 16:02:34 PDT 2020


dnsampaio added a comment.

Hi @efriedma,
thanks for looking into this.

I created https://bugs.llvm.org/show_bug.cgi?id=45489 to tackle this bug, with further details.

Bare with me, but the C++ code for this is like this:

  file043220.h:#include <setjmp.h>
  file043220.h:struct S38 {
  file043220.h:  long long M0;
  file043220.h:  bool M1;
  file043220.h:};
  file043220.h:struct S37 {
  file043220.h:  char M1;
  file043220.h:  S38 M2;
  file043220.h:  long long M3[4];
  file043220.h:  int M0a;
  file043220.h:  unsigned long long M1a;
  file043220.h:  int M6;
  file043220.h:  S37() : M2(), M3(), M6()  {}
  file043220.h:};
  file043220.h:struct S23 {
  file043220.h:  long long M0[2];
  file043220.h:  __fp16 M1;
  file043220.h:};
  file043220.h:struct S18  {
  file043220.h:  int Bx;
  file043220.h:  long long BM0;
  file043220.h:  long long BM1;
  file043220.h:  long long BM2;
  file043220.h:  long M0;
  file043220.h:  S23 M3;
  file043220.h:  int M4;
  file043220.h:  S18() : BM0(0), M0(42), M3(), M4() {}
  file043220.h:};
  file043220.h:void foo(jmp_buf incoming_jb, S18 P0) __attribute__((noreturn));
  file043220.h:void bar(jmp_buf incoming_jb, S37 P0) __attribute__((noreturn));

  nolto.cpp:#include <assert.h>
  nolto.cpp:#include <stdlib.h>
  nolto.cpp:#include "file043220.h"
  nolto.cpp:void foo(jmp_buf incoming_jb, S18 P0)  {
  nolto.cpp:  assert(P0.M0 == 42);
  nolto.cpp:  exit(0);
  nolto.cpp:}
  nolto.cpp:void bar(jmp_buf incoming_jb, S37 P0)  {
  nolto.cpp:  longjmp(incoming_jb, 1);
  nolto.cpp:}

  lto.cpp:#include <assert.h>
  lto.cpp:#include <alloca.h>
  lto.cpp:#include "file043220.h"
  lto.cpp:signed int main(void) {
  lto.cpp:  {
  lto.cpp:    S37 P0;
  lto.cpp:    jmp_buf jb1;
  lto.cpp:    if (!setjmp(jb1)) {
  lto.cpp:      bar(jb1, P0);
  lto.cpp:    }
  lto.cpp:  }
  lto.cpp:  {
  lto.cpp:    char *V6 = (char *)alloca(128);
  lto.cpp:    __asm volatile("" : : "r"(V6));
  lto.cpp:  }
  lto.cpp:  {
  lto.cpp:    __attribute((aligned(16))) char V7[16];
  lto.cpp:    __asm volatile("" : : "r"(&V7[0]));
  lto.cpp:  }
  lto.cpp:  __asm volatile("" : : "r"(__builtin_return_address(0)));
  lto.cpp:  S18 P1;
  lto.cpp:  jmp_buf jb2;
  lto.cpp:  if (!setjmp(jb2)) {
  lto.cpp:    foo(jb2, P1);
  lto.cpp:  }
  lto.cpp:  return 0;
  lto.cpp:}

>From my understanding, when we join variables with disjoint aliveness, one from before and the other after the long, changing the "pointer" to this new joined variable is dangerous. If it is spilled, it won't be restored by the longjmp.
If I understand correctly, in the example, `S37 P0` and `S18 P1` are selected to share the same stack slot. As the function `bar` is marked as `noreturn`, when performing `bar(jb1, P0);`, the copy of `P0` increments the pointer by 72.
`bar` then calls `longjmp`, that does not restore the pointer value of `P0` as it is spilled. When doing the copy of `P1` for `foo(jb2, P1);`, the read access of `P1` is misaligned by 72.

However, the only reason why we see the bug is because the initialization of `P1` writes to the correct address, just because it does not write to the start of the container, and after Local Stack Slot Allocation it uses a different "pointer". Thanks to that we hit the assert failure for `P1.M0 == 42` inside `foo`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77767/new/

https://reviews.llvm.org/D77767





More information about the llvm-commits mailing list