added more irql checks and secured access to buffers in symbolic link code Modified: trunk/reactos/ntoskrnl/cm/cm.h Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c Modified: trunk/reactos/ntoskrnl/ob/dirobj.c Modified: trunk/reactos/ntoskrnl/ob/handle.c Modified: trunk/reactos/ntoskrnl/ob/namespc.c Modified: trunk/reactos/ntoskrnl/ob/ntobj.c Modified: trunk/reactos/ntoskrnl/ob/object.c Modified: trunk/reactos/ntoskrnl/ob/security.c Modified: trunk/reactos/ntoskrnl/ob/symlink.c Modified: trunk/reactos/ntoskrnl/po/power.c _____
Modified: trunk/reactos/ntoskrnl/cm/cm.h --- trunk/reactos/ntoskrnl/cm/cm.h 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/cm/cm.h 2005-02-22 21:09:54 UTC (rev 13718) @@ -431,6 +431,7 @@
PEX_CALLBACK_FUNCTION Function; PVOID Context; LARGE_INTEGER Cookie; + BOOLEAN PendingDelete; } REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
NTSTATUS _____
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c --- trunk/reactos/ntoskrnl/cm/ntfunc.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/cm/ntfunc.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -50,6 +50,7 @@
ExInitializeRundownProtection(&Callback->RundownRef); Callback->Function = Function; Callback->Context = Context; + Callback->PendingDelete = FALSE;
/* add it to the callback list and receive a cookie for the callback */ ExAcquireFastMutex(&CmiCallbackLock); @@ -87,22 +88,32 @@ CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry); if(CurrentCallback->Cookie.QuadPart == Cookie.QuadPart) { - /* found the callback, don't unlink it from the list yet so we don't screw - the calling loop */ - ExReleaseFastMutex(&CmiCallbackLock); + if(!CurrentCallback->PendingDelete) + { + /* found the callback, don't unlink it from the list yet so we don't screw + the calling loop */ + CurrentCallback->PendingDelete = TRUE; + ExReleaseFastMutex(&CmiCallbackLock);
- /* if the callback is currently executing, wait until it finished */ - ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef); + /* if the callback is currently executing, wait until it finished */ + ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
- /* time to unlink it. It's now safe because every attempt to acquire a - runtime protection on this callback will fail */ - ExAcquireFastMutex(&CmiCallbackLock); - RemoveEntryList(&CurrentCallback->ListEntry); - ExReleaseFastMutex(&CmiCallbackLock); + /* time to unlink it. It's now safe because every attempt to acquire a + runtime protection on this callback will fail */ + ExAcquireFastMutex(&CmiCallbackLock); + RemoveEntryList(&CurrentCallback->ListEntry); + ExReleaseFastMutex(&CmiCallbackLock);
- /* free the callback */ - ExFreePool(CurrentCallback); - return STATUS_SUCCESS; + /* free the callback */ + ExFreePool(CurrentCallback); + return STATUS_SUCCESS; + } + else + { + /* pending delete, pretend like it already is deleted */ + ExReleaseFastMutex(&CmiCallbackLock); + return STATUS_UNSUCCESSFUL; + } } }
@@ -127,7 +138,8 @@ PREGISTRY_CALLBACK CurrentCallback;
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry); - if(ExAcquireRundownProtectionEx(&CurrentCallback->RundownRef, 1)) + if(!CurrentCallback->PendingDelete && + ExAcquireRundownProtectionEx(&CurrentCallback->RundownRef, 1)) { NTSTATUS Status;
_____
Modified: trunk/reactos/ntoskrnl/ob/dirobj.c --- trunk/reactos/ntoskrnl/ob/dirobj.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/ob/dirobj.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -50,6 +50,8 @@
KPROCESSOR_MODE PreviousMode; NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE(); + PreviousMode = ExGetPreviousMode();
if(PreviousMode != KernelMode) @@ -169,6 +171,8 @@ ULONG NextEntry = 0; NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE(); + PreviousMode = ExGetPreviousMode();
if(PreviousMode != KernelMode) @@ -427,6 +431,8 @@ KPROCESSOR_MODE PreviousMode; NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE(); + DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, " "DesiredAccess %x, ObjectAttributes %x\n", DirectoryHandle, DesiredAccess, ObjectAttributes); _____
Modified: trunk/reactos/ntoskrnl/ob/handle.c --- trunk/reactos/ntoskrnl/ob/handle.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/ob/handle.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -287,7 +287,7 @@
HANDLE TargetHandle; NTSTATUS Status;
- ASSERT_IRQL(PASSIVE_LEVEL); + PAGED_CODE();
Status = ObReferenceObjectByHandle(SourceProcessHandle, PROCESS_DUP_HANDLE, @@ -552,6 +552,8 @@ PHANDLE_TABLE HandleTable; POBJECT_HEADER Header; HANDLE_BLOCK *Block; + + PAGED_CODE();
DPRINT("ObDeleteHandle(Handle %x)\n",Handle);
@@ -630,6 +632,8 @@ HANDLE_BLOCK* new_blk = NULL; PHANDLE_TABLE HandleTable; KIRQL oldlvl; + + PAGED_CODE();
DPRINT("ObCreateHandle(Process %x, obj %x)\n",Process,ObjectBody);
@@ -723,6 +727,8 @@ PEPROCESS Process; KIRQL oldIrql; PHANDLE_ENTRY HandleEntry; + + PAGED_CODE();
DPRINT("ObQueryObjectAuditingByHandle(Handle %x)\n", Handle);
@@ -777,7 +783,7 @@ ULONG Attributes; NTSTATUS Status;
- ASSERT_IRQL(PASSIVE_LEVEL); + PAGED_CODE();
DPRINT("ObReferenceObjectByHandle(Handle %x, DesiredAccess %x, " "ObjectType %x, AccessMode %d, Object %x)\n",Handle,DesiredAccess, @@ -930,7 +936,7 @@ POBJECT_HEADER Header; NTSTATUS Status;
- ASSERT_IRQL(PASSIVE_LEVEL); + PAGED_CODE();
DPRINT("NtClose(Handle %x)\n",Handle);
@@ -966,6 +972,8 @@ { POBJECT_HEADER ObjectHeader; ACCESS_MASK Access; + + PAGED_CODE();
Access = DesiredAccess; ObjectHeader = BODY_TO_HEADER(Object); _____
Modified: trunk/reactos/ntoskrnl/ob/namespc.c --- trunk/reactos/ntoskrnl/ob/namespc.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/ob/namespc.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -55,6 +55,8 @@
UNICODE_STRING RemainingPath; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; + + PAGED_CODE();
InitializeObjectAttributes(&ObjectAttributes, ObjectPath, @@ -126,6 +128,8 @@ UNICODE_STRING RemainingPath; PVOID Object = NULL; NTSTATUS Status; + + PAGED_CODE();
DPRINT("ObOpenObjectByName(...)\n");
_____
Modified: trunk/reactos/ntoskrnl/ob/ntobj.c --- trunk/reactos/ntoskrnl/ob/ntobj.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/ob/ntobj.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -37,6 +37,8 @@
{ PVOID Object; NTSTATUS Status; + + PAGED_CODE();
if (ObjectInformationClass != ObjectHandleInformation) return STATUS_INVALID_INFO_CLASS; @@ -88,6 +90,8 @@ ULONG InfoLength; PVOID Object; NTSTATUS Status; + + PAGED_CODE();
Status = ObReferenceObjectByHandle (ObjectHandle, 0, @@ -260,6 +264,8 @@ { PVOID ObjectBody; NTSTATUS Status; + + PAGED_CODE();
Status = ObReferenceObjectByHandle(ObjectHandle, 0, @@ -299,6 +305,8 @@ { PVOID ObjectBody; NTSTATUS Status; + + PAGED_CODE();
Status = ObReferenceObjectByHandle(ObjectHandle, 0, _____
Modified: trunk/reactos/ntoskrnl/ob/object.c --- trunk/reactos/ntoskrnl/ob/object.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/ob/object.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -346,6 +346,8 @@
UNICODE_STRING PathString; ULONG Attributes; PUNICODE_STRING ObjectName; + + PAGED_CODE();
DPRINT("ObFindObject(ObjectAttributes %x, ReturnedObject %x, " "RemainingPath %x)\n",ObjectAttributes,ReturnedObject,RemainingPath); @@ -483,6 +485,8 @@ POBJECT_HEADER ObjectHeader; ULONG LocalReturnLength; NTSTATUS Status; + + PAGED_CODE();
*ReturnLength = 0;
@@ -611,7 +615,7 @@ PSECURITY_DESCRIPTOR NewSecurityDescriptor = NULL; SECURITY_SUBJECT_CONTEXT SubjectContext;
- ASSERT_IRQL(APC_LEVEL); + PAGED_CODE();
if(ObjectAttributesAccessMode == UserMode && ObjectAttributes != NULL) { @@ -814,6 +818,8 @@ IN KPROCESSOR_MODE AccessMode) { POBJECT_HEADER Header; + + /* NOTE: should be possible to reference an object above APC_LEVEL! */
DPRINT("ObReferenceObjectByPointer(Object %x, ObjectType %x)\n", Object,ObjectType); @@ -876,6 +882,8 @@ { NTSTATUS Status;
+ PAGED_CODE(); + DPRINT("ObOpenObjectByPointer()\n");
Status = ObReferenceObjectByPointer(Object, @@ -1117,6 +1125,8 @@ ObGetObjectPointerCount(PVOID Object) { POBJECT_HEADER Header; + + PAGED_CODE();
ASSERT(Object); Header = BODY_TO_HEADER(Object); @@ -1142,6 +1152,8 @@ ObGetObjectHandleCount(PVOID Object) { POBJECT_HEADER Header; + + PAGED_CODE();
ASSERT(Object); Header = BODY_TO_HEADER(Object); _____
Modified: trunk/reactos/ntoskrnl/ob/security.c --- trunk/reactos/ntoskrnl/ob/security.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/ob/security.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -1,4 +1,4 @@
-/* $Id:$ +/* $Id$ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -27,6 +27,8 @@ { PSECURITY_DESCRIPTOR NewDescriptor; NTSTATUS Status; + + PAGED_CODE();
/* Build the new security descriptor */ Status = SeAssignSecurity(SecurityDescriptor, @@ -73,6 +75,8 @@ POBJECT_HEADER Header; ULONG Length; NTSTATUS Status; + + PAGED_CODE();
Header = BODY_TO_HEADER(Object); if (Header->ObjectType == NULL) @@ -129,6 +133,8 @@ ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN BOOLEAN MemoryAllocated) { + PAGED_CODE(); + if (SecurityDescriptor == NULL) return;
@@ -156,6 +162,8 @@ POBJECT_HEADER Header; PVOID Object; NTSTATUS Status; + + PAGED_CODE();
DPRINT("NtQuerySecurityObject() called\n");
@@ -226,6 +234,8 @@ ULONG Control = 0; ULONG_PTR Current; NTSTATUS Status; + + PAGED_CODE();
DPRINT("NtSetSecurityObject() called\n");
_____
Modified: trunk/reactos/ntoskrnl/ob/symlink.c --- trunk/reactos/ntoskrnl/ob/symlink.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/ob/symlink.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -206,61 +206,104 @@
IN POBJECT_ATTRIBUTES ObjectAttributes, IN PUNICODE_STRING LinkTarget) { + HANDLE hLink; PSYMLINK_OBJECT SymbolicLink; - NTSTATUS Status; + UNICODE_STRING CapturedLinkTarget; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS;
- ASSERT_IRQL(PASSIVE_LEVEL); + PAGED_CODE(); + + PreviousMode = ExGetPreviousMode();
+ if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(LinkHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = RtlCaptureUnicodeString(&CapturedLinkTarget, + PreviousMode, + PagedPool, + FALSE, + LinkTarget); + if(!NT_SUCCESS(Status)) + { + DPRINT1("NtCreateSymbolicLinkObject: Capturing the target link failed!\n"); + return Status; + } + DPRINT("NtCreateSymbolicLinkObject(LinkHandle %p, DesiredAccess %ul, ObjectAttributes %p, LinkTarget %wZ)\n", LinkHandle, DesiredAccess, ObjectAttributes, - LinkTarget); + &CapturedLinkTarget);
Status = ObCreateObject(ExGetPreviousMode(), ObSymbolicLinkType, ObjectAttributes, - ExGetPreviousMode(), + PreviousMode, NULL, sizeof(SYMLINK_OBJECT), 0, 0, (PVOID*)&SymbolicLink); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + if (NT_SUCCESS(Status)) + { + SymbolicLink->TargetName.Length = 0; + SymbolicLink->TargetName.MaximumLength = + ((wcslen(LinkTarget->Buffer) + 1) * sizeof(WCHAR)); + SymbolicLink->TargetName.Buffer = + ExAllocatePoolWithTag(NonPagedPool, + SymbolicLink->TargetName.MaximumLength, + TAG_SYMLINK_TARGET); + RtlCopyUnicodeString(&SymbolicLink->TargetName, + &CapturedLinkTarget);
- Status = ObInsertObject ((PVOID)SymbolicLink, - NULL, - DesiredAccess, - 0, - NULL, - LinkHandle); - if (!NT_SUCCESS(Status)) + DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer); + + ZwQuerySystemTime (&SymbolicLink->CreateTime); + + Status = ObInsertObject ((PVOID)SymbolicLink, + NULL, + DesiredAccess, + 0, + NULL, + &hLink); + if (NT_SUCCESS(Status)) { - ObDereferenceObject (SymbolicLink); - return Status; + _SEH_TRY + { + *LinkHandle = hLink; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; } + ObDereferenceObject(SymbolicLink); + } + + RtlReleaseCapturedUnicodeString(&CapturedLinkTarget, + PreviousMode, + FALSE);
- SymbolicLink->TargetName.Length = 0; - SymbolicLink->TargetName.MaximumLength = - ((wcslen(LinkTarget->Buffer) + 1) * sizeof(WCHAR)); - SymbolicLink->TargetName.Buffer = - ExAllocatePoolWithTag(NonPagedPool, - SymbolicLink->TargetName.MaximumLength, - TAG_SYMLINK_TARGET); - RtlCopyUnicodeString(&SymbolicLink->TargetName, - LinkTarget); - - DPRINT("DeviceName %S\n", SymbolicLink->TargetName.Buffer); - - ZwQuerySystemTime (&SymbolicLink->CreateTime); - - DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__); - ObDereferenceObject(SymbolicLink); - - return(STATUS_SUCCESS); + return Status; }
@@ -282,16 +325,58 @@ IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes) { + HANDLE hLink; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForWrite(LinkHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + DPRINT("NtOpenSymbolicLinkObject (Name %wZ)\n", ObjectAttributes->ObjectName);
- return(ObOpenObjectByName(ObjectAttributes, - ObSymbolicLinkType, - NULL, - (KPROCESSOR_MODE)KeGetPreviousMode(), - DesiredAccess, - NULL, - LinkHandle)); + Status = ObOpenObjectByName(ObjectAttributes, + ObSymbolicLinkType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + &hLink); + if(NT_SUCCESS(Status)) + { + _SEH_TRY + { + *LinkHandle = hLink; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; }
@@ -313,38 +398,93 @@ OUT PUNICODE_STRING LinkTarget, OUT PULONG ResultLength OPTIONAL) { + UNICODE_STRING SafeLinkTarget; PSYMLINK_OBJECT SymlinkObject; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PAGED_CODE(); + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY + { + /* probe the unicode string and buffers supplied */ + ProbeForWrite(LinkTarget, + sizeof(UNICODE_STRING), + sizeof(ULONG)); + SafeLinkTarget = *LinkTarget; + ProbeForWrite(SafeLinkTarget.Buffer, + SafeLinkTarget.MaximumLength, + sizeof(WCHAR));
+ if(ResultLength != NULL) + { + ProbeForWrite(ResultLength, + sizeof(ULONG), + sizeof(ULONG)); + } + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + else + { + SafeLinkTarget = *LinkTarget; + } + Status = ObReferenceObjectByHandle(LinkHandle, SYMBOLIC_LINK_QUERY, ObSymbolicLinkType, - (KPROCESSOR_MODE)KeGetPreviousMode(), + PreviousMode, (PVOID *)&SymlinkObject, NULL); - if (!NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) + { + ULONG LengthRequired = SymlinkObject->TargetName.Length + sizeof(WCHAR); + + _SEH_TRY { - return Status; + if(SafeLinkTarget.MaximumLength >= LengthRequired) + { + /* don't pass TargetLink to RtlCopyUnicodeString here because the caller + might have modified the structure which could lead to a copy into + kernel memory! */ + RtlCopyUnicodeString(&SafeLinkTarget, + &SymlinkObject->TargetName); + SafeLinkTarget.Buffer[SafeLinkTarget.Length / sizeof(WCHAR)] = L'\0'; + /* copy back the new UNICODE_STRING structure */ + *LinkTarget = SafeLinkTarget; + } + else + { + Status = STATUS_BUFFER_TOO_SMALL; + } + + if(ResultLength != NULL) + { + *ResultLength = LengthRequired; + } } - - if (ResultLength != NULL) + _SEH_HANDLE { - *ResultLength = (ULONG)SymlinkObject->TargetName.Length + sizeof(WCHAR); + Status = _SEH_GetExceptionCode(); } + _SEH_END;
- if (LinkTarget->MaximumLength >= SymlinkObject->TargetName.Length + sizeof(WCHAR)) - { - RtlCopyUnicodeString(LinkTarget, - &SymlinkObject->TargetName); - Status = STATUS_SUCCESS; - } - else - { - Status = STATUS_BUFFER_TOO_SMALL; - } + ObDereferenceObject(SymlinkObject); + }
- ObDereferenceObject(SymlinkObject); - return Status; }
_____
Modified: trunk/reactos/ntoskrnl/po/power.c --- trunk/reactos/ntoskrnl/po/power.c 2005-02-22 20:08:06 UTC (rev 13717) +++ trunk/reactos/ntoskrnl/po/power.c 2005-02-22 21:09:54 UTC (rev 13718) @@ -91,6 +91,8 @@
IN POWER_STATE State) { POWER_STATE ps; + + ASSERT_IRQL(DISPATCH_LEVEL);
ps.SystemState = PowerSystemWorking; // Fully on ps.DeviceState = PowerDeviceD0; // Fully on @@ -228,6 +230,8 @@ ) { NTSTATUS Status; + + PAGED_CODE();
DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, " "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",