Merge commit from fork

_txm_module_manager_tx_block_pool_create_dispatch proved that two
ALIGN_TYPE words of the extra-parameter array a module supplies lay
inside the module's data, and then used indices 0 through 3. The two
words it had not proved were read twice each in privileged context:
once by the dispatcher's own buffer check, which takes index 1 as the
pool start and index 2 as the length to range-check it over, and once
when the argument list for _txe_block_pool_create was built. So the
out-of-bounds read was performed by the validation code itself, and
the size the caller's pool start was then validated against was a
word the manager had not proved the module owned.

A module reaches this by calling its kernel dispatcher directly with
an array that ends two words before the boundary of its data or of a
shared region, which the module library's own four-word array never
does. The read window is eight bytes on every module port and there
is nothing in it the module can lengthen.

The extent becomes sizeof(ALIGN_TYPE[4]), which is what the two
siblings of the same shape have always had: queue create validates
four words for four, and byte-pool create three for three. Both
checks on this path are data-only, with no fallback to the portable
code-region check, so the four Cortex-A35 and Cortex-A35 SMP module
port combinations whose data check is the constant (TX_SUCCESS) refuse
these create requests from a memory-protected module before and after
this change alike.

The regression test drives all three create dispatchers and measures
the extent each one validates rather than sampling either side of it:
it anchors the array at the end of each region a module owns and walks
it backwards until the dispatcher accepts, and the smallest room
accepted is the extent. It measures the highest index each dispatcher
uses through what the stubbed service records, so the invariant the
three are checked against is measured on both sides. It also measures
what a module can learn from the answers, since the buffer check is a
comparison against a threshold the module chooses and the dispatcher's
refusal is distinguishable from every status these services return.
Compiled against the previous dispatch header the test reports the
extent as two words and the service reached carrying a word planted
past the end of the region; against this one it reports four.

Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
This commit is contained in:
Frédéric Desbiens
2026-09-28 10:52:12 -04:00
committed by GitHub
parent 35d4137126
commit a967d005f6
3 changed files with 1476 additions and 1 deletions
@@ -21,6 +21,7 @@ set(SOURCE_DIR ${REPO_ROOT}/test/tx/module_manager)
set(module_manager_dir ${REPO_ROOT}/common_modules/module_manager)
set(cortex_a7_module_dir ${REPO_ROOT}/ports_module/cortex_a7/gnu)
set(cortex_m4_module_dir ${REPO_ROOT}/ports_module/cortex_m4/gnu)
add_executable(
threadx_module_manager_thread_kernel_stack_test
@@ -173,3 +174,23 @@ target_compile_options(
add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_object_allocate_overflow_test
threadx_module_manager_object_allocate_overflow_test)
add_executable(
threadx_module_manager_block_pool_parameters_test
${SOURCE_DIR}/threadx_module_manager_block_pool_parameters_test.c
${module_manager_dir}/src/txm_module_manager_util.c)
target_include_directories(
threadx_module_manager_block_pool_parameters_test
PRIVATE ${SOURCE_DIR}
${REPO_ROOT}/common/inc
${REPO_ROOT}/common_modules/inc
${module_manager_dir}/inc
${cortex_m4_module_dir}/inc)
target_compile_options(
threadx_module_manager_block_pool_parameters_test
PRIVATE -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h)
add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_block_pool_parameters_test
threadx_module_manager_block_pool_parameters_test)
File diff suppressed because it is too large Load Diff