コード例 #1
0
ファイル: obcreate.c プロジェクト: BaoYu0721/WRK-1.2
NTSTATUS
ObCreateObject (
    __in KPROCESSOR_MODE ProbeMode,
    __in POBJECT_TYPE ObjectType,
    __in POBJECT_ATTRIBUTES ObjectAttributes,
    __in KPROCESSOR_MODE OwnershipMode,
    __inout_opt PVOID ParseContext,
    __in ULONG ObjectBodySize,
    __in ULONG PagedPoolCharge,
    __in ULONG NonPagedPoolCharge,
    __out PVOID *Object
    )

/*++

Routine Description:

    This functions allocates space for an NT Object from either
    Paged or NonPaged pool. It captures the optional name and
    SECURITY_DESCRIPTOR parameters for later use when the object is
    inserted into an object table.  No quota is charged at this time.
    That occurs when the object is inserted into an object table.

Arguments:

    ProbeMode - The processor mode to consider when doing a probe
        of the input parameters

    ObjectType - A pointer of the type returned by ObCreateObjectType
        that gives the type of object being created.

    ObjectAttributes - Optionally supplies the attributes of the object
        being created (such as its name)

    OwnershipMode - The processor mode of who is going to own the object

    ParseContext - Ignored

    ObjectBodySize - Number of bytes to allocate for the object body.  The
        object body immediately follows the object header in memory and are
        part of a single allocation.

    PagedPoolCharge - Supplies the amount of paged pool to charge for the
        object.  If zero is specified then the default charge for the object
        type is used.

    NonPagedPoolCharge - Supplies the amount of nonpaged pool to charge for
        the object.  If zero is specified then the default charge for the
        object type is used.

    Object - Receives a pointer to the newly created object

Return Value:

    Following errors can occur:

        - invalid object type
        - insufficient memory

--*/

{
    UNICODE_STRING CapturedObjectName;
    POBJECT_CREATE_INFORMATION ObjectCreateInfo;
    POBJECT_HEADER ObjectHeader;
    NTSTATUS Status;

    PAGED_CODE();

    UNREFERENCED_PARAMETER (ParseContext);

    //
    //  Allocate a buffer to capture the object creation information.
    //

    ObjectCreateInfo = ObpAllocateObjectCreateInfoBuffer();

    if (ObjectCreateInfo == NULL) {

        Status = STATUS_INSUFFICIENT_RESOURCES;

    } else {

        //
        //  Capture the object attributes, quality of service, and object
        //  name, if specified. Otherwise, initialize the captured object
        //  name, the security quality of service, and the create attributes
        //  to default values.
        //

        Status = ObpCaptureObjectCreateInformation( ObjectType,
                                                    ProbeMode,
                                                    OwnershipMode,
                                                    ObjectAttributes,
                                                    &CapturedObjectName,
                                                    ObjectCreateInfo,
                                                    FALSE );

        if (NT_SUCCESS(Status)) {

            //
            //  If the creation attributes are invalid, then return an error
            //  status.
            //

            if (ObjectType->TypeInfo.InvalidAttributes & ObjectCreateInfo->Attributes) {

                Status = STATUS_INVALID_PARAMETER;

            } else {

                //
                //  Set the paged and nonpaged pool quota charges for the
                //  object allocation.
                //

                if (PagedPoolCharge == 0) {

                    PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
                }

                if (NonPagedPoolCharge == 0) {

                    NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
                }

                ObjectCreateInfo->PagedPoolCharge = PagedPoolCharge;
                ObjectCreateInfo->NonPagedPoolCharge = NonPagedPoolCharge;

                //
                //  Allocate and initialize the object.
                //

                Status = ObpAllocateObject( ObjectCreateInfo,
                                            OwnershipMode,
                                            ObjectType,
                                            &CapturedObjectName,
                                            ObjectBodySize,
                                            &ObjectHeader );

                if (NT_SUCCESS(Status)) {

                    //
                    //  If a permanent object is being created, then check if
                    //  the caller has the appropriate privilege.
                    //

                    *Object = &ObjectHeader->Body;

                    if (ObjectHeader->Flags & OB_FLAG_PERMANENT_OBJECT) {

                        if (!SeSinglePrivilegeCheck( SeCreatePermanentPrivilege,
                                                     ProbeMode)) {

                            ObpFreeObject(*Object);

                            Status = STATUS_PRIVILEGE_NOT_HELD;
                        }
                    }

#ifdef POOL_TAGGING
                    if (ObpTraceEnabled && NT_SUCCESS(Status)) {

                        //
                        //  Register the object and push stack information for the
                        //  first reference
                        //

                        ObpRegisterObject( ObjectHeader );
                        ObpPushStackInfo( ObjectHeader, TRUE );
                    }
#endif //POOL_TAGGING

                    //
                    //  Here is the only successful path out of this module but
                    //  this path can also return privilege not held.  In the 
                    //  error case, all the resources have already been freed
                    //  by ObpFreeObject.
                    //

                    return Status;
                }
            }

            //
            //  An error path, free the create information.
            //

            ObpReleaseObjectCreateInformation(ObjectCreateInfo);

            if (CapturedObjectName.Buffer != NULL) {

                ObpFreeObjectNameBuffer(&CapturedObjectName);
            }
        }

        //
        //  An error path, free object creation information buffer.
        //

        ObpFreeObjectCreateInfoBuffer(ObjectCreateInfo);
    }

    //
    //  An error path
    //

    return Status;
}
コード例 #2
0
ファイル: exinit.c プロジェクト: chunhualiu/OpenNT
NTSTATUS
NtDisplayString(
    IN PUNICODE_STRING String
    )

/*++

Routine Description:

    This service calls the HAL to display a string on the console.

    The caller must have SeTcbPrivilege to display a message.

Arguments:

    String - A pointer to the string that is to be displayed.

Return Value:

    !NT_SUCCESS - The operation failed or the caller did not have appropriate
        priviledges.

--*/

{
    KPROCESSOR_MODE PreviousMode;
    UNICODE_STRING CapturedString;
    PUCHAR StringBuffer = NULL;
    PUCHAR AnsiStringBuffer = NULL;
    STRING AnsiString;

    //
    // Check to determine if the caller has the privilege to make this
    // call.
    //

    PreviousMode = KeGetPreviousMode();
    if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) {
        return STATUS_PRIVILEGE_NOT_HELD;
    }

    try {

        //
        // If the previous mode was user, then check the input parameters.
        //

        if (PreviousMode != KernelMode) {

            //
            // Probe and capture the input unicode string descriptor.
            //

            CapturedString = ProbeAndReadUnicodeString(String);

            //
            // If the captured string descriptor has a length of zero, then
            // return success.
            //

            if ((CapturedString.Buffer == 0) ||
                (CapturedString.MaximumLength == 0)) {
                return STATUS_SUCCESS;
            }

            //
            // Probe and capture the input string.
            //
            // N.B. Note the length is in bytes.
            //

            ProbeForRead(
                CapturedString.Buffer,
                CapturedString.MaximumLength,
                sizeof(UCHAR)
                );

            //
            // Allocate a non-paged string buffer because the buffer passed to
            // HalDisplay string must be non-paged.
            //

            StringBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                                  CapturedString.MaximumLength,
                                                  'grtS');

            if ( !StringBuffer ) {
                return STATUS_NO_MEMORY;
            }

            RtlMoveMemory(StringBuffer,
                          CapturedString.Buffer,
                          CapturedString.MaximumLength);

            CapturedString.Buffer = (PWSTR)StringBuffer;

            //
            // Allocate a string buffer for the ansi string.
            //

            AnsiStringBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                                 CapturedString.MaximumLength,
                                                 'grtS');


            if (AnsiStringBuffer == NULL) {
                ExFreePool(StringBuffer);
                return STATUS_NO_MEMORY;
            }

            AnsiString.MaximumLength = CapturedString.MaximumLength;
            AnsiString.Length = 0;
            AnsiString.Buffer = AnsiStringBuffer;

            //
            // Transform the string to ANSI until the HAL handles unicode.
            //

            RtlUnicodeStringToOemString(
                &AnsiString,
                &CapturedString,
                FALSE
                );

        } else {

            //
            // Allocate a string buffer for the ansi string.
            //

            AnsiStringBuffer = ExAllocatePoolWithTag(NonPagedPool,
                                                     String->MaximumLength,
                                                     'grtS');


            if (AnsiStringBuffer == NULL) {
                return STATUS_NO_MEMORY;
            }

            AnsiString.MaximumLength = String->MaximumLength;
            AnsiString.Length = 0;
            AnsiString.Buffer = AnsiStringBuffer;

            //
            // We were in kernel mode; just transform the original string.
            //

            RtlUnicodeStringToOemString(
                &AnsiString,
                String,
                FALSE
                );
        }

        HalDisplayString( AnsiString.Buffer );

        //
        // Free up the memory we used to store the strings.
        //

        if (PreviousMode != KernelMode) {
            ExFreePool(StringBuffer);
        }

        ExFreePool(AnsiStringBuffer);

    } except(EXCEPTION_EXECUTE_HANDLER) {
        if (StringBuffer != NULL) {
            ExFreePool(StringBuffer);
        }

        return GetExceptionCode();
    }

    return STATUS_SUCCESS;
}
コード例 #3
0
ファイル: fsctl.c プロジェクト: reactos/reactos
__drv_mustHoldCriticalRegion
NTSTATUS
RfsdInvalidateVolumes ( IN PRFSD_IRP_CONTEXT IrpContext )
{
    NTSTATUS            Status;
    PIRP                Irp;
    PIO_STACK_LOCATION  IrpSp;

    HANDLE              Handle;

    PLIST_ENTRY         ListEntry;

    PFILE_OBJECT        FileObject;
    PDEVICE_OBJECT      DeviceObject;
    BOOLEAN             GlobalResourceAcquired = FALSE;

    LUID Privilege = {SE_TCB_PRIVILEGE, 0};

    _SEH2_TRY {

        Irp   = IrpContext->Irp;
        IrpSp = IoGetCurrentIrpStackLocation(Irp);

        if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) {
            Status = STATUS_PRIVILEGE_NOT_HELD;
            _SEH2_LEAVE;
        }

        if (
#ifndef _GNU_NTIFS_
            IrpSp->Parameters.FileSystemControl.InputBufferLength
#else
            ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))->
            Parameters.FileSystemControl.InputBufferLength
#endif
            != sizeof(HANDLE)) {

            Status = STATUS_INVALID_PARAMETER;

            _SEH2_LEAVE;
        }

        Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;

        Status = ObReferenceObjectByHandle( Handle,
        0,
        *IoFileObjectType,
        KernelMode,
        (void **)&FileObject,
        NULL );

        if (!NT_SUCCESS(Status)) {
            _SEH2_LEAVE;
        } else {
            ObDereferenceObject(FileObject);
            DeviceObject = FileObject->DeviceObject;
        }

        RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: FileObject=%xh ...\n", FileObject));

        ExAcquireResourceExclusiveLite(
            &RfsdGlobal->Resource,
            TRUE );

        GlobalResourceAcquired = TRUE;

        ListEntry = RfsdGlobal->VcbList.Flink;

        while (ListEntry != &RfsdGlobal->VcbList)  {

            PRFSD_VCB Vcb;

            Vcb = CONTAINING_RECORD(ListEntry, RFSD_VCB, Next);

            ListEntry = ListEntry->Flink;

            RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb));
            if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject))
            {
                ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
                RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: RfsdPurgeVolume...\n"));
                RfsdPurgeVolume(Vcb, FALSE);
                ClearFlag(Vcb->Flags, VCB_MOUNTED);
                ExReleaseResourceLite(&Vcb->MainResource);

                //
                // Vcb is still attached on the list ......
                //

                if (ListEntry->Blink == &Vcb->Next)
                {
                    RfsdPrint((DBG_INFO, "RfsdInvalidateVolumes: RfsdCheckDismount...\n"));
                    RfsdCheckDismount(IrpContext, Vcb, FALSE);
                }
            }
        }

    } _SEH2_FINALLY {

        if (GlobalResourceAcquired) {
            ExReleaseResourceForThreadLite(
                &RfsdGlobal->Resource,
                ExGetCurrentResourceThread() );
        }

        RfsdCompleteIrpContext(IrpContext, Status);
    } _SEH2_END;

    return Status;
}
コード例 #4
0
ファイル: exinit.c プロジェクト: chunhualiu/OpenNT
NTSTATUS
NtShutdownSystem(
    IN SHUTDOWN_ACTION Action
    )

/*++

Routine Description:

    This service is used to safely shutdown the system.

    N.B. The caller must have SeShutdownPrivilege to shut down the
        system.

Arguments:

    Action - Supplies an action that is to be taken after having shutdown.

Return Value:

    !NT_SUCCESS - The operation failed or the caller did not have appropriate
        priviledges.

--*/

{

    POWER_ACTION        SystemAction;
    KPROCESSOR_MODE     PreviousMode;
    NTSTATUS            Status;

    //
    // Convert shutdown action to system action
    //
    
    switch (Action) {
        case ShutdownNoReboot:  SystemAction = PowerActionShutdown;         break;
        case ShutdownReboot:    SystemAction = PowerActionShutdownReset;    break;
        case ShutdownPowerOff:  SystemAction = PowerActionShutdownOff;      break;
        default:                return STATUS_INVALID_PARAMETER;
    }

    //
    // Check to determine if the caller has the privilege to shutdown the
    // system.
    //

    PreviousMode = KeGetPreviousMode();
    if (PreviousMode != KernelMode) {

        //
        // Check to see if the caller has the privilege to make this
        // call.
        //

        if (!SeSinglePrivilegeCheck( SeShutdownPrivilege, PreviousMode )) {
            return STATUS_PRIVILEGE_NOT_HELD;
        }

        return ZwShutdownSystem(Action);
    } else {
        MmLockPagableCodeSection((PVOID)MmShutdownSystem);
    }

    //
    //  Prevent further hard error popups.
    //

    ExpTooLateForErrors = TRUE;

    //
    // Invoke each component of the executive that needs to be notified
    // that a shutdown is about to take place.
    //
    
    ExShutdownSystem();
    IoShutdownSystem(0);
    CmShutdownSystem();
    MmShutdownSystem();
    IoShutdownSystem(1);
    
    //
    // If the system is to be rebooted or powered off, then perform the
    // final operations.
    //

    if (Action != ShutdownNoReboot) {
        DbgUnLoadImageSymbols( NULL, (PVOID)-1, 0 );
        if (Action == ShutdownReboot) {
            HalReturnToFirmware( HalRebootRoutine );

        } else {
            HalReturnToFirmware( HalPowerDownRoutine );
        }
    }
    
    //
    // Bypass policy manager and pass directly to SetSystemPowerState
    //

    Status = NtSetSystemPowerState (
                SystemAction,
                PowerSystemSleeping3,
                POWER_ACTION_OVERRIDE_APPS | POWER_ACTION_DISABLE_WAKES | POWER_ACTION_CRITICAL
                );

    return STATUS_SUCCESS;
}
コード例 #5
0
ファイル: dbgctrl.c プロジェクト: chunhualiu/OpenNT
NTSTATUS
NtSystemDebugControl (
    IN SYSDBG_COMMAND Command,
    IN PVOID InputBuffer,
    IN ULONG InputBufferLength,
    OUT PVOID OutputBuffer,
    IN ULONG OutputBufferLength,
    OUT PULONG ReturnLength OPTIONAL
    )

/*++

Routine Description:

    This function controls the system debugger.

Arguments:

    Command - The command to be executed.  One of the following:

        SysDbgQueryTraceInformation
        SysDbgSetTracepoint
        SysDbgSetSpecialCall
        SysDbgClearSpecialCalls
        SysDbgQuerySpecialCalls

    InputBuffer - A pointer to a buffer describing the input data for
        the request, if any.  The structure of this buffer varies
        depending upon Command.

    InputBufferLength - The length in bytes of InputBuffer.

    OutputBuffer - A pointer to a buffer that is to receive the output
        data for the request, if any.  The structure of this buffer
        varies depending upon Command.

    OutputBufferLength - The length in bytes of OutputBuffer.

    ReturnLength - A optional pointer to a ULONG that is to receive the
        output data length for the request.

Return Value:

    Returns one of the following status codes:

        STATUS_SUCCESS - normal, successful completion.

        STATUS_INVALID_INFO_CLASS - The Command parameter did not
            specify a valid value.

        STATUS_INFO_LENGTH_MISMATCH - The value of the Length field in the
            Parameters buffer was not correct.

        STATUS_ACCESS_VIOLATION - Either the Parameters buffer pointer
            or a pointer within the Parameters buffer specified an
            invalid address.

        STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
            for this request to complete.

--*/

{
    NTSTATUS status = STATUS_SUCCESS;
    BOOLEAN releaseModuleResoure = FALSE;
    ULONG length = 0;
    KPROCESSOR_MODE PreviousMode;

    PreviousMode = KeGetPreviousMode();

    if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode)) {
        return STATUS_ACCESS_DENIED;
    }

    //
    // Operate within a try block in order to catch errors.
    //

    try {

        //
        // Probe input and output buffers, if previous mode is not
        // kernel.
        //

        if ( PreviousMode != KernelMode ) {

            if ( InputBufferLength != 0 ) {
                ProbeForRead( InputBuffer, InputBufferLength, sizeof(ULONG) );
            }

            if ( OutputBufferLength != 0 ) {
                ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(ULONG) );
            }

            if ( ARGUMENT_PRESENT(ReturnLength) ) {
                ProbeForWriteUlong( ReturnLength );
            }
        }

        //
        // Switch on the command code.
        //

        switch ( Command ) {

#ifdef _X86_

        case SysDbgQueryTraceInformation:

            status = KdGetTraceInformation(
                        OutputBuffer,
                        OutputBufferLength,
                        &length
                        );

            break;

        case SysDbgSetTracepoint:

            if ( InputBufferLength != sizeof(DBGKD_MANIPULATE_STATE64) ) {
                return STATUS_INFO_LENGTH_MISMATCH;
            }

            KdSetInternalBreakpoint( InputBuffer );

            break;

        case SysDbgSetSpecialCall:

            if ( InputBufferLength != sizeof(PVOID) ) {
                return STATUS_INFO_LENGTH_MISMATCH;
            }

            KdSetSpecialCall( InputBuffer, NULL );

            break;

        case SysDbgClearSpecialCalls:

            KdClearSpecialCalls( );

            break;

        case SysDbgQuerySpecialCalls:

            status = KdQuerySpecialCalls(
                        OutputBuffer,
                        OutputBufferLength,
                        &length
                        );

            break;

#endif

        case SysDbgBreakPoint:
            if (KdDebuggerEnabled) {
                DbgBreakPointWithStatus(DBG_STATUS_DEBUG_CONTROL);
            } else {
                status = STATUS_UNSUCCESSFUL;
            }
            break;

        default:

            //
            // Invalid Command.
            //

            status = STATUS_INVALID_INFO_CLASS;
        }

        if ( ARGUMENT_PRESENT(ReturnLength) ) {
            *ReturnLength = length;
        }
    }

    except ( EXCEPTION_EXECUTE_HANDLER ) {

        if ( releaseModuleResoure ) {
            ExReleaseResource( &PsLoadedModuleResource );
            KeLeaveCriticalRegion();
        }

        status = GetExceptionCode();

    }

    return status;

} // NtSystemDebugControl
コード例 #6
0
ファイル: loadunld.c プロジェクト: BillTheBest/WinNT4
NTSTATUS
NtLoadDriver(
    IN PUNICODE_STRING DriverServiceName
    )

/*++

Routine Description:

    This service dynamically loads a device or file system driver into
    the currently running system.  It requires that the caller have the
    appropriate privilege to execute this service.

Arguments:

    DriverServiceName - Specifies the name of the node in the registry
        associated with the driver to be loaded.

Return Value:

    The status returned is the final completion status of the load operation.

--*/

{
    KPROCESSOR_MODE requestorMode;
    UNICODE_STRING driverServiceName;
    PWCHAR nameBuffer = (PWCHAR) NULL;
    LOAD_PACKET loadPacket;

    PAGED_CODE();

    //
    // Get the previous mode;  i.e., the mode of the caller.
    //

    requestorMode = KeGetPreviousMode();

    if (requestorMode != KernelMode) {

        //
        // The caller's access mode is not kernel so check to ensure that
        // the caller has the privilege to load a driver and probe and
        // capture the name of the driver service entry.
        //

        if (!SeSinglePrivilegeCheck( SeLoadDriverPrivilege, requestorMode )) {
            return STATUS_PRIVILEGE_NOT_HELD;
        }

        //
        // The caller has the appropriate privilege to load and unload
        // drivers, so capture the driver service name string so that it
        // can be used to locate the driver from the registry node.
        //

        try {

            driverServiceName = ProbeAndReadUnicodeString( DriverServiceName );

            if (!driverServiceName.Length) {
                return STATUS_INVALID_PARAMETER;
            }

            ProbeForRead( driverServiceName.Buffer,
                          driverServiceName.Length,
                          sizeof( WCHAR ) );

            nameBuffer = ExAllocatePoolWithQuota( PagedPool,
                                                  driverServiceName.Length );

            RtlCopyMemory( nameBuffer,
                           driverServiceName.Buffer,
                           driverServiceName.Length );

            driverServiceName.Buffer = nameBuffer;

        } except(EXCEPTION_EXECUTE_HANDLER) {

            //
            // An exception was incurred while attempting to capture the
            // input name string or while attempting to allocate the name
            // string buffer.  Simply clean everything up and return an
            // appropriate error status code.
            //

            if (nameBuffer) {
                ExFreePool( nameBuffer );
            }
            return GetExceptionCode();
        }
    } else {
コード例 #7
0
ファイル: subject.c プロジェクト: hackerwang/OSexperiment
BOOLEAN
SepValidOwnerSubjectContext(
    IN PSECURITY_SUBJECT_CONTEXT SubjectContext,
    IN PSID Owner,
    IN BOOLEAN ServerObject
)
/*++

Routine Description:

    This routine checks to see whether the provided SID is one the subject
    is authorized to assign as the owner of objects.  It will also check to
    see if the caller has SeRestorePrivilege, if so, the request is granted.

Arguments:

    SubjectContext - Points to the subject's security context.

    Owner - Points to the SID to be checked.



Return Value:

    none.

--*/

{

    ULONG Index;
    BOOLEAN Found;
    PTOKEN EffectiveToken;
    BOOLEAN Rc = FALSE;

    PAGED_CODE();

    //
    // It is invalid to assign a NULL owner, regardless of
    // whether you have SeRestorePrivilege or not.
    //

    if (Owner == NULL) {
        return( FALSE );
    }

    //
    // Allowable owners come from the primary if it's a server object.
    //

    if (!ServerObject && ARGUMENT_PRESENT(SubjectContext->ClientToken)) {
        EffectiveToken = (PTOKEN)SubjectContext->ClientToken;
    } else {
        EffectiveToken = (PTOKEN)SubjectContext->PrimaryToken;
    }


    //
    // If we're impersonating, make sure we're at TokenImpersonation
    // or above.  This prevents someone from setting the owner of an
    // object when impersonating at less Identify or Anonymous.
    //

    if (EffectiveToken->TokenType == TokenImpersonation) {

        if (EffectiveToken->ImpersonationLevel < SecurityImpersonation) {

            return( FALSE );

        }
    }

    Index = 0;

    SepAcquireTokenReadLock( EffectiveToken );

    //
    //  Walk through the list of user and group IDs looking
    //  for a match to the specified SID.  If one is found,
    //  make sure it may be assigned as an owner.
    //
    //  This code is similar to that performed to set the default
    //  owner of a token (NtSetInformationToken).
    //

    while (Index < EffectiveToken->UserAndGroupCount) {


        Found = RtlEqualSid(
                    Owner,
                    EffectiveToken->UserAndGroups[Index].Sid
                );

        if ( Found ) {

            //
            // We may return success if the Sid is one that may be assigned
            // as an owner, or if the caller has SeRestorePrivilege
            //

            if ( SepIdAssignableAsOwner(EffectiveToken,Index) ) {

                SepReleaseTokenReadLock( EffectiveToken );
                Rc = TRUE;
                goto exit;

            } else {

                //
                // Rc is already set to FALSE, just exit.
                //

                SepReleaseTokenReadLock( EffectiveToken );
                goto exit;

            } //endif assignable


        }  //endif Found


        Index += 1;

    } //endwhile


    SepReleaseTokenReadLock( EffectiveToken );

exit:

    //
    // If we are going to fail this call, check for Restore privilege,
    // and succeed if he has it.
    //

    //
    // We should really have gotten PreviousMode from the caller, but we
    // didn't, so hard wire it to be user-mode here.
    //

    if ( Rc == FALSE ) {
        Rc = SeSinglePrivilegeCheck( SeRestorePrivilege, UserMode );
    }

    return Rc;
}
コード例 #8
0
NTSTATUS
NTAPI
PspSetPrimaryToken(IN PEPROCESS Process,
                   IN HANDLE TokenHandle OPTIONAL,
                   IN PACCESS_TOKEN Token OPTIONAL)
{
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    BOOLEAN IsChild;
    PACCESS_TOKEN NewToken = Token;
    NTSTATUS Status, AccessStatus;
    BOOLEAN Result, SdAllocated;
    PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
    SECURITY_SUBJECT_CONTEXT SubjectContext;
    PSTRACE(PS_SECURITY_DEBUG, "Process: %p Token: %p\n", Process, Token);

    /* Make sure we got a handle */
    if (TokenHandle)
    {
        /* Reference it */
        Status = ObReferenceObjectByHandle(TokenHandle,
                                           TOKEN_ASSIGN_PRIMARY,
                                           SeTokenObjectType,
                                           PreviousMode,
                                           (PVOID*)&NewToken,
                                           NULL);
        if (!NT_SUCCESS(Status)) return Status;
    }

    /* Check if this is a child */
    Status = SeIsTokenChild(NewToken, &IsChild);
    if (!NT_SUCCESS(Status))
    {
        /* Failed, dereference */
        if (TokenHandle) ObDereferenceObject(NewToken);
        return Status;
    }

    /* Check if this was an independent token */
    if (!IsChild)
    {
        /* Make sure we have the privilege to assign a new one */
        if (!SeSinglePrivilegeCheck(SeAssignPrimaryTokenPrivilege,
                                    PreviousMode))
        {
            /* Failed, dereference */
            if (TokenHandle) ObDereferenceObject(NewToken);
            return STATUS_PRIVILEGE_NOT_HELD;
        }
    }

    /* Assign the token */
    Status = PspAssignPrimaryToken(Process, NULL, NewToken);
    if (NT_SUCCESS(Status))
    {
        /*
         * We need to completely reverify if the process still has access to
         * itself under this new token.
         */
        Status = ObGetObjectSecurity(Process,
                                     &SecurityDescriptor,
                                     &SdAllocated);
        if (NT_SUCCESS(Status))
        {
            /* Setup the security context */
            SubjectContext.ProcessAuditId = Process;
            SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);
            SubjectContext.ClientToken = NULL;

            /* Do the access check */
            Result = SeAccessCheck(SecurityDescriptor,
                                   &SubjectContext,
                                   FALSE,
                                   MAXIMUM_ALLOWED,
                                   0,
                                   NULL,
                                   &PsProcessType->TypeInfo.GenericMapping,
                                   PreviousMode,
                                   &Process->GrantedAccess,
                                   &AccessStatus);

            /* Dereference the token and let go the SD */
            ObFastDereferenceObject(&Process->Token,
                                    SubjectContext.PrimaryToken);
            ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);

            /* Remove access if it failed */
            if (!Result) Process->GrantedAccess = 0;

            /* Setup granted access */
            Process->GrantedAccess |= (PROCESS_VM_OPERATION |
                                       PROCESS_VM_READ |
                                       PROCESS_VM_WRITE |
                                       PROCESS_QUERY_INFORMATION |
                                       PROCESS_TERMINATE |
                                       PROCESS_CREATE_THREAD |
                                       PROCESS_DUP_HANDLE |
                                       PROCESS_CREATE_PROCESS |
                                       PROCESS_SET_INFORMATION |
                                       STANDARD_RIGHTS_ALL |
                                       PROCESS_SET_QUOTA);
        }
    }

    /* Dereference the token */
    if (TokenHandle) ObDereferenceObject(NewToken);
    return Status;
}