From bd2e6acbbb8ed994e7c739adb9528a6678a99db0 Mon Sep 17 00:00:00 2001 From: Dmitry Muhomor Date: Tue, 23 Jan 2024 12:34:52 +0200 Subject: [PATCH] memtag_test: move SEGV code checks to device-side binary --- androidtest/memtag/memtag_test.cc | 43 +++++++++++------- .../src/grapheneos/hmalloc/MemtagTest.java | 45 +++++-------------- 2 files changed, 40 insertions(+), 48 deletions(-) diff --git a/androidtest/memtag/memtag_test.cc b/androidtest/memtag/memtag_test.cc index ca491d8..8b6a784 100644 --- a/androidtest/memtag/memtag_test.cc +++ b/androidtest/memtag/memtag_test.cc @@ -204,54 +204,63 @@ u8* alloc_default() { } } -volatile u8 u8_var; +int expected_segv_code; + +#define expect_segv(exp, segv_code) ({\ + expected_segv_code = segv_code; \ + volatile auto val = exp; \ + (void) val; \ + do_context_switch(); \ + fprintf(stderr, "didn't receive SEGV code %i", segv_code); \ + exit(1); }) + +// it's expected that the device is configured to use asymm MTE tag checking mode (sync read checks, +// async write checks) +#define expect_read_segv(exp) expect_segv(exp, SEGV_MTESERR) +#define expect_write_segv(exp) expect_segv(exp, SEGV_MTEAERR) void read_after_free() { u8 *p = alloc_default(); free(p); - volatile u8 v = p[0]; - (void) v; + expect_read_segv(p[0]); } void write_after_free() { u8 *p = alloc_default(); free(p); - p[0] = 1; + expect_write_segv(p[0] = 1); } void underflow_read() { u8 *p = alloc_default(); - volatile u8 v = p[-1]; - (void) v; + expect_read_segv(p[-1]); } void underflow_write() { u8 *p = alloc_default(); - p[-1] = 1; + expect_write_segv(p[-1] = 1); } void overflow_read() { u8 *p = alloc_default(); - volatile u8 v = p[DEFAULT_ALLOC_SIZE + CANARY_SIZE]; - (void) v; + expect_read_segv(p[DEFAULT_ALLOC_SIZE + CANARY_SIZE]); } void overflow_write() { u8 *p = alloc_default(); - p[DEFAULT_ALLOC_SIZE + CANARY_SIZE] = 1; + expect_write_segv(p[DEFAULT_ALLOC_SIZE + CANARY_SIZE] = 1); } void untagged_read() { u8 *p = alloc_default(); p = (u8 *) untag_pointer(p); - volatile u8 v = p[0]; - (void) v; + expect_read_segv(p[0]); } void untagged_write() { u8 *p = alloc_default(); p = (u8 *) untag_pointer(p); - p[0] = 1; + expect_write_segv(p[0] = 1); } map> tests = { @@ -269,8 +278,12 @@ map> tests = { }; void segv_handler(int, siginfo_t *si, void *) { - fprintf(stderr, "SEGV_CODE %i", si->si_code); - exit(139); // standard exit code for SIGSEGV + if (expected_segv_code == 0 || expected_segv_code != si->si_code) { + fprintf(stderr, "received unexpected SEGV_CODE %i", si->si_code); + exit(139); // standard exit code for SIGSEGV + } + + exit(0); } int main(int argc, char **argv) { diff --git a/androidtest/src/grapheneos/hmalloc/MemtagTest.java b/androidtest/src/grapheneos/hmalloc/MemtagTest.java index 8cb7a45..455e0d0 100644 --- a/androidtest/src/grapheneos/hmalloc/MemtagTest.java +++ b/androidtest/src/grapheneos/hmalloc/MemtagTest.java @@ -7,36 +7,15 @@ import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; import org.junit.Test; import org.junit.runner.RunWith; -import java.io.IOException; import java.util.ArrayList; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; @RunWith(DeviceJUnit4ClassRunner.class) public class MemtagTest extends BaseHostJUnit4Test { - private static final String TEST_BINARY = "/data/local/tmp/memtag_test"; - enum Result { - SUCCESS(0, ""), - // it's expected that the device is configured to use asymm MTE tag checking mode - ASYNC_MTE_ERROR(139, "SEGV_CODE 8"), - SYNC_MTE_ERROR(139, "SEGV_CODE 9"), - ; - - public final int exitCode; - public final String stderr; - - Result(int exitCode, String stderr) { - this.exitCode = exitCode; - this.stderr = stderr; - } - } - - private static final int SEGV_EXIT_CODE = 139; - - private void runTest(String name, Result expectedResult) throws DeviceNotAvailableException { + private void runTest(String name) throws DeviceNotAvailableException { var args = new ArrayList(); args.add(TEST_BINARY); args.add(name); @@ -44,52 +23,52 @@ public class MemtagTest extends BaseHostJUnit4Test { var result = getDevice().executeShellV2Command(cmdLine); - assertEquals("process exit code", expectedResult.exitCode, result.getExitCode().intValue()); - assertEquals("stderr", expectedResult.stderr, result.getStderr()); + assertEquals("stderr", "", result.getStderr()); + assertEquals("process exit code", 0, result.getExitCode().intValue()); } @Test public void tag_distinctness() throws DeviceNotAvailableException { - runTest("tag_distinctness", Result.SUCCESS); + runTest("tag_distinctness"); } @Test public void read_after_free() throws DeviceNotAvailableException { - runTest("read_after_free", Result.SYNC_MTE_ERROR); + runTest("read_after_free"); } @Test public void write_after_free() throws DeviceNotAvailableException { - runTest("write_after_free", Result.ASYNC_MTE_ERROR); + runTest("write_after_free"); } @Test public void underflow_read() throws DeviceNotAvailableException { - runTest("underflow_read", Result.SYNC_MTE_ERROR); + runTest("underflow_read"); } @Test public void underflow_write() throws DeviceNotAvailableException { - runTest("underflow_write", Result.ASYNC_MTE_ERROR); + runTest("underflow_write"); } @Test public void overflow_read() throws DeviceNotAvailableException { - runTest("overflow_read", Result.SYNC_MTE_ERROR); + runTest("overflow_read"); } @Test public void overflow_write() throws DeviceNotAvailableException { - runTest("overflow_write", Result.ASYNC_MTE_ERROR); + runTest("overflow_write"); } @Test public void untagged_read() throws DeviceNotAvailableException { - runTest("untagged_read", Result.SYNC_MTE_ERROR); + runTest("untagged_read"); } @Test public void untagged_write() throws DeviceNotAvailableException { - runTest("untagged_write", Result.ASYNC_MTE_ERROR); + runTest("untagged_write"); } }