Author: ion Date: Thu Jun 8 10:17:46 2006 New Revision: 22280
URL: http://svn.reactos.ru/svn/reactos?rev=22280&view=rev Log: - ObFindObject should return the actual object being inserted, in the insert case (otherwise it always returns the root-directory instead...) - Add check for optimized case for objects with no name and no security, but not implemented (ObpIncrementUnnamedHandleCount in Gl00my docs), since I need a better translation then babelfish's. - Fix ObInsertObject to save the Security Descriptor in the Access State structure. Gl00my mentions this isn't absorbed by SeCreateAccessCheck and I just noticed that too. - We only need to perform security checks for a new object, in ObInsertObject, not if the object already existed. - Added proper backout+failure code in ObInsertObject if lookup failed, and also look out for mismatch/exists/collision cases (implemented using simple logic).
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c trunk/reactos/ntoskrnl/ob/obname.c
Modified: trunk/reactos/ntoskrnl/ob/obhandle.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obhandle.c (original) +++ trunk/reactos/ntoskrnl/ob/obhandle.c Thu Jun 8 10:17:46 2006 @@ -1175,6 +1175,7 @@ AUX_DATA AuxData; BOOLEAN IsNamed = FALSE; OB_OPEN_REASON OpenReason = ObCreateHandle; + static int LostOptimizations = 0; PAGED_CODE();
/* Get the Header and Create Info */ @@ -1182,6 +1183,22 @@ ObjectCreateInfo = Header->ObjectCreateInfo; ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(Header); ObjectType = Header->Type; + + /* Check if this is an named object */ + if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) IsNamed = TRUE; + + /* Check if the object is unnamed and also doesn't have security */ + if ((!ObjectType->TypeInfo.SecurityRequired) && !(IsNamed)) + { + /* + * FIXME: TODO (Optimized path through ObpIncrement*UnNamed*HandleCount). + * Described in chapter 6 of Gl00my, but babelfish translation isn't fully + * clear, so waiting on Aleksey's translation. Currently just profiling. + * (about ~500 calls per boot - not critical atm). + */ + ++LostOptimizations; + DPRINT("Optimized case could've be taken: %d times!\n", LostOptimizations); + }
/* Check if we didn't get an access state */ if (!PassedAccessState) @@ -1200,8 +1217,9 @@ } }
- /* Check if this is an named object */ - if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer)) IsNamed = TRUE; + /* Save the security descriptor */ + PassedAccessState->SecurityDescriptor = + ObjectCreateInfo->SecurityDescriptor;
/* Check if the object is named */ if (IsNamed) @@ -1218,12 +1236,48 @@ ObjectCreateInfo->SecurityQos, ObjectCreateInfo->ParseContext, Object); - if (!NT_SUCCESS(Status)) return Status; - - if (FoundObject) - { - DPRINT("Getting header: %x\n", FoundObject); + /* Check if we found an object that doesn't match the one requested */ + if ((NT_SUCCESS(Status)) && (FoundObject) && (Object != FoundObject)) + { + /* This means we're opening an object, not creating a new one */ FoundHeader = OBJECT_TO_OBJECT_HEADER(FoundObject); + OpenReason = ObOpenHandle; + + /* Make sure the caller said it's OK to do this */ + if (ObjectCreateInfo->Attributes & OBJ_OPENIF) + { + /* He did, but did he want this type? */ + if (ObjectType != FoundHeader->Type) + { + /* Wrong type, so fail */ + Status = STATUS_OBJECT_TYPE_MISMATCH; + } + else + { + /* Right type, so warn */ + Status = STATUS_OBJECT_NAME_EXISTS; + } + } + else + { + /* Caller wanted to create a new object, fail */ + Status = STATUS_OBJECT_NAME_COLLISION; + } + } + + /* Check if anything until now failed */ + if (!NT_SUCCESS(Status)) + { + /* We failed, dereference the object and delete the access state */ + ObDereferenceObject(Object); + if (PassedAccessState == &AccessState) + { + /* We used a local one; delete it */ + SeDeleteAccessState(PassedAccessState); + } + + /* Return failure code */ + return Status; } } else @@ -1252,57 +1306,60 @@ } }
- /* Check if it's named or forces security */ - if ((IsNamed) || (ObjectType->TypeInfo.SecurityRequired)) - { - /* Make sure it's inserted into an object directory */ - if ((ObjectNameInfo) && (ObjectNameInfo->Directory)) - { - /* Get the current descriptor */ - ObGetObjectSecurity(ObjectNameInfo->Directory, - &DirectorySd, - &SdAllocated); - } - - /* Now assign it */ - Status = ObAssignSecurity(PassedAccessState, - DirectorySd, - Object, - ObjectType); - - /* Check if we captured one */ - if (DirectorySd) - { - /* We did, release it */ - DPRINT1("Here\n"); - ObReleaseObjectSecurity(DirectorySd, SdAllocated); - } - else if (NT_SUCCESS(Status)) - { - /* Other we didn't, but we were able to use the current SD */ - SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor, - ObjectCreateInfo->ProbeMode, - TRUE); - - /* Clear the current one */ - PassedAccessState->SecurityDescriptor = - ObjectCreateInfo->SecurityDescriptor = NULL; - } - } - - /* Check if anything until now failed */ - if (!NT_SUCCESS(Status)) - { - /* We failed, dereference the object and delete the access state */ - ObDereferenceObject(Object); - if (PassedAccessState == &AccessState) - { - /* We used a local one; delete it */ - SeDeleteAccessState(PassedAccessState); - } - - /* Return failure code */ - return Status; + /* Now check if this object is being created */ + if (FoundObject == Object) + { + /* Check if it's named or forces security */ + if ((IsNamed) || (ObjectType->TypeInfo.SecurityRequired)) + { + /* Make sure it's inserted into an object directory */ + if ((ObjectNameInfo) && (ObjectNameInfo->Directory)) + { + /* Get the current descriptor */ + ObGetObjectSecurity(ObjectNameInfo->Directory, + &DirectorySd, + &SdAllocated); + } + + /* Now assign it */ + Status = ObAssignSecurity(PassedAccessState, + DirectorySd, + Object, + ObjectType); + + /* Check if we captured one */ + if (DirectorySd) + { + /* We did, release it */ + ObReleaseObjectSecurity(DirectorySd, SdAllocated); + } + else if (NT_SUCCESS(Status)) + { + /* Other we didn't, but we were able to use the current SD */ + SeReleaseSecurityDescriptor(ObjectCreateInfo->SecurityDescriptor, + ObjectCreateInfo->ProbeMode, + TRUE); + + /* Clear the current one */ + PassedAccessState->SecurityDescriptor = + ObjectCreateInfo->SecurityDescriptor = NULL; + } + } + + /* Check if anything until now failed */ + if (!NT_SUCCESS(Status)) + { + /* We failed, dereference the object and delete the access state */ + ObDereferenceObject(Object); + if (PassedAccessState == &AccessState) + { + /* We used a local one; delete it */ + SeDeleteAccessState(PassedAccessState); + } + + /* Return failure code */ + return Status; + } }
/* HACKHACK: Because of ROS's incorrect startup, this can be called
Modified: trunk/reactos/ntoskrnl/ob/obname.c URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/ntoskrnl/ob/obname.c?rev=222... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obname.c (original) +++ trunk/reactos/ntoskrnl/ob/obname.c Thu Jun 8 10:17:46 2006 @@ -310,6 +310,7 @@ } } RtlFreeUnicodeString(RemainingPath); + *ReturnedObject = Insert; } else {