Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10640bf9 authored by Florian Mayer's avatar Florian Mayer Committed by Automerger Merge Worker
Browse files

Merge "Add test for invalid setjmp in MTE" into main am: 851c8574

parents db71f06e 851c8574
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -371,6 +371,11 @@ cc_test {
        },
    },

    sanitize: {
        memtag_heap: true,
        memtag_stack: true,
    },

    shared_libs: [
        "libbase",
        "libcutils",
+50 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <linux/prctl.h>
#include <malloc.h>
#include <pthread.h>
#include <setjmp.h>
#include <stdlib.h>
#include <sys/capability.h>
#include <sys/mman.h>
@@ -601,6 +602,55 @@ TEST_P(SizeParamCrasherTest, mte_underflow) {
#endif
}

__attribute__((noinline)) void mte_illegal_setjmp_helper(jmp_buf& jump_buf) {
  // Because the detection of illegal setjmp is done relative to the SP in setjmp,
  // we need to make sure this stack frame is bigger than the one of setjmp.
  // TODO(fmayer): fix that bug and remove the workaround.
  volatile char buf[1024];
  buf[0] = '1';
  setjmp(jump_buf);
}

TEST_F(CrasherTest, mte_illegal_setjmp) {
  // This setjmp is illegal because it jumps back into a function that already returned.
  // Quoting man 3 setjmp:
  //     If the function which called setjmp() returns before longjmp() is
  //     called, the behavior is undefined.  Some kind of subtle or
  //     unsubtle chaos is sure to result.
  // https://man7.org/linux/man-pages/man3/longjmp.3.html
#if defined(__aarch64__)
  if (!mte_supported()) {
    GTEST_SKIP() << "Requires MTE";
  }

  int intercept_result;
  unique_fd output_fd;
  StartProcess([&]() {
    SetTagCheckingLevelSync();
    jmp_buf jump_buf;
    mte_illegal_setjmp_helper(jump_buf);
    longjmp(jump_buf, 1);
  });

  StartIntercept(&output_fd);
  FinishCrasher();
  AssertDeath(SIGABRT);
  FinishIntercept(&intercept_result);

  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";

  std::string result;
  ConsumeFd(std::move(output_fd), &result);

  // In our test-case, we have a NEGATIVE stack adjustment, which is being
  // interpreted as unsigned integer, and thus is "too large".
  // TODO(fmayer): fix the error message for this
  ASSERT_MATCH(result, R"(memtag_handle_longjmp: stack adjustment too large)");
#else
  GTEST_SKIP() << "Requires aarch64";
#endif
}

TEST_F(CrasherTest, mte_async) {
#if defined(__aarch64__)
  if (!mte_supported()) {