summaryrefslogtreecommitdiff
path: root/common_modules/module_manager/inc/txm_module_manager_util.h
diff options
context:
space:
mode:
Diffstat (limited to 'common_modules/module_manager/inc/txm_module_manager_util.h')
-rw-r--r--common_modules/module_manager/inc/txm_module_manager_util.h86
1 files changed, 81 insertions, 5 deletions
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..3583edcc 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
**************************************************************************/
+// Portions of this file were generated with AI assistance.
+
/**************************************************************************/
/**************************************************************************/
@@ -43,8 +45,32 @@
/* Define check macros for modules. */
+/* A port supplies TXM_MODULE_MANAGER_CHECK_INSIDE_DATA to decide whether a caller-supplied
+ range lies inside the module's writable data or shared memory. Ports whose check can tell
+ a read-only region from a writable one also supply the two intent-specific variants below.
+ Ports that cannot make the distinction inherit their single check for both intents, so
+ their behaviour is unchanged. */
+
+#ifndef TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ
+#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) \
+ TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size)
+#endif
+
+#ifndef TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE
+#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) \
+ TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size)
+#endif
+
+/* A range is outside the module's data only when no part of it is reachable by the module.
+ The read intent is used here because it describes the widest set of reachable addresses.
+ A port whose inside check cannot prove the whole range at once must supply its own
+ definition, because negating a partial-range check would report a partly reachable range
+ as being outside the module. */
+
+#ifndef TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA
#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) \
- (!(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size)))
+ (!(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size)))
+#endif
#define TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size) \
(((obj_ptr) < ((obj_ptr) + (obj_size))) && \
@@ -63,12 +89,14 @@
/* Define macros for module. */
+/* The module reads from these ranges, so a read-only region is acceptable. */
#define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, obj_ptr, obj_size) \
- (TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) || \
+ (TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) || \
TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size))
+/* The kernel writes to these ranges, so the module must be able to write them too. */
#define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, obj_ptr, obj_size) \
- TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size)
+ TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size)
#define TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, obj_ptr, obj_size) \
(TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) && \
@@ -89,19 +117,59 @@
((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))
+/* When deleting an object, being allowed to use it is not enough. Deletion is the
+ inverse of creation, so it asks what creation asks: that the object is one this
+ module allocated from the manager's object pool, at the exact address the manager
+ gave it, for an object of this size. A module may hold a pointer to an object it
+ does not own -- the manager's object lookup service hands application-owned
+ objects to modules by name, and sharing an object is what that service is for --
+ and this is what separates using such an object from destroying it. */
+#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, obj_ptr, obj_size) \
+ (_txm_module_manager_allocated_object_check(module_instance, obj_ptr, obj_size))
+
/* Strings we dereference can be in RW/RO/Shared areas. */
#define TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, string_ptr) \
((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, string_ptr, 1)) || \
((void *) (string_ptr) == TX_NULL))
+/* Strings we walk are checked over the whole range the walk may reach: the declared
+ length plus the terminating character that follows it, since a length excludes the
+ terminator and the comparison reads it. A length whose range cannot be expressed
+ is refused rather than truncated. */
+#define TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING_RANGE(module_instance, string_ptr, string_length) \
+ (((((ALIGN_TYPE) (string_length)) < (~((ALIGN_TYPE) 0))) && \
+ (TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, string_ptr, ((ALIGN_TYPE) (string_length)) + ((ALIGN_TYPE) 1)))) || \
+ ((void *) (string_ptr) == TX_NULL))
+
#define TXM_MODULE_MANAGER_UTIL_MAX_VALUE_OF_TYPE_UNSIGNED(type) ((1ULL << (sizeof(type) * 8)) - 1)
#define TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(augend, addend, result) \
@@ -118,10 +186,18 @@
UINT _txm_module_manager_object_memory_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size);
UINT _txm_module_manager_object_size_check(ALIGN_TYPE object_ptr, ULONG object_size);
-UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_name1_length, CHAR *object_name2);
+UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_name1_length, TX_NAME_CONST CHAR *object_name2);
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);
+TXM_MODULE_ALLOCATED_OBJECT
+ *_txm_module_manager_allocated_object_find(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG *object_size_ptr);
+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_live_object_check(ALIGN_TYPE object_ptr);
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