Add test for invalid setjmp in MTE
BYPASS_INCLUSIVE_LANGUAGE_REASON=man is for manpage
Test: atest debuggerd_test
Change-Id: I774095b79baadb4f692f4b97b47df80e635e3a1c
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 5cc2b3a..3135d9e 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -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 @@
#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()) {