summaryrefslogtreecommitdiff
path: root/common_modules
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-09-28 09:08:55 -0400
committerGitHub <[email protected]>2026-09-28 09:08:55 -0400
commit7495b0237459ca703ff86cc27a8a975c0f0292f4 (patch)
tree00489afc06380d09253c32c824a55e698eb9961d /common_modules
parentd55fe1ef2f9e512439c9b1147204683e7feeeafa (diff)
Merge commit from fork
A memory-protected module names the kernel objects it wants operated on by address, and the Module Manager decided whether a privileged service could dereference that address by asking only whether it fell outside the module. The object pool is outside every module, so that test was satisfied by an address shifted into the interior of one of the module's own privileged allocations, which denotes no object at all. The bytes such an address presents as a control block are bytes the module put there through ordinary create and set services, so the control block ID at the front of them could be made to read as any type the module chose, and the _txe_ layer's ID test then agreed. A module could therefore have the kernel read and write fields of an object that does not exist, at an address it picked; the reported chain reaches a privileged memset across an attacker-chosen range that way. Authentication now answers the question the location test could not: is this the exact address of a live kernel object of the type this service expects. It is answered from the kernel's created list for the type, which the create and delete services maintain, so membership establishes at once that the address is an object start rather than an address inside an object, that the object is of this type, and that it has not been deleted. That list is also what makes an object the application created and shared with a module authenticable at all, since the manager allocated no such object and has no record of its own to consult, so sharing keeps working and needs no new registration API. Nothing a module can influence is used to establish a type. An earlier form of this fix accepted an address that was the exact start of one of the calling module's own allocations of the right size and then took the type from the control block ID, which is cheaper -- a module's allocation list is much shorter than the system's created list for a type. The tests here refused it: a byte pool, a mutex and a timer are all the same size on a 32-bit target, so an allocation created as one of them and presented as another passed both the address and the size test, leaving the ID as the only thing between the module and a type confusion. The ID is still checked, after the created list has settled the question, because it is the test the _txe_ services make and it is compiled away with them under TX_DISABLE_ERROR_CHECKING. An address a module named is not read at all until a kernel record says there is an object there. All 58 object-using dispatchers now pass the object type rather than a control block size, since a size cannot establish a type. Both scans are bounded by the counts the kernel and the manager maintain beside their lists, so the cost of one check is bounded and a list whose links have been damaged cannot make a scan run on, and both run with interrupts disabled, which is the protection those lists are maintained under and which adds no blocking point or priority inversion to a kernel request. The cost is a walk of the created list for the type, paid only by memory-protected modules; the size-based check is kept for dispatchers outside this repository and hardened to refuse object pool interiors, which is the part of the attack it can see without a type. Two further changes close paths the authentication alone would leave open. Thread reset now refuses a thread that carries no module instance: such a thread is authentic, can be found by name and satisfies reset's own state test, and reset reads the shell entry function out of that instance, so a null one was followed in privileged mode. Object deallocation now clears the control block ID as it gives memory back, so an object freed without being deleted first stops being vouched for at the moment the manager stops owning its memory, rather than returning to the pool still carrying a valid ID for the next allocation placed there to present. The 120 expectations in the new test offer every aligned interior offset of a legitimate object as a foreign type, with that type's own ID planted at the offset, and assert that none is accepted; they cover all eight object types against each other, uncreated allocations, deleted objects, freed addresses that have been handed out again, objects the application owns and memory that merely carries a plausible ID, objects another module allocated, and the bounds on both scans. Reverting the object checks to the permissive policy fails 89 of them; removing the thread reset guard makes the test die with SIGSEGV inside the reset path; removing the ID clearing in deallocation fails 2. All 99 tests pass in each of the five configurations the tree builds with GCC 14. Assisted-by: Claude Code (Opus 5) <[email protected]>
Diffstat (limited to 'common_modules')
-rw-r--r--common_modules/module_manager/inc/txm_module_manager_dispatch.h118
-rw-r--r--common_modules/module_manager/inc/txm_module_manager_util.h30
-rw-r--r--common_modules/module_manager/src/txm_module_manager_object_deallocate.c23
-rw-r--r--common_modules/module_manager/src/txm_module_manager_thread_reset.c16
-rw-r--r--common_modules/module_manager/src/txm_module_manager_util.c814
5 files changed, 940 insertions, 61 deletions
diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h
index 3763d35d..9c0e5d21 100644
--- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h
+++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h
@@ -10,6 +10,8 @@
**************************************************************************/
// Portions of this file were generated with AI assistance.
+// Some portions generated by Claude Code (Opus 5).
+
/**************************************************************************/
/**************************************************************************/
@@ -34,7 +36,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(VOID *)))
@@ -102,7 +104,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -136,7 +138,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -189,7 +191,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -270,7 +272,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -336,7 +338,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(VOID *)))
@@ -406,7 +408,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -440,7 +442,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -496,7 +498,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -604,7 +606,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -696,7 +698,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -728,7 +730,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, extra_parameters[1], sizeof(ULONG)))
@@ -765,7 +767,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -814,7 +816,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -897,7 +899,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -924,7 +926,7 @@ VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *);
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* Since we need to write to the object, ensure it's valid. */
@@ -1001,7 +1003,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1030,7 +1032,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1059,7 +1061,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -1114,7 +1116,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -1213,7 +1215,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1235,7 +1237,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1298,7 +1300,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1326,7 +1328,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1351,7 +1353,7 @@ TX_QUEUE *queue_ptr;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* We need to get the size of the message from the queue. */
@@ -1386,7 +1388,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -1441,7 +1443,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -1540,7 +1542,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1565,7 +1567,7 @@ TX_QUEUE *queue_ptr;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* We need to get the max size of the buffer from the queue. */
@@ -1597,7 +1599,7 @@ TX_QUEUE *queue_ptr;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* We need to get the size of the message from the queue. */
@@ -1629,7 +1631,7 @@ VOID (*queue_send_notify)(TX_QUEUE *);
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* Since we need to write to the object, ensure it's valid. */
@@ -1673,7 +1675,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1730,7 +1732,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1759,7 +1761,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1787,7 +1789,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -1836,7 +1838,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -1917,7 +1919,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1939,7 +1941,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -1964,7 +1966,7 @@ VOID (*semaphore_put_notify)(TX_SEMAPHORE *);
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* Since we need to write to the object, ensure it's valid. */
@@ -2071,7 +2073,7 @@ ALIGN_TYPE stack_status;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2121,7 +2123,7 @@ VOID (*thread_entry_exit_notify)(TX_THREAD *, UINT);
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
/* Since we need to write to the object, ensure it's valid. */
@@ -2188,7 +2190,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -2274,7 +2276,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
@@ -2421,7 +2423,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(UINT)))
@@ -2455,7 +2457,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(UINT)))
@@ -2492,7 +2494,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2514,7 +2516,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2571,7 +2573,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2600,7 +2602,7 @@ TX_THREAD *thread_ptr;
{
return(TXM_MODULE_INVALID_MEMORY);
}
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2650,7 +2652,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2674,7 +2676,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(ULONG)))
@@ -2701,7 +2703,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2749,7 +2751,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2773,7 +2775,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2870,7 +2872,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2892,7 +2894,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
}
@@ -2925,7 +2927,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *)))
@@ -2975,7 +2977,7 @@ ALIGN_TYPE return_value;
if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION)
{
- if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER)))
+ if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT))
return(TXM_MODULE_INVALID_MEMORY);
if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG)))
diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h
index 45c7f409..77631bea 100644
--- a/common_modules/module_manager/inc/txm_module_manager_util.h
+++ b/common_modules/module_manager/inc/txm_module_manager_util.h
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Some portions generated by Claude Code (Opus 5).
+
/**************************************************************************/
/**************************************************************************/
@@ -89,10 +91,31 @@
((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, buffer_ptr, buffer_size)) || \
((void *) (buffer_ptr) == TX_NULL))
-/* Kernel objects should be outside the module at the very least. */
+/* Kernel objects a module names must be authenticated before a privileged service is
+ allowed to dereference them. Being outside the module is necessary but nowhere near
+ sufficient: the manager's object pool is outside every module, so an address shifted
+ into the interior of one of the module's own privileged allocations satisfies that
+ test while denoting no object at all. Authentication answers the question the
+ location test cannot -- is this the exact address of a live kernel object of the type
+ this service expects -- and it answers it from manager and kernel bookkeeping rather
+ than from fields of the purported object, which a module can influence.
+
+ TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE is the complete check and is what
+ the dispatch table uses. It is given the object type rather than a control block size
+ so that it can also establish the type, which a size cannot: distinct object types of
+ equal size exist.
+
+ TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE is retained for dispatchers outside this
+ repository that pass a size. It authenticates addresses in the manager's object pool,
+ which is what the shifted-pointer attack needs, but without a type it can neither
+ establish the type nor authenticate an application-owned object, so in-repository code
+ should use the typed form. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, obj_ptr, obj_size) \
(_txm_module_manager_param_check_object_for_use(module_instance, obj_ptr, obj_size))
+#define TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, obj_ptr, obj_type) \
+ (_txm_module_manager_param_check_typed_object_for_use(module_instance, obj_ptr, obj_type))
+
/* When creating an object, the object must be inside the object pool. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_CREATION(module_instance, obj_ptr, obj_size) \
(_txm_module_manager_param_check_object_for_creation(module_instance, obj_ptr, obj_size))
@@ -122,6 +145,11 @@ UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_
UCHAR _txm_module_manager_created_object_check(TXM_MODULE_INSTANCE *module_instance, void *object_ptr);
UINT _txm_module_manager_param_check_object_for_creation(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
+UINT _txm_module_manager_param_check_typed_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, UINT object_type);
+UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
+UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size);
+UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type);
+UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type);
UINT _txm_module_manager_util_code_allocation_size_and_alignment_get(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_alignment_dest, ULONG *code_allocation_size_dest);
#endif
diff --git a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c
index 95e28e4d..c34a0005 100644
--- a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c
+++ b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Some portions generated by Claude Code (Opus 5).
+
/**************************************************************************/
/**************************************************************************/
@@ -125,6 +127,27 @@ UINT return_value;
}
}
+ /* Clear the first word of the object being given back, which for every kernel
+ object is its control block ID.
+
+ Object authentication reads that ID to establish the type of an object and
+ that it is still created, having first established that the address is the
+ exact start of an allocation. The kernel clears the ID when it deletes an
+ object, so the ordinary sequence of delete and then deallocate has already
+ cleared it. What has not is a deallocation of an object that was never
+ deleted: the memory returns to the pool still carrying a valid ID, and the
+ next allocation to be placed there is a raw allocation that presents one.
+ Clearing it here means the manager stops vouching for a control block at
+ the moment it stops owning the memory, whatever order the module chose.
+
+ An allocation too small to hold an ID cannot be presenting one, and is
+ left alone rather than written past its end. */
+ if (module_allocated_object_ptr -> txm_module_object_size >= ((ULONG) sizeof(ULONG)))
+ {
+
+ *((ULONG *) object_ptr) = TX_CLEAR_ID;
+ }
+
/* Release the object memory. */
return_value = (ULONG) _txe_byte_release((VOID *) module_allocated_object_ptr);
}
diff --git a/common_modules/module_manager/src/txm_module_manager_thread_reset.c b/common_modules/module_manager/src/txm_module_manager_thread_reset.c
index 75dd4a49..1a33964e 100644
--- a/common_modules/module_manager/src/txm_module_manager_thread_reset.c
+++ b/common_modules/module_manager/src/txm_module_manager_thread_reset.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Some portions generated by Claude Code (Opus 5).
+
/**************************************************************************/
/**************************************************************************/
@@ -106,6 +108,20 @@ TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info;
status = TX_NOT_DONE;
}
}
+
+ /* Resetting a thread means rebuilding its stack around a module's shell entry
+ function, so the thread has to be one a module manager created. A thread the
+ application created carries no module instance, and the fields this function
+ goes on to read from it -- the shell entry function it builds the new stack
+ frame around -- would be read through a null pointer in privileged mode. A
+ module can name such a thread: any thread the system created can be found by
+ name, and one that has run to completion satisfies the state test above. */
+ if (thread_ptr -> tx_thread_module_instance_ptr == TX_NULL)
+ {
+
+ /* Not a module thread, so there is nothing here to reset. */
+ status = TX_NOT_DONE;
+ }
}
/* Is the request valid? */
diff --git a/common_modules/module_manager/src/txm_module_manager_util.c b/common_modules/module_manager/src/txm_module_manager_util.c
index 78031b5f..1b60f900 100644
--- a/common_modules/module_manager/src/txm_module_manager_util.c
+++ b/common_modules/module_manager/src/txm_module_manager_util.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Some portions generated by Claude Code (Opus 5).
+
/**************************************************************************/
/**************************************************************************/
@@ -25,6 +27,15 @@
#define TX_SOURCE_CODE
+#include "tx_api.h"
+#include "tx_thread.h"
+#include "tx_timer.h"
+#include "tx_queue.h"
+#include "tx_event_flags.h"
+#include "tx_semaphore.h"
+#include "tx_mutex.h"
+#include "tx_block_pool.h"
+#include "tx_byte_pool.h"
#include "txm_module.h"
#include "txm_module_manager_util.h"
@@ -461,11 +472,414 @@ UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *modu
return(TX_FALSE);
}
- /* Determine if the object pointer is inside the module object pool. */
+ /* Determine if the object is outside the calling module. */
if (TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, object_ptr, object_size) == TX_FALSE)
{
- /* Object pointer is not inside the object pool, which is invalid. */
+ /* Object pointer is not outside the module, which is invalid. */
+ return(TX_FALSE);
+ }
+
+ /* Being outside the module does not make an address an object. The manager's
+ object pool is outside every module, so an address shifted into the interior of
+ one of this module's own privileged allocations satisfies the test above while
+ denoting no object at all, and the bytes the shifted address then presents as a
+ control block are bytes the module chose through ordinary create and set
+ services. An address in the object pool is therefore only usable if it is the
+ exact address the manager handed out for an allocation of this size.
+
+ This function is given a size rather than a type, so it can go no further than
+ that: it cannot establish which type of object it is, and it cannot authenticate
+ an application-owned object outside the pool. Dispatchers in this repository use
+ _txm_module_manager_param_check_typed_object_for_use, which does both. */
+ if ((_txm_module_manager_object_pool_created == TX_TRUE) &&
+ (object_ptr >= (ALIGN_TYPE) _txm_module_manager_object_pool.tx_byte_pool_start) &&
+ (object_ptr < (ALIGN_TYPE) (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size)))
+ {
+
+ if (_txm_module_manager_allocated_object_check(module_instance, object_ptr, object_size) == TX_FALSE)
+ {
+
+ /* An address in the object pool that is not the exact start of one of this
+ module's allocations, which is invalid. */
+ return(TX_FALSE);
+ }
+ }
+
+ /* Define application-specific object memory check. */
+#ifdef TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_CHECK
+
+ /* Bring in the application-spefic objeft memory check, defined by the user. */
+ TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_CHECK
+#endif /* TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_ENABLE */
+
+ /* Everything is okay with the object, return TX_TRUE. */
+ return(TX_TRUE);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_object_type_size_get PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function returns the size of the control block belonging to a */
+/* module object type. It is the size a service of that type is */
+/* entitled to dereference, and the size the manager recorded when it */
+/* allocated object memory for that type. */
+/* */
+/* INPUT */
+/* */
+/* object_type Module object type */
+/* object_size Destination for the control block */
+/* size of that type */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE Known object type */
+/* TX_FALSE Unknown object type */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_param_check_typed_object_for_use */
+/* Module object authentication */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size)
+{
+
+UINT status;
+
+
+ /* Assume the type is one this manager knows. */
+ status = TX_TRUE;
+
+ switch (object_type)
+ {
+
+ case TXM_BLOCK_POOL_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_BLOCK_POOL);
+ break;
+
+ case TXM_BYTE_POOL_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_BYTE_POOL);
+ break;
+
+ case TXM_EVENT_FLAGS_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_EVENT_FLAGS_GROUP);
+ break;
+
+ case TXM_MUTEX_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_MUTEX);
+ break;
+
+ case TXM_QUEUE_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_QUEUE);
+ break;
+
+ case TXM_SEMAPHORE_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_SEMAPHORE);
+ break;
+
+ case TXM_THREAD_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_THREAD);
+ break;
+
+ case TXM_TIMER_OBJECT:
+
+ *object_size = (ULONG) sizeof(TX_TIMER);
+ break;
+
+ default:
+
+ /* Not a type the manager authenticates. Report it rather than guessing a
+ size, so that a caller cannot be given a range to validate that has no
+ relationship to the object the service will dereference. */
+ *object_size = ((ULONG) 0);
+ status = TX_FALSE;
+ break;
+ }
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_allocated_object_check PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function determines whether an address is the exact address */
+/* the manager handed the specified module for one of its object */
+/* allocations, and whether that allocation is the size the caller */
+/* expects. */
+/* */
+/* The allocation list is the manager's own record, built as it hands */
+/* object memory out. Comparing against it is what makes an address */
+/* inside the object pool distinguishable from the exact start of an */
+/* allocation. Reading a header in front of a candidate address cannot */
+/* make that distinction: the bytes in front of an address chosen */
+/* inside an allocation are part of the object, and a module can place */
+/* values there through ordinary create and set services. */
+/* */
+/* INPUT */
+/* */
+/* module_instance Requesting module instance pointer*/
+/* object_ptr Address of object memory area */
+/* object_size Expected size of the allocation */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE An exact allocation of that size */
+/* TX_FALSE Anything else */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_param_check_object_for_use */
+/* Module object authentication */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+TXM_MODULE_ALLOCATED_OBJECT *allocated_object_ptr;
+ULONG objects_examined;
+UINT status;
+
+
+ /* Assume the address is not one of this module's allocations. */
+ status = TX_FALSE;
+
+ /* Disable interrupts. The allocation list is maintained by threads holding the
+ manager protection mutex, so a scan that runs to completion with interrupts
+ disabled cannot observe it being changed, and unlike taking the mutex it adds
+ no blocking point and no priority inversion to a kernel request. */
+ TX_DISABLE
+
+ allocated_object_ptr = module_instance -> txm_module_instance_object_list_head;
+ objects_examined = ((ULONG) 0);
+
+ /* Loop through the objects allocated to this module. The loop is bounded by the
+ count the manager maintains alongside the list, so the cost of one check is
+ bounded by the number of objects this module has allocated, and a list whose
+ links have been damaged cannot make the scan run on. */
+ while ((objects_examined < module_instance -> txm_module_instance_object_list_count) &&
+ (allocated_object_ptr != TX_NULL))
+ {
+
+ /* The address the module was given is the one immediately after the private
+ header, so that is the only address in this allocation that names it. */
+ if (((ALIGN_TYPE) (allocated_object_ptr + 1)) == object_ptr)
+ {
+
+ /* Is the allocation the size the caller expects? An allocation made for a
+ smaller object does not become a larger one because a service was asked
+ to treat it as one. */
+ if (allocated_object_ptr -> txm_module_object_size == object_size)
+ {
+
+ status = TX_TRUE;
+ }
+
+ /* An address matches at most one allocation, so there is nothing further
+ to look at either way. */
+ break;
+ }
+
+ /* Move to the next allocated object. */
+ objects_examined++;
+ allocated_object_ptr = allocated_object_ptr -> txm_module_allocated_object_next;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_param_check_typed_object_for_use */
+/* PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function authenticates a kernel object a module has named, */
+/* before a privileged service is allowed to dereference it. It */
+/* establishes that the address is the exact address of a live kernel */
+/* object of the type the service expects. */
+/* */
+/* The address is accepted only if it is on the kernel's created list */
+/* for that type. That list is the record the create and delete */
+/* services maintain, so being on it establishes at once that the */
+/* address is an object start rather than an address inside an object, */
+/* that the object is of this type, and that it has not been deleted. */
+/* It is also how an object the application created and shared with a */
+/* module is authenticated, since the manager allocated no such object */
+/* and has no record of its own to consult. */
+/* */
+/* Nothing a module can influence is used to establish a type. In */
+/* particular the control block ID is not, on its own, evidence of */
+/* anything: a module can arrange for the value of an ID to appear */
+/* inside an object it legitimately owns, which is what lets a shifted */
+/* pointer pass an ID test, and distinct object types of equal size */
+/* exist, so an ID is not even a type at an address known to be an */
+/* object start. It is checked, after the created list has settled the */
+/* question, because it is the check the _txe_ services make and it is */
+/* compiled away with them under TX_DISABLE_ERROR_CHECKING. */
+/* */
+/* INPUT */
+/* */
+/* module_instance Requesting module instance pointer*/
+/* object_ptr Address of object memory area */
+/* object_type Module object type the service */
+/* expects */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE Authenticated object pointer */
+/* TX_FALSE Invalid object pointer */
+/* */
+/* CALLS */
+/* */
+/* _txm_module_manager_object_type_size_get */
+/* Get control block size */
+/* _txm_module_manager_created_object_type_check */
+/* Check kernel created list */
+/* _txm_module_manager_object_id_check Check control block ID */
+/* */
+/* CALLED BY */
+/* */
+/* txm_module_manager_* Module manager functions */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_param_check_typed_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, UINT object_type)
+{
+
+ULONG object_size;
+UINT exact_object;
+
+
+ /* Determine if the object pointer is NULL. */
+ if ((void *) object_ptr == TX_NULL)
+ {
+
+ /* Object pointer is NULL, which is invalid. */
+ return(TX_FALSE);
+ }
+
+ /* Pickup the size of the control block this type of service dereferences. */
+ if (_txm_module_manager_object_type_size_get(object_type, &object_size) == TX_FALSE)
+ {
+
+ /* Not an object type this manager authenticates, so it cannot be used. */
+ return(TX_FALSE);
+ }
+
+ /* Determine if the object is outside the calling module. A kernel object inside
+ the module's own memory is one the module can write behind the kernel's back,
+ so it is rejected here as it always has been. This also rejects a size that
+ wraps when added to the address. */
+ if (TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, object_ptr, object_size) == TX_FALSE)
+ {
+
+ /* Object pointer is not outside the module, which is invalid. */
+ return(TX_FALSE);
+ }
+
+ /* Establish that the address is the exact address of a live object of this type,
+ from the kernel's created list for the type. That list is the record the create
+ and delete services maintain, so being on it establishes at once that the
+ address is an object start, that the object is of this type, and that it has not
+ been deleted.
+
+ It is deliberately the only ground on which an address is accepted. The
+ manager's own allocation list would establish the address and the size of an
+ object a module allocated, and would do it by walking a shorter list, but it
+ records no type, and the type cannot then be taken from the control block
+ itself: distinct object types of equal size exist -- on a 32-bit target a byte
+ pool, a mutex and a timer are all the same size -- so a control block whose ID
+ has been made to read as one of them would be accepted as that type. Nothing a
+ module can influence is used to establish a type.
+
+ The address is not dereferenced to reach this decision. An address a module
+ named is not read until a kernel record says there is an object there. */
+ exact_object = _txm_module_manager_created_object_type_check(object_ptr, object_type);
+
+ if (exact_object == TX_FALSE)
+ {
+
+ /* The address is not the start of a live object of this type. */
+ return(TX_FALSE);
+ }
+
+ /* The address is a live object of the requested type. Confirm it against the
+ control block's own ID, which is the check the _txe_ services would make and
+ which is compiled away with them under TX_DISABLE_ERROR_CHECKING. */
+ if (_txm_module_manager_object_id_check(object_ptr, object_type) == TX_FALSE)
+ {
+
+ /* The created list and the control block disagree, so the object is not in a
+ state the manager is prepared to vouch for. */
return(TX_FALSE);
}
@@ -485,6 +899,402 @@ UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *modu
/* */
/* FUNCTION RELEASE */
/* */
+/* _txm_module_manager_created_object_type_check PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function determines whether an address is the exact address */
+/* of an object on the kernel's created list for a module object type. */
+/* */
+/* This is how an object the application created and shared with a */
+/* module is authenticated. Such an object is not in the manager's */
+/* object pool and the manager has no allocation record of it, so the */
+/* kernel's own created list is the only record of it that a module */
+/* cannot influence. Being on that list establishes at once that the */
+/* address is an object start, that the object is of this type, and */
+/* that it is created. */
+/* */
+/* INPUT */
+/* */
+/* object_ptr Address of object memory area */
+/* object_type Module object type */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE A created object of that type */
+/* TX_FALSE Anything else */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_param_check_typed_object_for_use */
+/* Module object authentication */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+ULONG objects_examined;
+ULONG objects_created;
+ALIGN_TYPE candidate_ptr;
+UINT status;
+TX_BLOCK_POOL *block_pool_ptr;
+TX_BYTE_POOL *byte_pool_ptr;
+TX_EVENT_FLAGS_GROUP *event_flags_ptr;
+TX_MUTEX *mutex_ptr;
+TX_QUEUE *queue_ptr;
+TX_SEMAPHORE *semaphore_ptr;
+TX_THREAD *thread_ptr;
+TX_TIMER *timer_ptr;
+
+
+ /* Assume the address is not on the created list for this type. */
+ status = TX_FALSE;
+
+ /* Disable interrupts. The created lists are maintained with interrupts disabled,
+ so a scan that runs to completion this way sees a consistent list, and it adds
+ no blocking point to a kernel request. The cost of one check is bounded by the
+ number of objects of this type the system has created, which is the price of
+ authenticating an object the manager did not allocate; a module using its own
+ allocated objects does not reach this function. */
+ TX_DISABLE
+
+ /* Start each list from its head and pick up the count that bounds the walk, so a
+ list whose links have been damaged cannot make the scan run on. */
+ switch (object_type)
+ {
+
+ case TXM_BLOCK_POOL_OBJECT:
+
+ block_pool_ptr = _tx_block_pool_created_ptr;
+ objects_created = _tx_block_pool_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (block_pool_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) block_pool_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next;
+ }
+ break;
+
+ case TXM_BYTE_POOL_OBJECT:
+
+ byte_pool_ptr = _tx_byte_pool_created_ptr;
+ objects_created = _tx_byte_pool_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (byte_pool_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) byte_pool_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next;
+ }
+ break;
+
+ case TXM_EVENT_FLAGS_OBJECT:
+
+ event_flags_ptr = _tx_event_flags_created_ptr;
+ objects_created = _tx_event_flags_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (event_flags_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) event_flags_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ event_flags_ptr = event_flags_ptr -> tx_event_flags_group_created_next;
+ }
+ break;
+
+ case TXM_MUTEX_OBJECT:
+
+ mutex_ptr = _tx_mutex_created_ptr;
+ objects_created = _tx_mutex_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (mutex_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) mutex_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ mutex_ptr = mutex_ptr -> tx_mutex_created_next;
+ }
+ break;
+
+ case TXM_QUEUE_OBJECT:
+
+ queue_ptr = _tx_queue_created_ptr;
+ objects_created = _tx_queue_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (queue_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) queue_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ queue_ptr = queue_ptr -> tx_queue_created_next;
+ }
+ break;
+
+ case TXM_SEMAPHORE_OBJECT:
+
+ semaphore_ptr = _tx_semaphore_created_ptr;
+ objects_created = _tx_semaphore_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (semaphore_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) semaphore_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next;
+ }
+ break;
+
+ case TXM_THREAD_OBJECT:
+
+ thread_ptr = _tx_thread_created_ptr;
+ objects_created = _tx_thread_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (thread_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) thread_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ thread_ptr = thread_ptr -> tx_thread_created_next;
+ }
+ break;
+
+ case TXM_TIMER_OBJECT:
+
+ timer_ptr = _tx_timer_created_ptr;
+ objects_created = _tx_timer_created_count;
+ objects_examined = ((ULONG) 0);
+
+ while ((objects_examined < objects_created) && (timer_ptr != TX_NULL))
+ {
+ candidate_ptr = (ALIGN_TYPE) timer_ptr;
+ if (candidate_ptr == object_ptr)
+ {
+ status = TX_TRUE;
+ break;
+ }
+ objects_examined++;
+ timer_ptr = timer_ptr -> tx_timer_created_next;
+ }
+ break;
+
+ default:
+
+ /* Not a type the manager authenticates. */
+ break;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _txm_module_manager_object_id_check PORTABLE C */
+/* 6.4.3 */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function determines whether the control block at an object */
+/* start carries the ID of a module object type. The kernel writes */
+/* that ID when it creates an object and clears it when it deletes */
+/* one, so at an address already established to be an object start the */
+/* ID reports both the type and whether the object is still created. */
+/* */
+/* This check must not be used on its own to decide that an address is */
+/* an object. A module can place the value of an ID inside an object */
+/* it legitimately owns, so an ID found at an address the manager has */
+/* not otherwise authenticated proves nothing. */
+/* */
+/* The check matters most where the error checking layer is absent: */
+/* with TX_DISABLE_ERROR_CHECKING the _txe_ services that would */
+/* otherwise test the ID are compiled away, and this is then the only */
+/* ID test between a module and a privileged dereference. */
+/* */
+/* INPUT */
+/* */
+/* object_ptr Address of an object start */
+/* object_type Module object type */
+/* */
+/* OUTPUT */
+/* */
+/* TX_TRUE A created object of that type */
+/* TX_FALSE Anything else */
+/* */
+/* CALLS */
+/* */
+/* None */
+/* */
+/* CALLED BY */
+/* */
+/* _txm_module_manager_param_check_typed_object_for_use */
+/* Module object authentication */
+/* */
+/* RELEASE HISTORY */
+/* */
+/* DATE NAME DESCRIPTION */
+/* */
+/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */
+/* contributors */
+/* */
+/**************************************************************************/
+UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type)
+{
+
+TX_INTERRUPT_SAVE_AREA
+
+ULONG object_id;
+ULONG expected_id;
+UINT status;
+
+
+ /* Read the ID through a pointer to the type the caller named, so that the field
+ read is the one that type declares rather than an assumed offset. */
+ TX_DISABLE
+
+ switch (object_type)
+ {
+
+ case TXM_BLOCK_POOL_OBJECT:
+
+ object_id = ((TX_BLOCK_POOL *) object_ptr) -> tx_block_pool_id;
+ expected_id = TX_BLOCK_POOL_ID;
+ break;
+
+ case TXM_BYTE_POOL_OBJECT:
+
+ object_id = ((TX_BYTE_POOL *) object_ptr) -> tx_byte_pool_id;
+ expected_id = TX_BYTE_POOL_ID;
+ break;
+
+ case TXM_EVENT_FLAGS_OBJECT:
+
+ object_id = ((TX_EVENT_FLAGS_GROUP *) object_ptr) -> tx_event_flags_group_id;
+ expected_id = TX_EVENT_FLAGS_ID;
+ break;
+
+ case TXM_MUTEX_OBJECT:
+
+ object_id = ((TX_MUTEX *) object_ptr) -> tx_mutex_id;
+ expected_id = TX_MUTEX_ID;
+ break;
+
+ case TXM_QUEUE_OBJECT:
+
+ object_id = ((TX_QUEUE *) object_ptr) -> tx_queue_id;
+ expected_id = TX_QUEUE_ID;
+ break;
+
+ case TXM_SEMAPHORE_OBJECT:
+
+ object_id = ((TX_SEMAPHORE *) object_ptr) -> tx_semaphore_id;
+ expected_id = TX_SEMAPHORE_ID;
+ break;
+
+ case TXM_THREAD_OBJECT:
+
+ object_id = ((TX_THREAD *) object_ptr) -> tx_thread_id;
+ expected_id = TX_THREAD_ID;
+ break;
+
+ case TXM_TIMER_OBJECT:
+
+ object_id = ((TX_TIMER *) object_ptr) -> tx_timer_id;
+ expected_id = TX_TIMER_ID;
+ break;
+
+ default:
+
+ /* Not a type the manager authenticates. Choose values that cannot match. */
+ object_id = TX_CLEAR_ID;
+ expected_id = ~((ULONG) TX_CLEAR_ID);
+ break;
+ }
+
+ /* Restore interrupts. */
+ TX_RESTORE
+
+ if (object_id == expected_id)
+ {
+
+ status = TX_TRUE;
+ }
+ else
+ {
+
+ status = TX_FALSE;
+ }
+
+ return(status);
+}
+
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
/* _txm_module_manager_util_code_allocation_size_and_alignment_get */
/* PORTABLE C */
/* 6.1 */