My Project
Loading...
Searching...
No Matches
ob.c
Go to the documentation of this file.
1/*++
2
3Module Name:
4
5 ob.c
6
7Purpose:
8
9 This translation unit contains the implementation of the object manager.
10
11Author:
12
13 slep (Matanel) 2025.
14
15Revision History:
16
17--*/
18
19#include "../../includes/ob.h"
20#include "../../includes/mg.h"
21#include "../../includes/md.h"
22#include "../../assert.h"
23#include "../../includes/ps.h"
24
25// Global list of types (for debugging/enumeration)
28volatile void* ObpReaperList = NULL;
29
30
32
34 void
35)
36
37/*++
38
39 Routine description:
40
41 Initializes the Object Manager of the kernel.
42
43 Arguments:
44
45 None.
46
47 Return Values:
48
49 None.
50
51--*/
52
53{
54 ObGlobalLock.locked = false;
56 // Initialize the DPC here, not at the ObpDefer function, as it would overwrite.
58}
59
61 IN char* TypeName,
62 IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
63 OUT POBJECT_TYPE* ReturnedObjectType
64)
65
66/*++
67
68 Routine description:
69
70 Creates an object type for the specified object in the kernel subsystem.
71
72 Arguments:
73
74 [IN] char* TypeName - The name of the object subsystem that will be created for.
75 [IN] POBJECT_TYPE_INITIALIZER ObjectTypeInitializer - The initializer for each object created by ObCreateObject that defines how it should be created & its attributes.
76 [OUT] POBJECT_TYPE* ReturnedObjectType - The returned object type, used to identify this type of object initialization.
77
78 Return Values:
79
80 MTSTATUS Status codes:
81
82 MT_INVALID_PARAM: Invalid parameter, one of them is NULL.
83 MT_NO_MEMORY: No memory is available to create the object type.
84 MT_SUCCESS: Successfully created the object type.
85
86--*/
87
88{
89 if (!TypeName || !ObjectTypeInitializer || !ReturnedObjectType) {
90 return MT_INVALID_PARAM;
91 }
92
93 // Allocate the Type Object itself.
94 POBJECT_TYPE NewType = (POBJECT_TYPE)MmAllocatePoolWithTag(NonPagedPool, sizeof(OBJECT_TYPE), 'epyT'); // Type
95 if (!NewType) return MT_NO_MEMORY;
96
97 // Initialize the Type Object
98 kmemset(NewType, 0, sizeof(OBJECT_TYPE));
99 kstrncpy(NewType->Name, TypeName, 32);
100
101 // Copy the initializer into the object
102 kmemcpy(&NewType->TypeInfo, ObjectTypeInitializer, sizeof(OBJECT_TYPE_INITIALIZER));
103
104 // Link it into the global list
105 IRQL oldIrql;
109
110 // 5. Return the pointer
111 *ReturnedObjectType = NewType;
112 return MT_SUCCESS;
113}
114
117 IN POBJECT_TYPE ObjectType,
118 IN uint32_t ObjectSize,
119 OUT void** ObjectCreated
120 //_In_Opt char* Name - When files arrive, i'll uncomment this.
121)
122
123/*++
124
125 Routine description:
126
127 Creates an object for the specified object type subsystem.
128
129 Arguments:
130
131 [IN] POBJECT_TYPE ObjectType - The object type to create the object for.
132 [IN] uint32_t ObjectBodySize - The size of the object in bytes to create.
133
134 Return Values:
135
136 Pointer to object, or NULL on failure.
137
138--*/
139
140{
141 // 1. Calculate size
142 size_t ActualSize = sizeof(OBJECT_HEADER) + ObjectSize;
143
144 // Allocate memory for the header.
145 POBJECT_HEADER Header = (POBJECT_HEADER)MmAllocatePoolWithTag(ObjectType->TypeInfo.PoolType, ActualSize, 'bObO'); // Ob Object, not bobo, lol.
146 if (!Header) return MT_NO_MEMORY;
147
148 Header->Type = ObjectType;
149 Header->PointerCount = 1; // Start with 1 reference
150
151 // Update stats in the Type object
152 InterlockedIncrementU32((volatile uint32_t*)&ObjectType->TotalNumberOfObjects);
153
154 // Return Body
155 *ObjectCreated = OBJECT_HEADER_TO_OBJECT(Header);
156 return MT_SUCCESS;
157}
158
159bool
161 IN void* Object
162)
163
164/*++
165
166 Routine description:
167
168 References the Object given.
169
170 Arguments:
171
172 [IN] void* Object - The Object to increment reference count for.
173
174 Return Values:
175
176 True if reference succeded, false otherwise (object dying/dead).
177
178--*/
179
180{
181 if (!Object) return false;
183
184 uint64_t OldCount = Header->PointerCount;
185 while (1) {
186 if (OldCount == 0) return false; // Object is dying or dead
187
188 uint64_t NewCount = InterlockedCompareExchangeU64(
189 (volatile uint64_t*)&Header->PointerCount,
190 OldCount + 1,
191 OldCount
192 );
193
194 if (NewCount == OldCount) return true;
195 OldCount = NewCount;
196 }
197}
198
201 IN void* Object,
202 IN POBJECT_TYPE DesiredType
203)
204
205/*++
206
207 Routine description:
208
209 References the Object given by its pointer.
210
211 Arguments:
212
213 [IN] void* Object - The Object to increment reference count for.
214 [IN] POBJECT_TYPE DesiredType - The type we EXPECT the Object to be (PsProcessType, PsThreadType, etc..)
215
216 Return Values:
217
218 MT_SUCCESS if reference succeeded.
219 MT_TYPE_MISMATCH if DesiredType isn't the Object's actual OBJECT_TYPE.
220 MT_INVALID_PARAM if Object is NULL.
221 MT_OBJECT_DELETED if Object is deleted / ongoing deletion.
222
223 MT_BETTER_THAN_WINDOWS if (true)
224
225--*/
226
227{
228 if (!Object) return MT_INVALID_PARAM;
229
231
232 // If the caller expects a process but gets a thread or a file, we say no no bye bye.
233 if (DesiredType != NULL && Header->Type != DesiredType) {
234 return MT_TYPE_MISMATCH;
235 }
236
237 // We reference it.
238 if (ObReferenceObject(Object)) {
239 return MT_SUCCESS;
240 }
241
242 // Object is RIP, we return.
243 return MT_OBJECT_DELETED;
244}
245
248 IN HANDLE Handle,
249 IN uint32_t DesiredAccess,
250 IN POBJECT_TYPE DesiredType,
251 OUT void** Object,
252 _Out_Opt PHANDLE_TABLE_ENTRY HandleInformation
253)
254
255/*++
256
257 Routine description:
258
259 References the Object given by its given handle.
260
261 Arguments:
262
263 [IN] HANDLE Handle - The handle to reference the object for.
264 [IN] uint32_t DesiredAccess - The access rights requested for the object.
265 [IN] POBJECT_TYPE DesiredType - The type we EXPECT the Object to be (PsProcessType, PsThreadType, etc..)
266 [OUT] void** Object - The pointer to the object expected.
267 [OUT OPTIONAL] PHANDLE_TABLE_ENTRY HandleInformation - Information about the handle given if MT_SUCCESS is returned.
268
269 Return Values:
270
271 MT_SUCCESS if reference succeeded.
272 MT_INVALID_HANDLE if the HANDLE is simply invalid (doesn't exist, or table doesnt exist)
273 MT_TYPE_MISMATCH if DesiredType isn't the Object's actual OBJECT_TYPE.
274 MT_INVALID_PARAM if Object is NULL.
275 MT_OBJECT_DELETED if Object is deleted / ongoing deletion.
276 MT_ACCESS_DENIED if the desired access does not meet the access rights of the Object.
277
278 MT_BETTER_THAN_WINDOWS if (true)
279
280--*/
281
282{
283 // Set initially to NULL. (to overwrite stack default if uninitialized)
284 *Object = NULL;
285
286 // Get the handle table from current process (requesting process)
287 PEPROCESS Process = PsGetCurrentProcess();
288 if (!Process || !Process->ObjectTable) return MT_INVALID_HANDLE;
289
290 // Lookup in the handle table.
291 PHANDLE_TABLE_ENTRY OutHandleEntry = NULL;
292 void* RetrievedObject = HtGetObject(Process->ObjectTable, Handle, &OutHandleEntry);
293 if (!RetrievedObject) return MT_INVALID_HANDLE;
294
295 // Get the header.
296 POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(RetrievedObject);
297
298 // Lets check if the type matches
299 if (DesiredType && Header->Type != DesiredType) {
300 // Invalid type.
301 return MT_TYPE_MISMATCH;
302 }
303
304 // Check access.
305 if ((OutHandleEntry->GrantedAccess & DesiredAccess) != DesiredAccess) {
306 // Access is invalid.
307 return MT_ACCESS_DENIED;
308 }
309
310 // Wow!! It is all good!!, reference it.
311 ObReferenceObject(RetrievedObject);
312 *Object = RetrievedObject;
313 if (HandleInformation) *HandleInformation = *OutHandleEntry;
314 return MT_SUCCESS;
315}
316
319 IN void* Object,
320 IN ACCESS_MASK DesiredAccess,
321 OUT PHANDLE ReturnedHandle
322)
323
324/*++
325
326 Routine description:
327
328 Creates a handle in the current process's handle table for the specified Object.
329
330 Arguments:
331
332 [IN] void* Object - The object to create the handle for.
333 [IN] ACCESS_MASK DesiredAccess - The maximum access the handle should have.
334 [OUT] PHANDLE ReturnedHandle - The returned handle for the object if success.
335
336 Return Values:
337
338 MTSTATUS Status Codes:
339
340 MT_SUCCESS - Successful.
341 MT_INVALID_STATE - No handle table for current process.
342 MT_INVALID_CHECK - HtCreateHandle returned MT_INVALID_HANDLE.
343--*/
344
345{
346 // Acquire the object table.
348 if (!ObjectTable) return MT_INVALID_ADDRESS;
349
350 // Create the handle.
351 HANDLE Handle = HtCreateHandle(ObjectTable, Object, DesiredAccess);
352 if (Handle == MT_INVALID_HANDLE) return MT_INVALID_CHECK;
353
354 // Reference the object.
355 ObReferenceObject(Object);
356
357 // Return success.
358 *ReturnedHandle = Handle;
359 return MT_SUCCESS;
360}
361
364 IN void* Object,
365 IN ACCESS_MASK DesiredAccess,
366 OUT PHANDLE ReturnedHandle,
367 IN PHANDLE_TABLE ObjectTable
368)
369
370/*++
371
372 Routine description:
373
374 Creates a handle in the specified handle table for the specified Object.
375
376 Arguments:
377
378 [IN] void* Object - The object to create the handle for.
379 [IN] ACCESS_MASK DesiredAccess - The maximum access the handle should have.
380 [OUT] PHANDLE ReturnedHandle - The returned handle for the object if success.
381 [IN] PHANDLE_TABLE ObjectTable - The handle table to insert the newly created handle in.
382
383 Return Values:
384
385 MTSTATUS Status Codes:
386
387 MT_SUCCESS - Successful.
388 MT_INVALID_STATE - No handle table for current process.
389 MT_INVALID_CHECK - HtCreateHandle returned MT_INVALID_HANDLE.
390--*/
391
392{
393 if (!ObjectTable || !Object) return MT_INVALID_ADDRESS;
394
395 // Create the handle.
396 HANDLE Handle = HtCreateHandle(ObjectTable, Object, DesiredAccess);
397 if (Handle == MT_INVALID_HANDLE) return MT_INVALID_CHECK;
398
399 // Reference the object.
400 ObReferenceObject(Object);
401
402 // Return success.
403 *ReturnedHandle = Handle;
404 return MT_SUCCESS;
405}
406
407static
408void
409ObpDeferObjectDeletion(
410 IN POBJECT_HEADER Header
411)
412
413/*++
414
415 Routine description:
416
417 Defers object deletion to a DPC, to ensure no use after free.
418
419 Arguments:
420
421 [IN] POBJECT_HEADER Header - The object header to defer deletion for.
422
423 Return Values:
424
425 None.
426
427--*/
428
429{
430 volatile void* Entry;
431 do {
432 // Get the current entry.
433 Entry = ObpReaperList;
434
435 // Link our object to the linked list.
436 Header->NextToFree = Entry;
437 // Update the list
438 } while (InterlockedCompareExchangePointer(&ObpReaperList, Header, (void*)Entry) != Entry);
439
440 if (!Entry) {
441 // Looks like a DPC hasn't been queued yet, lets do so!
442 MeInsertQueueDpc(&ObpReaperDpc, NULL, NULL);
443 }
444}
445
447 IN void* Object
448)
449
450/*++
451
452 Routine description:
453
454 Dereferences the Object given.
455
456 Arguments:
457
458 [IN] void* Object - The Object to decrement reference count for.
459
460 Return Values:
461
462 None.
463
464 Notes:
465
466 On reference count 0, object is deleted using type initializer routine.
467
468--*/
469
470{
471 if (!Object) return;
473
474 uint64_t NewCount = InterlockedDecrementU64((volatile uint64_t*)&Header->PointerCount);
475
476 if (NewCount == 0) {
477 // Get the type initializer for the object.
478 POBJECT_TYPE Type = Header->Type;
479
480#ifdef DEBUG
481 // First call debug callback if exists
482 if (Type->TypeInfo.DumpProcedure) Type->TypeInfo.DumpProcedure(Object);
483#endif
484
485 // Call Delete Callback if it exists
486 if (Type->TypeInfo.DeleteProcedure) Type->TypeInfo.DeleteProcedure(Object);
487
488 // Update Stats
489 InterlockedDecrementU32((volatile uint32_t*)&Type->TotalNumberOfObjects);
490 // Free Memory
491 gop_printf(COLOR_RED, "Freeing the header\n");
492 //ObpDeferObjectDeletion(Header);
493 MmFreePool(Header);
494 }
495}
#define _Out_Opt
Definition annotations.h:10
#define IN
Definition annotations.h:7
#define OUT
Definition annotations.h:8
FORCEINLINE uint32_t InterlockedIncrementU32(volatile uint32_t *target)
Definition atomic.h:115
FORCEINLINE uint64_t InterlockedCompareExchangeU64(volatile uint64_t *target, uint64_t value, uint64_t comparand)
Definition atomic.h:86
FORCEINLINE void * InterlockedCompareExchangePointer(volatile void *volatile *target, void *value, void *comparand)
Definition atomic.h:171
FORCEINLINE uint32_t InterlockedDecrementU32(volatile uint32_t *target)
Definition atomic.h:116
FORCEINLINE uint64_t InterlockedDecrementU64(volatile uint64_t *target)
Definition atomic.h:122
enum _IRQL IRQL
EPROCESS * PEPROCESS
Definition core.h:50
struct _DOUBLY_LINKED_LIST DOUBLY_LINKED_LIST
bool MeInsertQueueDpc(IN PDPC Dpc, IN void *SystemArgument1, IN void *SystemArgument2)
Definition dpc.c:47
volatile void * ObpReaperList
Definition ob.c:28
void MeInitializeDpc(IN PDPC DpcAllocated, IN PDEFERRED_ROUTINE DeferredRoutine, IN void *DeferredContext, IN DPC_PRIORITY DeferredPriority)
Definition dpc.c:384
void ReapOb(DPC *dpc, void *DeferredContext, void *SystemArgument1, void *SystemArgument2)
Definition dpc.c:18
void gop_printf(uint32_t color, const char *fmt,...)
Definition gop.c:694
char * kstrncpy(char *dst, const char *src, size_t n)
Definition gop.c:416
void * HtGetObject(PHANDLE_TABLE Table, HANDLE Handle, PHANDLE_TABLE_ENTRY *OutEntry)
Definition handle.c:389
HANDLE HtCreateHandle(PHANDLE_TABLE Table, void *Object, uint32_t Access)
Definition handle.c:269
uint32_t ACCESS_MASK
Definition ht.h:63
int32_t * PHANDLE
Definition ht.h:59
struct _HANDLE_TABLE_ENTRY * PHANDLE_TABLE_ENTRY
struct _HANDLE_TABLE * PHANDLE_TABLE
int32_t HANDLE
Definition ht.h:59
@ MEDIUM_PRIORITY
Definition me.h:60
struct _DPC DPC
#define COLOR_RED
Colors definitions for easier access.
Definition mg.h:29
@ NonPagedPool
Definition mm.h:316
FORCEINLINE void * kmemcpy(void *dest, const void *src, size_t len)
Definition mm.h:554
FORCEINLINE void * kmemset(void *dest, int64_t val, uint64_t len)
Definition mm.h:540
FORCEINLINE void InitializeListHead(PDOUBLY_LINKED_LIST Head)
Definition ms.h:166
FORCEINLINE void InsertTailList(PDOUBLY_LINKED_LIST Head, PDOUBLY_LINKED_LIST Entry)
Definition ms.h:179
struct _SPINLOCK SPINLOCK
#define MT_NO_MEMORY
Definition mtstatus.h:42
#define MT_TYPE_MISMATCH
Definition mtstatus.h:34
#define MT_SUCCESS
Definition mtstatus.h:22
#define MT_ACCESS_DENIED
Definition mtstatus.h:26
#define MT_INVALID_ADDRESS
Definition mtstatus.h:46
#define MT_INVALID_PARAM
Definition mtstatus.h:24
#define MT_OBJECT_DELETED
Definition mtstatus.h:35
int32_t MTSTATUS
Definition mtstatus.h:12
#define MT_INVALID_HANDLE
Definition mtstatus.h:36
#define MT_INVALID_CHECK
Definition mtstatus.h:33
MTSTATUS ObCreateHandleForObject(IN void *Object, IN ACCESS_MASK DesiredAccess, OUT PHANDLE ReturnedHandle)
Definition ob.c:318
void ObInitialize(void)
Definition ob.c:33
MTSTATUS ObReferenceObjectByHandle(IN HANDLE Handle, IN uint32_t DesiredAccess, IN POBJECT_TYPE DesiredType, OUT void **Object, _Out_Opt PHANDLE_TABLE_ENTRY HandleInformation)
Definition ob.c:247
MTSTATUS ObReferenceObjectByPointer(IN void *Object, IN POBJECT_TYPE DesiredType)
Definition ob.c:200
MTSTATUS ObCreateHandleForObjectEx(IN void *Object, IN ACCESS_MASK DesiredAccess, OUT PHANDLE ReturnedHandle, IN PHANDLE_TABLE ObjectTable)
Definition ob.c:363
MTSTATUS ObCreateObjectType(IN char *TypeName, IN POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, OUT POBJECT_TYPE *ReturnedObjectType)
Definition ob.c:60
void ObDereferenceObject(IN void *Object)
Definition ob.c:446
DPC ObpReaperDpc
Definition ob.c:31
bool ObReferenceObject(IN void *Object)
Definition ob.c:160
SPINLOCK ObGlobalLock
Definition ob.c:27
MTSTATUS ObCreateObject(IN POBJECT_TYPE ObjectType, IN uint32_t ObjectSize, OUT void **ObjectCreated)
Definition ob.c:116
DOUBLY_LINKED_LIST ObTypeDirectoryList
Definition ob.c:26
struct _OBJECT_TYPE * POBJECT_TYPE
POBJECT_TYPE Type
Definition ob.h:5
struct _OBJECT_TYPE_INITIALIZER * POBJECT_TYPE_INITIALIZER
#define OBJECT_HEADER_TO_OBJECT(h)
Definition ob.h:71
struct _OBJECT_HEADER * POBJECT_HEADER
Definition ob.h:64
struct _OBJECT_TYPE OBJECT_TYPE
struct _OBJECT_TYPE_INITIALIZER OBJECT_TYPE_INITIALIZER
#define OBJECT_TO_OBJECT_HEADER(o)
Definition ob.h:68
void MmFreePool(IN void *buf)
Definition pool.c:586
void * MmAllocatePoolWithTag(IN enum _POOL_TYPE PoolType, IN size_t NumberOfBytes, IN uint32_t Tag)
Definition pool.c:427
FORCEINLINE PEPROCESS PsGetCurrentProcess(void)
Definition ps.h:212
void MsAcquireSpinlock(IN PSPINLOCK lock, IN PIRQL OldIrql)
Definition spinlock.c:13
void MsReleaseSpinlock(IN PSPINLOCK lock, IN IRQL OldIrql)
Definition spinlock.c:45
PHANDLE_TABLE ObjectTable
Definition ps.h:114
uint32_t GrantedAccess
Definition ht.h:33
DOUBLY_LINKED_LIST TypeList
Definition ob.h:48
char Name[32]
Definition ob.h:49
OBJECT_TYPE_INITIALIZER TypeInfo
Definition ob.h:52