From e6462f91c2de269e06346cf7a736c9ec3061e00b Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Wed, 28 Feb 2024 11:12:11 -0800 Subject: [PATCH] Add test for invalid setjmp in MTE BYPASS_INCLUSIVE_LANGUAGE_REASON=man is for manpage Test: atest debuggerd_test Change-Id: I774095b79baadb4f692f4b97b47df80e635e3a1c --- debuggerd/Android.bp | 5 ++++ debuggerd/debuggerd_test.cpp | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp index 439218d4d..235fdfdde 100644 --- a/debuggerd/Android.bp +++ b/debuggerd/Android.bp @@ -371,6 +371,11 @@ cc_test { }, }, + sanitize: { + memtag_heap: true, + memtag_stack: true, + }, + shared_libs: [ "libbase", "libcutils", diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp index 5cc2b3aef..3135d9e50 100644 --- a/debuggerd/debuggerd_test.cpp +++ b/debuggerd/debuggerd_test.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -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()) {