Beispiel #1
0
BOOLEAN
ObDupHandleProcedure(
    PEPROCESS Process,
    PVOID HandleTableEntry
    )
{
    NTSTATUS Status;
    POBJECT_TABLE_ENTRY ObjectTableEntry = HandleTableEntry;
    POBJECT_HEADER ObjectHeader;
    PVOID Object;
    ACCESS_STATE AccessState;

    if (!(ObjectTableEntry->Attributes & OBJ_INHERIT)) {
        return( FALSE );
        }

    ObjectHeader = (POBJECT_HEADER)
        (ObjectTableEntry->Attributes & ~OBJ_HANDLE_ATTRIBUTES);

    Object = &ObjectHeader->Body;
#if i386 && !FPO
    if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
        AccessState.PreviouslyGrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
        }
    else
#endif // i386 && !FPO
    AccessState.PreviouslyGrantedAccess = ObjectTableEntry->GrantedAccess;
    Status = ObpIncrementHandleCount( ObInheritHandle,
                                      Process,
                                      Object,
                                      ObjectHeader->Type,
                                      &AccessState,
                                      KernelMode,     // BUGBUG this is probably wrong
                                      0
                                    );
    if (!NT_SUCCESS( Status )) {
        return( FALSE );
        }

    ObpIncrPointerCount( ObjectHeader );
    return( TRUE );
}
Beispiel #2
0
BOOLEAN
ObpEnumFindHandleProcedure(
    PVOID HandleTableEntry,
    PVOID HandleId,
    PVOID EnumParameter
    )

/*++

Routine Description:

    Call back routine when enumerating an object table to find a handle
    for a particular object and/or

Arguments:

    argument-name - Supplies | Returns description of argument.
    .
    .

Return Value:

    Returns TRUE if a match is found and the enumeration should stop.  Returns FALSE
    otherwise, so the enumeration will continue.

--*/
{
    POBJECT_TABLE_ENTRY ObjectTableEntry = HandleTableEntry;
    POBJECT_HEADER ObjectHeader;
    ACCESS_MASK GrantedAccess;
    ULONG HandleAttributes;
    POBP_FIND_HANDLE_DATA MatchCriteria = EnumParameter;

    ObjectHeader = (POBJECT_HEADER)((ULONG)ObjectTableEntry->ObjectHeader & ~OBJ_HANDLE_ATTRIBUTES);
    if (MatchCriteria->ObjectHeader != NULL &&
        MatchCriteria->ObjectHeader != ObjectHeader
       ) {
        return FALSE;
        }

    if (MatchCriteria->ObjectType != NULL &&
        MatchCriteria->ObjectType != ObjectHeader->Type
       ) {
        return FALSE;
        }

    if (ARGUMENT_PRESENT( MatchCriteria->HandleInformation )) {
#if i386 && !FPO
        if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
            GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
            }
        else
#endif // i386 && !FPO
        GrantedAccess = ObjectTableEntry->GrantedAccess;
        HandleAttributes = (ULONG)ObjectTableEntry->ObjectHeader & OBJ_HANDLE_ATTRIBUTES;
        if (MatchCriteria->HandleInformation->HandleAttributes != HandleAttributes ||
            MatchCriteria->HandleInformation->GrantedAccess != GrantedAccess
           ) {
            return FALSE;
            }
        }

    return TRUE;
}
Beispiel #3
0
NTSTATUS
NtClose (
    IN HANDLE Handle
    )

/*++

Routine Description:

    This function is used to close access to the specified handle

Arguments:

    Handle - Supplies the handle being closed

Return Value:

    An appropriate status value

--*/

{
    PHANDLE_TABLE ObjectTable;
    PHANDLE_TABLE_ENTRY ObjectTableEntry;
    PVOID Object;
    ULONG CapturedGrantedAccess;
    ULONG CapturedAttributes;
    POBJECT_HEADER ObjectHeader;
    POBJECT_TYPE ObjectType;
    NTSTATUS Status;
    BOOLEAN AttachedToProcess = FALSE;
    KAPC_STATE ApcState;

    //
    //  Protect ourselves from being interrupted while we hold a handle table
    //  entry lock
    //

    KeEnterCriticalRegion();

    try {

    #if DBG
        KIRQL SaveIrql;
    #endif // DBG

        ObpValidateIrql( "NtClose" );

        ObpBeginTypeSpecificCallOut( SaveIrql );

    #if DBG

        //
        //  On checked builds, check that if the Kernel handle bit is set, then
        //  we're coming from Kernel mode. We should probably fail the call if
        //  bit set && !Kmode
        //

        if ((Handle != NtCurrentThread()) && (Handle != NtCurrentProcess())) {

            ASSERT((Handle < 0 ) ? (KeGetPreviousMode() == KernelMode) : TRUE);
        }

    #endif
        //
        //  For the current process we will grab its handle/object table and
        //  translate the handle to its corresponding table entry.  If the
        //  call is successful it also lock down the handle table.  But first
        //  check for a kernel handle and attach and use that table if so.
        //

        if (IsKernelHandle( Handle, KeGetPreviousMode() ))  {

            Handle = DecodeKernelHandle( Handle );

            ObjectTable = ObpKernelHandleTable;

            //
            //  Go to the system process if we have to
            //
            if (PsGetCurrentProcess() != PsInitialSystemProcess) {
               KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState);
               AttachedToProcess = TRUE;
            }

        } else {

            ObjectTable = ObpGetObjectTable();
        }

        ObjectTableEntry = ExMapHandleToPointer( ObjectTable,
                                                 Handle );

        //
        //  Check that the specified handle is legitimate otherwise we can
        //  assume the caller just passed in some bogus handle value
        //

        if (ObjectTableEntry != NULL) {

            //
            //  From the object table entry we can grab a pointer to the object
            //  header, get its type and its body
            //

            ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
            ObjectType = ObjectHeader->Type;
            Object = &ObjectHeader->Body;

            //
            //  If the object type specifies an okay to close procedure then we
            //  need to invoke that callback.  If the callback doesn't want us to
            //  close handle then unlock the object table and return the error
            //  to our caller
            //

            if (ObjectType->TypeInfo.OkayToCloseProcedure != NULL) {

                if (!(*ObjectType->TypeInfo.OkayToCloseProcedure)( PsGetCurrentProcess(), Object, Handle )) {

                    ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object );

                    ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

                    //
                    //  If we are attached to the system process then return
                    //  back to our caller
                    //

                    if (AttachedToProcess) {

                        KeUnstackDetachProcess(&ApcState);
                        AttachedToProcess = FALSE;
                    }

                    Status = STATUS_HANDLE_NOT_CLOSABLE;
                    leave;
                }
            }

            CapturedAttributes = ObjectTableEntry->ObAttributes;

            //
            //  If the previous mode was user and the handle is protected from
            //  being closed, then we'll either raise or return an error depending
            //  on the global flags and debugger port situation.
            //

            if ((CapturedAttributes & OBJ_PROTECT_CLOSE) != 0) {

                if (KeGetPreviousMode() != KernelMode) {

                    ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

                    if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
                        (PsGetCurrentProcess()->DebugPort != NULL)) {

                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE);
                        leave;

                    } else {

                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = STATUS_HANDLE_NOT_CLOSABLE;
                        leave;
                    }

                } else {

                    if ((!PsIsThreadTerminating(PsGetCurrentThread())) &&
                        (PsGetCurrentProcess()->Peb != NULL)) {

                        ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );

    #if DBG
                        //
                        //  bugcheck here on checked builds if kernel mode code is
                        //  closing a protected handle and process is not exiting.
                        //  Ignore if no PEB as this occurs if process is killed
                        //  before really starting.
                        //

                        KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 0, 0, 0);
    #else
                        //
                        //  If we are attached to the system process then return
                        //  back to our caller
                        //

                        if (AttachedToProcess) {
                            KeUnstackDetachProcess(&ApcState);
                            AttachedToProcess = FALSE;
                        }

                        Status = STATUS_HANDLE_NOT_CLOSABLE;
                        leave;
    #endif // DBG

                    }
                }
            }

            //
            //  Get the granted access for the handle
            //

    #if defined(_X86_) && !FPO

            if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {

                CapturedGrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );

            } else {

                CapturedGrantedAccess = ObjectTableEntry->GrantedAccess;
            }

    #else

            CapturedGrantedAccess = ObjectTableEntry->GrantedAccess;

    #endif // _X86_ && !FPO

            //
            //  Now remove the handle from the handle table
            //

            ExDestroyHandle( ObjectTable,
                             Handle,
                             ObjectTableEntry );

            //
            //  perform any auditing required
            //

            //
            //  Extract the value of the GenerateOnClose bit stored
            //  after object open auditing is performed.  This value
            //  was stored by a call to ObSetGenerateOnClosed.
            //

            if (CapturedAttributes & OBJ_AUDIT_OBJECT_CLOSE) {

                if ( SepAdtAuditingEnabled ) {

                    SeCloseObjectAuditAlarm( Object,
                                             (HANDLE)((ULONG_PTR)Handle & ~OBJ_HANDLE_TAGBITS),  // Mask off the tagbits defined for OB objects.
                                             TRUE );
                }
            }

            //
            //  Since we took the handle away we need to decrement the objects
            //  handle count, and remove a reference
            //

            ObpDecrementHandleCount( PsGetCurrentProcess(),
                                     ObjectHeader,
                                     ObjectHeader->Type,
                                     CapturedGrantedAccess );

            ObDereferenceObject( Object );

            ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object );

            //
            //  If we are attached to the system process then return
            //  back to our caller
            //

            if (AttachedToProcess) {
                KeUnstackDetachProcess(&ApcState);
                AttachedToProcess = FALSE;
            }

            //
            //  And return to our caller
            //

            Status = STATUS_SUCCESS;
            leave;

        } else {

            //
            //  At this point the input handle did not translate to a valid
            //  object table entry
            //

            ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObpTypeObjectType, Handle );

            //
            //  If we are attached to the system process then return
            //  back to our caller
            //

            if (AttachedToProcess) {
                KeUnstackDetachProcess(&ApcState);
                AttachedToProcess = FALSE;
            }

            //
            //  Now if the handle is not null and it does not represent the
            //  current thread or process then if we're user mode we either raise
            //  or return an error
            //

            if ((Handle != NULL) &&
                (Handle != NtCurrentThread()) &&
                (Handle != NtCurrentProcess())) {

                if (KeGetPreviousMode() != KernelMode) {

                    if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
                        (PsGetCurrentProcess()->DebugPort != NULL)) {

                        Status = KeRaiseUserException(STATUS_INVALID_HANDLE);
                        leave;

                    } else {

                        Status = STATUS_INVALID_HANDLE;
                        leave;
                    }

                } else {

                    //
                    //  bugcheck here if kernel debugger is enabled and if kernel mode code is
                    //  closing a bogus handle and process is not exiting.  Ignore
                    //  if no PEB as this occurs if process is killed before
                    //  really starting.
                    //

                    if (( !PsIsThreadTerminating(PsGetCurrentThread())) &&
                        (PsGetCurrentProcess()->Peb != NULL)) {

                        if (KdDebuggerEnabled) {
                            KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 1, 0, 0);
                        }
                    }

                }
            }

            Status = STATUS_INVALID_HANDLE;
            leave;
        }

    } finally {

        KeLeaveCriticalRegion();
    }

    return Status;
}