diff --git a/core/unix/module_elf.c b/core/unix/module_elf.c index f946d32d371..33856b60e24 100644 --- a/core/unix/module_elf.c +++ b/core/unix/module_elf.c @@ -1688,8 +1688,15 @@ module_init_rseq(module_area_t *ma, bool at_map) goto module_init_rseq_cleanup; /* We assume this is a full mapping and it's safe to read the data * (a partial map shouldn't make it to module list processing). + * We do perform a sanity check to handle unusual non-relocated + * cases (it's possible this array is not in a loaded segment?). */ - rseq_process_entry((struct rseq_cs *)(*ptrs + load_offs), entry_offs); + if (*ptrs < ma->start || *ptrs > ma->end) { + SYSLOG_INTERNAL_WARNING(RSEQ_PTR_ARRAY_SEC_NAME + " is not in memory. Aborting rseq parsing."); + goto module_init_rseq_cleanup; + } + rseq_process_entry((struct rseq_cs *)(*ptrs), entry_offs); ++ptrs; } break; @@ -1713,8 +1720,12 @@ module_init_rseq(module_area_t *ma, bool at_map) int j; for (j = 0; j < sec_hdr->sh_size / sizeof(*array); ++j) { /* We require that the table is loaded. If not, bail. */ - if (array > (struct rseq_cs *)ma->end) + if (array < (struct rseq_cs *)ma->start || + array > (struct rseq_cs *)ma->end) { + SYSLOG_INTERNAL_WARNING(RSEQ_SEC_NAME " is not in memory." + " Aborting rseq parsing."); goto module_init_rseq_cleanup; + } rseq_process_entry(array, entry_offs); ++array; } diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index 62f15b04baf..9e0daa5738e 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -3457,6 +3457,13 @@ if (UNIX) # The rseq feature is Linux-only. # TODO i#2350: Port the assembly in the test to 32-bit, ARM, AArch64. tobuild(linux.rseq linux/rseq.c) + # Test the other sections. Unfortunately we need a separate binary for each. + tobuild(linux.rseq_table linux/rseq.c) + append_property_string(TARGET linux.rseq_table + COMPILE_FLAGS "-DRSEQ_TEST_USE_OLD_SECTION_NAME") + tobuild(linux.rseq_noarray linux/rseq.c) + append_property_string(TARGET linux.rseq_noarray + COMPILE_FLAGS "-DRSEQ_TEST_USE_NO_ARRAY") # Test attaching, which has a separate lazy rseq check. tobuild_api(api.rseq linux/rseq.c "" "" OFF OFF) append_property_string(TARGET api.rseq COMPILE_FLAGS "-DRSEQ_TEST_ATTACH") diff --git a/suite/tests/linux/rseq.c b/suite/tests/linux/rseq.c index eca7e676a8e..37df828878e 100644 --- a/suite/tests/linux/rseq.c +++ b/suite/tests/linux/rseq.c @@ -70,13 +70,23 @@ test_rseq(void) static __u32 id = RSEQ_CPU_ID_UNINITIALIZED; static int restarts = 0; __asm__ __volatile__( +#ifdef RSEQ_TEST_USE_OLD_SECTION_NAME /* Add a table entry. */ ".pushsection __rseq_table, \"aw\"\n\t" +#else + ".pushsection __rseq_cs, \"aw\"\n\t" +#endif ".balign 32\n\t" "1:\n\t" ".long 0, 0\n\t" /* version, flags */ ".quad 2f, 3f-2f, 4f\n\t" /* start_ip, post_commit_offset, abort_ip */ ".popsection\n\t" +#if !defined(RSEQ_TEST_USE_OLD_SECTION_NAME) && !defined(RSEQ_TEST_USE_NO_ARRAY) + /* Add an array section. */ + ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" + ".quad 1b\n\t" + ".popsection\n\t" +#endif /* Although our abort handler has to handle being called (that's all DR * supports), we structure the code to allow directly calling past it, to