xref: /reactos/ntoskrnl/ob/obinit.c (revision b4af5597)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * FILE:            ntoskrnl/ob/obinit.c
5  * PURPOSE:         Handles Object Manager Initialization and Shutdown
6  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7  *                  Eric Kohl
8  *                  Thomas Weidenmueller (w3seek@reactos.org)
9  */
10 
11 /* INCLUDES ******************************************************************/
12 
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS *******************************************************************/
18 
19 GENERIC_MAPPING ObpTypeMapping =
20 {
21     STANDARD_RIGHTS_READ,
22     STANDARD_RIGHTS_WRITE,
23     STANDARD_RIGHTS_EXECUTE,
24     0x000F0001
25 };
26 
27 GENERIC_MAPPING ObpDirectoryMapping =
28 {
29     STANDARD_RIGHTS_READ    | DIRECTORY_QUERY               |
30     DIRECTORY_TRAVERSE,
31     STANDARD_RIGHTS_WRITE   | DIRECTORY_CREATE_SUBDIRECTORY |
32     DIRECTORY_CREATE_OBJECT,
33     STANDARD_RIGHTS_EXECUTE | DIRECTORY_QUERY               |
34     DIRECTORY_TRAVERSE,
35     DIRECTORY_ALL_ACCESS
36 };
37 
38 GENERIC_MAPPING ObpSymbolicLinkMapping =
39 {
40     STANDARD_RIGHTS_READ    | SYMBOLIC_LINK_QUERY,
41     STANDARD_RIGHTS_WRITE,
42     STANDARD_RIGHTS_EXECUTE | SYMBOLIC_LINK_QUERY,
43     SYMBOLIC_LINK_ALL_ACCESS
44 };
45 
46 PDEVICE_MAP ObSystemDeviceMap = NULL;
47 ULONG ObpTraceLevel = 0;
48 
49 VOID
50 NTAPI
51 PsInitializeQuotaSystem(VOID);
52 
53 ULONG ObpInitializationPhase;
54 
55 ULONG ObpObjectSecurityMode = 0;
56 ULONG ObpProtectionMode = 0;
57 
58 /* PRIVATE FUNCTIONS *********************************************************/
59 
60 static
61 INIT_FUNCTION
62 NTSTATUS
63 NTAPI
64 ObpCreateKernelObjectsSD(OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
65 {
66     PSECURITY_DESCRIPTOR Sd = NULL;
67     PACL Dacl;
68     ULONG AclSize, SdSize;
69     NTSTATUS Status;
70 
71     AclSize = sizeof(ACL) +
72               sizeof(ACE) + RtlLengthSid(SeWorldSid) +
73               sizeof(ACE) + RtlLengthSid(SeAliasAdminsSid) +
74               sizeof(ACE) + RtlLengthSid(SeLocalSystemSid);
75 
76     SdSize = sizeof(SECURITY_DESCRIPTOR) + AclSize;
77 
78     /* Allocate the SD and ACL */
79     Sd = ExAllocatePoolWithTag(PagedPool, SdSize, TAG_SD);
80     if (Sd == NULL)
81     {
82         return STATUS_INSUFFICIENT_RESOURCES;
83     }
84 
85     /* Initialize the SD */
86     Status = RtlCreateSecurityDescriptor(Sd,
87                                          SECURITY_DESCRIPTOR_REVISION);
88     if (!NT_SUCCESS(Status))
89         goto done;
90 
91     Dacl = (PACL)((INT_PTR)Sd + sizeof(SECURITY_DESCRIPTOR));
92 
93     /* Initialize the DACL */
94     RtlCreateAcl(Dacl, AclSize, ACL_REVISION);
95 
96     /* Add the ACEs */
97     RtlAddAccessAllowedAce(Dacl,
98                            ACL_REVISION,
99                            GENERIC_READ,
100                            SeWorldSid);
101 
102     RtlAddAccessAllowedAce(Dacl,
103                            ACL_REVISION,
104                            GENERIC_ALL,
105                            SeAliasAdminsSid);
106 
107     RtlAddAccessAllowedAce(Dacl,
108                            ACL_REVISION,
109                            GENERIC_ALL,
110                            SeLocalSystemSid);
111 
112     /* Attach the DACL to the SD */
113     Status = RtlSetDaclSecurityDescriptor(Sd,
114                                           TRUE,
115                                           Dacl,
116                                           FALSE);
117     if (!NT_SUCCESS(Status))
118         goto done;
119 
120     *SecurityDescriptor = Sd;
121 
122 done:
123     if (!NT_SUCCESS(Status))
124     {
125         if (Sd != NULL)
126             ExFreePoolWithTag(Sd, TAG_SD);
127     }
128 
129     return Status;
130 }
131 
132 BOOLEAN
133 INIT_FUNCTION
134 NTAPI
135 ObInit2(VOID)
136 {
137     CCHAR i;
138     PKPRCB Prcb;
139     PGENERAL_LOOKASIDE CurrentList = NULL;
140 
141     /* Now allocate the per-processor lists */
142     for (i = 0; i < KeNumberProcessors; i++)
143     {
144         /* Get the PRCB for this CPU */
145         Prcb = KiProcessorBlock[(int)i];
146 
147         /* Set the OBJECT_CREATE_INFORMATION List */
148         Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList;
149         CurrentList = ExAllocatePoolWithTag(NonPagedPool,
150                                             sizeof(GENERAL_LOOKASIDE),
151                                             'ICbO');
152         if (CurrentList)
153         {
154             /* Initialize it */
155             ExInitializeSystemLookasideList(CurrentList,
156                                             NonPagedPool,
157                                             sizeof(OBJECT_CREATE_INFORMATION),
158                                             'ICbO',
159                                             32,
160                                             &ExSystemLookasideListHead);
161         }
162         else
163         {
164             /* No list, use the static buffer */
165             CurrentList = &ObpCreateInfoLookasideList;
166         }
167 
168         /* Link it */
169         Prcb->PPLookasideList[LookasideCreateInfoList].P = CurrentList;
170 
171         /* Set the captured UNICODE_STRING Object Name List */
172         Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList;
173         CurrentList = ExAllocatePoolWithTag(NonPagedPool,
174                                             sizeof(GENERAL_LOOKASIDE),
175                                             'MNbO');
176         if (CurrentList)
177         {
178             /* Initialize it */
179             ExInitializeSystemLookasideList(CurrentList,
180                                             PagedPool,
181                                             248,
182                                             'MNbO',
183                                             16,
184                                             &ExSystemLookasideListHead);
185         }
186         else
187         {
188             /* No list, use the static buffer */
189             CurrentList = &ObpNameBufferLookasideList;
190         }
191 
192         /* Link it */
193         Prcb->PPLookasideList[LookasideNameBufferList].P = CurrentList;
194     }
195 
196     return TRUE;
197 }
198 
199 BOOLEAN
200 INIT_FUNCTION
201 NTAPI
202 ObInitSystem(VOID)
203 {
204     OBJECT_ATTRIBUTES ObjectAttributes;
205     UNICODE_STRING Name;
206     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
207     OBP_LOOKUP_CONTEXT Context;
208     HANDLE Handle;
209     PKPRCB Prcb = KeGetCurrentPrcb();
210     PLIST_ENTRY ListHead, NextEntry;
211     POBJECT_HEADER Header;
212     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
213     POBJECT_HEADER_NAME_INFO NameInfo;
214     PSECURITY_DESCRIPTOR KernelObjectsSD = NULL;
215     NTSTATUS Status;
216 
217     /* Check if this is actually Phase 1 initialization */
218     if (ObpInitializationPhase != 0) goto ObPostPhase0;
219 
220     /* Initialize the OBJECT_CREATE_INFORMATION List */
221     ExInitializeSystemLookasideList(&ObpCreateInfoLookasideList,
222                                     NonPagedPool,
223                                     sizeof(OBJECT_CREATE_INFORMATION),
224                                     'ICbO',
225                                     32,
226                                     &ExSystemLookasideListHead);
227 
228     /* Set the captured UNICODE_STRING Object Name List */
229     ExInitializeSystemLookasideList(&ObpNameBufferLookasideList,
230                                     PagedPool,
231                                     248,
232                                     'MNbO',
233                                     16,
234                                     &ExSystemLookasideListHead);
235 
236     /* Temporarily setup both pointers to the shared list */
237     Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList;
238     Prcb->PPLookasideList[LookasideCreateInfoList].P = &ObpCreateInfoLookasideList;
239     Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList;
240     Prcb->PPLookasideList[LookasideNameBufferList].P = &ObpNameBufferLookasideList;
241 
242     /* Initialize the security descriptor cache */
243     ObpInitSdCache();
244 
245     /* Initialize the Default Event */
246     KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE);
247 
248     /* Initialize the Dos Device Map mutex */
249     KeInitializeGuardedMutex(&ObpDeviceMapLock);
250 
251     /* Setup default access for the system process */
252     PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS;
253     PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS;
254 
255     /* Setup the Object Reaper */
256     ExInitializeWorkItem(&ObpReaperWorkItem, ObpReapObject, NULL);
257 
258     /* Initialize default Quota block */
259     PsInitializeQuotaSystem();
260 
261     /* Create kernel handle table */
262     PsGetCurrentProcess()->ObjectTable = ExCreateHandleTable(NULL);
263     ObpKernelHandleTable = PsGetCurrentProcess()->ObjectTable;
264 
265     /* Create the Type Type */
266     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
267     RtlInitUnicodeString(&Name, L"Type");
268     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
269     ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
270     ObjectTypeInitializer.UseDefaultObject = TRUE;
271     ObjectTypeInitializer.MaintainTypeList = TRUE;
272     ObjectTypeInitializer.PoolType = NonPagedPool;
273     ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
274     ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE);
275     ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
276     ObjectTypeInitializer.DeleteProcedure = ObpDeleteObjectType;
277     ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObpTypeObjectType);
278 
279     /* Create the Directory Type */
280     RtlInitUnicodeString(&Name, L"Directory");
281     ObjectTypeInitializer.PoolType = PagedPool;
282     ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
283     ObjectTypeInitializer.CaseInsensitive = TRUE;
284     ObjectTypeInitializer.MaintainTypeList = FALSE;
285     ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
286     ObjectTypeInitializer.DeleteProcedure = NULL;
287     ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY);
288     ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObpDirectoryObjectType);
289     ObpDirectoryObjectType->TypeInfo.ValidAccessMask &= ~SYNCHRONIZE;
290 
291     /* Create 'symbolic link' object type */
292     RtlInitUnicodeString(&Name, L"SymbolicLink");
293     ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_SYMBOLIC_LINK);
294     ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping;
295     ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS;
296     ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink;
297     ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink;
298     ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObpSymbolicLinkObjectType);
299     ObpSymbolicLinkObjectType->TypeInfo.ValidAccessMask &= ~SYNCHRONIZE;
300 
301     /* Phase 0 initialization complete */
302     ObpInitializationPhase++;
303     return TRUE;
304 
305 ObPostPhase0:
306 
307     /* Re-initialize lookaside lists */
308     ObInit2();
309 
310     /* Initialize Object Types directory attributes */
311     RtlInitUnicodeString(&Name, L"\\");
312     InitializeObjectAttributes(&ObjectAttributes,
313                                &Name,
314                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
315                                NULL,
316                                SePublicDefaultUnrestrictedSd);
317 
318     /* Create the directory */
319     Status = NtCreateDirectoryObject(&Handle,
320                                      DIRECTORY_ALL_ACCESS,
321                                      &ObjectAttributes);
322     if (!NT_SUCCESS(Status)) return FALSE;
323 
324     /* Get a handle to it */
325     Status = ObReferenceObjectByHandle(Handle,
326                                        0,
327                                        ObpDirectoryObjectType,
328                                        KernelMode,
329                                        (PVOID*)&ObpRootDirectoryObject,
330                                        NULL);
331     if (!NT_SUCCESS(Status)) return FALSE;
332 
333     /* Close the extra handle */
334     Status = NtClose(Handle);
335     if (!NT_SUCCESS(Status)) return FALSE;
336 
337     /* Create a custom security descriptor for the KernelObjects directory */
338     Status = ObpCreateKernelObjectsSD(&KernelObjectsSD);
339     if (!NT_SUCCESS(Status))
340         return FALSE;
341 
342     /* Initialize the KernelObjects directory attributes */
343     RtlInitUnicodeString(&Name, L"\\KernelObjects");
344     InitializeObjectAttributes(&ObjectAttributes,
345                                &Name,
346                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
347                                NULL,
348                                KernelObjectsSD);
349 
350     /* Create the directory */
351     Status = NtCreateDirectoryObject(&Handle,
352                                      DIRECTORY_ALL_ACCESS,
353                                      &ObjectAttributes);
354     ExFreePoolWithTag(KernelObjectsSD, TAG_SD);
355     if (!NT_SUCCESS(Status)) return FALSE;
356 
357     /* Close the extra handle */
358     Status = NtClose(Handle);
359     if (!NT_SUCCESS(Status)) return FALSE;
360 
361     /* Initialize ObjectTypes directory attributes */
362     RtlInitUnicodeString(&Name, L"\\ObjectTypes");
363     InitializeObjectAttributes(&ObjectAttributes,
364                                &Name,
365                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
366                                NULL,
367                                NULL);
368 
369     /* Create the directory */
370     Status = NtCreateDirectoryObject(&Handle,
371                                      DIRECTORY_ALL_ACCESS,
372                                      &ObjectAttributes);
373     if (!NT_SUCCESS(Status)) return FALSE;
374 
375     /* Get a handle to it */
376     Status = ObReferenceObjectByHandle(Handle,
377                                        0,
378                                        ObpDirectoryObjectType,
379                                        KernelMode,
380                                        (PVOID*)&ObpTypeDirectoryObject,
381                                        NULL);
382     if (!NT_SUCCESS(Status)) return FALSE;
383 
384     /* Close the extra handle */
385     Status = NtClose(Handle);
386     if (!NT_SUCCESS(Status)) return FALSE;
387 
388     /* Initialize lookup context */
389     ObpInitializeLookupContext(&Context);
390 
391     /* Lock it */
392     ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context);
393 
394     /* Loop the object types */
395     ListHead = &ObpTypeObjectType->TypeList;
396     NextEntry = ListHead->Flink;
397     while (ListHead != NextEntry)
398     {
399         /* Get the creator info from the list */
400         CreatorInfo = CONTAINING_RECORD(NextEntry,
401                                         OBJECT_HEADER_CREATOR_INFO,
402                                         TypeList);
403 
404         /* Recover the header and the name header from the creator info */
405         Header = (POBJECT_HEADER)(CreatorInfo + 1);
406         NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header);
407 
408         /* Make sure we have a name, and aren't inserted yet */
409         if ((NameInfo) && !(NameInfo->Directory))
410         {
411             /* Do the initial lookup to setup the context */
412             if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject,
413                                          &NameInfo->Name,
414                                          OBJ_CASE_INSENSITIVE,
415                                          FALSE,
416                                          &Context))
417             {
418                 /* Insert this object type */
419                 ObpInsertEntryDirectory(ObpTypeDirectoryObject,
420                                         &Context,
421                                         Header);
422             }
423         }
424 
425         /* Move to the next entry */
426         NextEntry = NextEntry->Flink;
427     }
428 
429     /* Cleanup after lookup */
430     ObpReleaseLookupContext(&Context);
431 
432     /* Initialize DOS Devices Directory and related Symbolic Links */
433     Status = ObpCreateDosDevicesDirectory();
434     if (!NT_SUCCESS(Status)) return FALSE;
435     return TRUE;
436 }
437 
438 /* EOF */
439