Skip to content

Commit

Permalink
i#2350 rseq: Fix __rseq_cs_ptr_array parsing crash
Browse files Browse the repository at this point in the history
The __rseq_cs_ptr_array will be relocated, so we should not add the
load offset.

Adds an array to the suite test (previously arrays were only tested
manually using a librseq app).  Creates 2 separate tests to test all 3
section types.

Issue: #2350
  • Loading branch information
derekbruening committed Jul 25, 2019
1 parent 73874cb commit a392a15
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
15 changes: 13 additions & 2 deletions core/unix/module_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down
7 changes: 7 additions & 0 deletions suite/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
10 changes: 10 additions & 0 deletions suite/tests/linux/rseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a392a15

Please sign in to comment.