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