Add test for invalid setjmp in MTE

BYPASS_INCLUSIVE_LANGUAGE_REASON=man is for manpage

Test: atest debuggerd_test
Change-Id: I774095b79baadb4f692f4b97b47df80e635e3a1c
This commit is contained in:
Florian Mayer 2024-02-28 11:12:11 -08:00
parent eed1c42087
commit e6462f91c2
2 changed files with 55 additions and 0 deletions

View file

@ -371,6 +371,11 @@ cc_test {
},
},
sanitize: {
memtag_heap: true,
memtag_stack: true,
},
shared_libs: [
"libbase",
"libcutils",

View file

@ -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()) {