summaryrefslogtreecommitdiff
path: root/common_modules/module_manager/inc/txm_module_manager_util.h
blob: 3583edcc659dc8f287702efad62cd35394764681 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 * Copyright (c) 2026-present Eclipse ThreadX contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/

// Portions of this file were generated with AI assistance.


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** ThreadX Component                                                     */
/**                                                                       */
/**   Module Manager                                                      */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/


/**************************************************************************/
/*                                                                        */
/*  COMPONENT DEFINITION                                   RELEASE        */
/*                                                                        */
/*    txm_module_manager_util.h                           PORTABLE C      */
/*                                                           6.4.3        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Scott Larson, Microsoft Corporation                                 */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This file declares prototypes of utility functions used by the      */
/*    module manager.                                                     */
/*                                                                        */
/**************************************************************************/

#ifndef TXM_MODULE_MANAGER_UTIL_H
#define TXM_MODULE_MANAGER_UTIL_H

/* 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_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))) && \
     ((obj_ptr) >= (ALIGN_TYPE) module_instance -> txm_module_instance_code_start) && \
     (((obj_ptr) + (obj_size)) <= ((ALIGN_TYPE) module_instance -> txm_module_instance_code_end + 1)))

#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_CODE(module_instance, obj_ptr, obj_size) \
    (!(TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size)))

/* Add sizeof(TXM_MODULE_ALLOCATED_OBJECT) to pool start because the object can't exist before that. */
#define TXM_MODULE_MANAGER_CHECK_INSIDE_OBJ_POOL(module_instance, obj_ptr, obj_size) \
    ((_txm_module_manager_object_pool_created == TX_TRUE) && \
     ((obj_ptr) < ((obj_ptr) + (obj_size))) && \
     (((obj_ptr) >= ((ALIGN_TYPE) _txm_module_manager_object_pool.tx_byte_pool_start + sizeof(TXM_MODULE_ALLOCATED_OBJECT))) && \
      (((obj_ptr) + (obj_size)) <= (ALIGN_TYPE) (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size))))

/* 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_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_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) && \
     TXM_MODULE_MANAGER_CHECK_OUTSIDE_CODE(module_instance, obj_ptr, obj_size))

#define TXM_MODULE_MANAGER_ENSURE_INSIDE_OBJ_POOL(module_instance, obj_ptr, obj_size) \
    TXM_MODULE_MANAGER_CHECK_INSIDE_OBJ_POOL(module_instance, obj_ptr, obj_size)

/* Define macros for parameter types.  */

/* Buffers we read from can be in RW/RO/Shared areas.  */
#define TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, buffer_ptr, buffer_size) \
    ((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, buffer_ptr, buffer_size)) || \
     ((void *) (buffer_ptr) == TX_NULL))

/* Buffers we write to can only be in RW/Shared areas.  */
#define TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, buffer_ptr, buffer_size) \
    ((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, buffer_ptr, buffer_size)) || \
     ((void *) (buffer_ptr) == TX_NULL))

/* 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) \
    if ((ULONG)-1 - (augend) < (addend))                 \
    {                                                    \
        return(TXM_MODULE_MATH_OVERFLOW);                \
    }                                                    \
    else                                                 \
    {                                                    \
        (result) = (augend) + (addend);                  \
    }

/* Define utility functions.  */

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, 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