- Fix ExChangeHandle not to send NULL but the actual context to the callback function (fix by Thomas Weidenmueller <w3seek@reactos.org>)

- Re-implement NtSetInformationObject based on ExChangeHandle and using ObpSetHandleAttributes as a callback.
- Re-implement NtQueryObject's ObjectHandleInformation case to simply return the information that's already in HandleAttributes; there is no point in querying for it all over again.
- Fix NtSetInformationObject not to allow a user-mode call to modify kernel-mdoe handle attributes. Add FIXME for Inheritance permissions check.
- Fix NtQueryObject to properly return OBJ_PERMANENT and OBJ_EXCLUSIVE; these flags are not stored in Handle Attributes.
- Fix NtQueryObject not to attempt referencing the handle if the caller specified AllTypesInformation, because then a handle is not needed.

svn path=/trunk/; revision=22228
This commit is contained in:
Alex Ionescu 2006-06-05 00:04:36 +00:00
parent 7c2e312093
commit 02d0bb9dbd
4 changed files with 203 additions and 182 deletions

View file

@ -916,7 +916,7 @@ ExChangeHandle(IN PHANDLE_TABLE HandleTable,
{ {
Ret = ChangeHandleCallback(HandleTable, Ret = ChangeHandleCallback(HandleTable,
HandleTableEntry, HandleTableEntry,
NULL); Context);
ExUnlockHandleTableEntry(HandleTable, ExUnlockHandleTableEntry(HandleTable,
HandleTableEntry); HandleTableEntry);

View file

@ -9,6 +9,12 @@
#ifndef __INCLUDE_INTERNAL_OBJMGR_H #ifndef __INCLUDE_INTERNAL_OBJMGR_H
#define __INCLUDE_INTERNAL_OBJMGR_H #define __INCLUDE_INTERNAL_OBJMGR_H
typedef struct _OBP_SET_HANDLE_ATTRIBUTES_CONTEXT
{
KPROCESSOR_MODE PreviousMode;
OBJECT_HANDLE_ATTRIBUTE_INFORMATION Information;
} OBP_SET_HANDLE_ATTRIBUTES_CONTEXT, *POBP_SET_HANDLE_ATTRIBUTES_CONTEXT;
#define GENERIC_ACCESS (GENERIC_READ | \ #define GENERIC_ACCESS (GENERIC_READ | \
GENERIC_WRITE | \ GENERIC_WRITE | \
GENERIC_EXECUTE | \ GENERIC_EXECUTE | \
@ -100,18 +106,12 @@ ObFindObject(
IN PVOID Insert IN PVOID Insert
); );
NTSTATUS BOOLEAN
NTAPI
ObpQueryHandleAttributes(
HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
);
NTSTATUS
NTAPI NTAPI
ObpSetHandleAttributes( ObpSetHandleAttributes(
HANDLE Handle, IN PHANDLE_TABLE HandleTable,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
IN PVOID Context
); );
NTSTATUS NTSTATUS

View file

@ -154,129 +154,51 @@ ObpDecrementHandleCount(PVOID ObjectBody)
} }
} }
NTSTATUS BOOLEAN
NTAPI NTAPI
ObpQueryHandleAttributes(HANDLE Handle, ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo) IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
IN PVOID Context)
{ {
PHANDLE_TABLE_ENTRY HandleTableEntry; POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo =
PEPROCESS Process, CurrentProcess; (POBP_SET_HANDLE_ATTRIBUTES_CONTEXT)Context;
KAPC_STATE ApcState; POBJECT_HEADER ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
BOOLEAN AttachedToProcess = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
DPRINT("ObpQueryHandleAttributes(Handle %p)\n", Handle); /* Don't allow operations on kernel objects */
CurrentProcess = PsGetCurrentProcess(); if ((ObjectHeader->Flags & OB_FLAG_KERNEL_MODE) &&
(SetHandleInfo->PreviousMode != KernelMode))
KeEnterCriticalRegion();
if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
{ {
Process = PsInitialSystemProcess; /* Fail */
Handle = ObKernelHandleToHandle(Handle); return FALSE;
}
if (Process != CurrentProcess) /* Check if making the handle inheritable */
{ if (SetHandleInfo->Information.Inherit)
KeStackAttachProcess(&Process->Pcb, {
&ApcState); /* Set the flag. FIXME: Need to check if this is allowed */
AttachedToProcess = TRUE; HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
}
} }
else else
{ {
Process = CurrentProcess; /* Otherwise this implies we're removing the flag */
HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
} }
HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable, /* Check if making the handle protected */
Handle); if (SetHandleInfo->Information.ProtectFromClose)
if (HandleTableEntry != NULL)
{ {
HandleInfo->Inherit = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0; /* Set the flag */
HandleInfo->ProtectFromClose = (HandleTableEntry->ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0; HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
ExUnlockHandleTableEntry(Process->ObjectTable,
HandleTableEntry);
}
else
Status = STATUS_INVALID_HANDLE;
if (AttachedToProcess)
{
KeUnstackDetachProcess(&ApcState);
}
KeLeaveCriticalRegion();
return Status;
}
NTSTATUS
NTAPI
ObpSetHandleAttributes(HANDLE Handle,
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo)
{
PHANDLE_TABLE_ENTRY HandleTableEntry;
PEPROCESS Process, CurrentProcess;
KAPC_STATE ApcState;
BOOLEAN AttachedToProcess = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DPRINT("ObpSetHandleAttributes(Handle %p)\n", Handle);
CurrentProcess = PsGetCurrentProcess();
KeEnterCriticalRegion();
if(ObIsKernelHandle(Handle, ExGetPreviousMode()))
{
Process = PsInitialSystemProcess;
Handle = ObKernelHandleToHandle(Handle);
if (Process != CurrentProcess)
{
KeStackAttachProcess(&Process->Pcb,
&ApcState);
AttachedToProcess = TRUE;
}
} }
else else
{ {
Process = CurrentProcess; /* Otherwise, remove it */
HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
} }
HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable, /* Return success */
Handle); return TRUE;
if (HandleTableEntry != NULL)
{
if (HandleInfo->Inherit)
HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_INHERITABLE;
else
HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_INHERITABLE;
if (HandleInfo->ProtectFromClose)
HandleTableEntry->ObAttributes |= EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
else
HandleTableEntry->ObAttributes &= ~EX_HANDLE_ENTRY_PROTECTFROMCLOSE;
/* FIXME: Do we need to set anything in the object header??? */
ExUnlockHandleTableEntry(Process->ObjectTable,
HandleTableEntry);
}
else
Status = STATUS_INVALID_HANDLE;
if (AttachedToProcess)
{
KeUnstackDetachProcess(&ApcState);
}
KeLeaveCriticalRegion();
return Status;
} }
static NTSTATUS static NTSTATUS

View file

@ -790,95 +790,157 @@ NtQueryObject(IN HANDLE ObjectHandle,
OUT PULONG ResultLength OPTIONAL) OUT PULONG ResultLength OPTIONAL)
{ {
OBJECT_HANDLE_INFORMATION HandleInfo; OBJECT_HANDLE_INFORMATION HandleInfo;
POBJECT_HEADER ObjectHeader; POBJECT_HEADER ObjectHeader = NULL;
POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
POBJECT_BASIC_INFORMATION BasicInfo;
ULONG InfoLength; ULONG InfoLength;
PVOID Object; PVOID Object = NULL;
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE(); PAGED_CODE();
Status = ObReferenceObjectByHandle(ObjectHandle, /* FIXME: Needs SEH */
0,
NULL,
KeGetPreviousMode(),
&Object,
&HandleInfo);
if (!NT_SUCCESS (Status)) return Status;
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); /*
* Make sure this isn't a generic type query, since the caller doesn't
* have to give a handle for it
*/
if (ObjectInformationClass != ObjectAllTypesInformation)
{
/* Reference the object */
Status = ObReferenceObjectByHandle(ObjectHandle,
0,
NULL,
KeGetPreviousMode(),
&Object,
&HandleInfo);
if (!NT_SUCCESS (Status)) return Status;
/* Get the object header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
}
/* Check the information class */
switch (ObjectInformationClass) switch (ObjectInformationClass)
{ {
case ObjectBasicInformation: /* Basic info */
InfoLength = sizeof(OBJECT_BASIC_INFORMATION); case ObjectBasicInformation:
if (Length != sizeof(OBJECT_BASIC_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
}
else
{
POBJECT_BASIC_INFORMATION BasicInfo;
/* Validate length */
InfoLength = sizeof(OBJECT_BASIC_INFORMATION);
if (Length != sizeof(OBJECT_BASIC_INFORMATION))
{
/* Fail */
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Fill out the basic information */
BasicInfo = (POBJECT_BASIC_INFORMATION)ObjectInformation; BasicInfo = (POBJECT_BASIC_INFORMATION)ObjectInformation;
BasicInfo->Attributes = HandleInfo.HandleAttributes; BasicInfo->Attributes = HandleInfo.HandleAttributes;
BasicInfo->GrantedAccess = HandleInfo.GrantedAccess; BasicInfo->GrantedAccess = HandleInfo.GrantedAccess;
BasicInfo->HandleCount = ObjectHeader->HandleCount; BasicInfo->HandleCount = ObjectHeader->HandleCount;
BasicInfo->PointerCount = ObjectHeader->PointerCount; BasicInfo->PointerCount = ObjectHeader->PointerCount;
/* Permanent/Exclusive Flags are NOT in Handle attributes! */
if (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE)
{
/* Set the flag */
BasicInfo->Attributes |= OBJ_EXCLUSIVE;
}
if (ObjectHeader->Flags & OB_FLAG_PERMANENT)
{
/* Set the flag */
BasicInfo->Attributes |= OBJ_PERMANENT;
}
/* Copy quota information */
BasicInfo->PagedPoolUsage = 0; /* FIXME*/ BasicInfo->PagedPoolUsage = 0; /* FIXME*/
BasicInfo->NonPagedPoolUsage = 0; /* FIXME*/ BasicInfo->NonPagedPoolUsage = 0; /* FIXME*/
/* Copy name information */
BasicInfo->NameInformationLength = 0; /* FIXME*/ BasicInfo->NameInformationLength = 0; /* FIXME*/
BasicInfo->TypeInformationLength = 0; /* FIXME*/ BasicInfo->TypeInformationLength = 0; /* FIXME*/
/* Copy security information */
BasicInfo->SecurityDescriptorLength = 0; /* FIXME*/ BasicInfo->SecurityDescriptorLength = 0; /* FIXME*/
/* Check if this is a symlink */
if (ObjectHeader->Type == ObSymbolicLinkType) if (ObjectHeader->Type == ObSymbolicLinkType)
{ {
/* Return the creation time */
BasicInfo->CreateTime.QuadPart = BasicInfo->CreateTime.QuadPart =
((POBJECT_SYMBOLIC_LINK)Object)->CreationTime.QuadPart; ((POBJECT_SYMBOLIC_LINK)Object)->CreationTime.QuadPart;
} }
else else
{ {
/* Otherwise return 0 */
BasicInfo->CreateTime.QuadPart = (ULONGLONG)0; BasicInfo->CreateTime.QuadPart = (ULONGLONG)0;
} }
/* Break out with success */
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} break;
break;
case ObjectNameInformation: /* Name information */
Status = ObQueryNameString(Object, case ObjectNameInformation:
(POBJECT_NAME_INFORMATION)ObjectInformation,
Length,
&InfoLength);
break;
case ObjectTypeInformation: /* Call the helper and break out */
Status = STATUS_NOT_IMPLEMENTED; Status = ObQueryNameString(Object,
break; (POBJECT_NAME_INFORMATION)
ObjectInformation,
Length,
&InfoLength);
break;
case ObjectAllTypesInformation: /* Information about this type */
Status = STATUS_NOT_IMPLEMENTED; case ObjectTypeInformation:
break; DPRINT1("NOT IMPLEMENTED!\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
case ObjectHandleInformation: /* Information about all types */
InfoLength = sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION); case ObjectAllTypesInformation:
if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION)) DPRINT1("NOT IMPLEMENTED!\n");
{ Status = STATUS_NOT_IMPLEMENTED;
Status = STATUS_INFO_LENGTH_MISMATCH; break;
}
else
{
Status = ObpQueryHandleAttributes(
ObjectHandle,
(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)ObjectInformation);
}
break;
default: /* Information about the handle flags */
Status = STATUS_INVALID_INFO_CLASS; case ObjectHandleInformation:
break;
/* Validate length */
InfoLength = sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION);
if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
/* Get the structure */
HandleFlags = (POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
ObjectInformation;
/* Set the flags */
HandleFlags->Inherit = (HandleInfo.HandleAttributes &
EX_HANDLE_ENTRY_INHERITABLE) != 0;
HandleFlags->ProtectFromClose = (HandleInfo.HandleAttributes &
EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0;
/* Break out with success */
Status = STATUS_SUCCESS;
break;
/* Anything else */
default:
/* Fail it */
Status = STATUS_INVALID_INFO_CLASS;
break;
} }
ObDereferenceObject (Object); /* Derefernece the object if we had referenced it */
if (Object) ObDereferenceObject (Object);
if (ResultLength != NULL) *ResultLength = InfoLength;
/* Return the length and status */
if (ResultLength) *ResultLength = InfoLength;
return Status; return Status;
} }
@ -912,29 +974,66 @@ NtSetInformationObject(IN HANDLE ObjectHandle,
IN PVOID ObjectInformation, IN PVOID ObjectInformation,
IN ULONG Length) IN ULONG Length)
{ {
PVOID Object; NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS Status; OBP_SET_HANDLE_ATTRIBUTES_CONTEXT Context;
PVOID ObjectTable;
KAPC_STATE ApcState;
BOOLEAN AttachedToProcess = FALSE;
PAGED_CODE(); PAGED_CODE();
/* Validate the information class */
if (ObjectInformationClass != ObjectHandleInformation) if (ObjectInformationClass != ObjectHandleInformation)
{
/* Invalid class */
return STATUS_INVALID_INFO_CLASS; return STATUS_INVALID_INFO_CLASS;
}
/* Validate the length */
if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION)) if (Length != sizeof (OBJECT_HANDLE_ATTRIBUTE_INFORMATION))
{
/* Invalid length */
return STATUS_INFO_LENGTH_MISMATCH; return STATUS_INFO_LENGTH_MISMATCH;
}
Status = ObReferenceObjectByHandle(ObjectHandle, /* Save the previous mode and actual information */
0, Context.PreviousMode = ExGetPreviousMode();
NULL, Context.Information = *(POBJECT_HANDLE_ATTRIBUTE_INFORMATION)
KeGetPreviousMode(), ObjectInformation;
&Object,
NULL);
if (!NT_SUCCESS (Status)) return Status;
Status = ObpSetHandleAttributes(ObjectHandle, /* Check if this is a kernel handle */
(POBJECT_HANDLE_ATTRIBUTE_INFORMATION) if (ObIsKernelHandle(ObjectHandle, Context.PreviousMode))
ObjectInformation); {
/* Get the actual handle */
ObjectHandle = ObKernelHandleToHandle(ObjectHandle);
ObjectTable = ObpKernelHandleTable;
ObDereferenceObject (Object); /* Check if we're not in the system process */
if (PsGetCurrentProcess() != PsInitialSystemProcess)
{
/* Attach to it */
KeStackAttachProcess(&PsInitialSystemProcess->Pcb, &ApcState);
AttachedToProcess = TRUE;
}
}
else
{
/* Use the current table */
ObjectTable = PsGetCurrentProcess()->ObjectTable;
}
/* Change the handle attributes */
if (!ExChangeHandle(ObjectTable,
ObjectHandle,
ObpSetHandleAttributes,
&Context))
{
/* Some failure */
Status = STATUS_ACCESS_DENIED;
}
/* De-attach if we were attached, and return status */
if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
return Status; return Status;
} }
/* EOF */ /* EOF */