SUPDrv-win.cpp revision 9c3f9ad981f048b8343f47ec6155a91f6b740624
c6ade8a5a12fad69394e7223b7ea170bd729f0f4vboxsync * VBoxDrv - The VirtualBox Support Driver - Windows NT specifics.
c6ade8a5a12fad69394e7223b7ea170bd729f0f4vboxsync * Copyright (C) 2006-2012 Oracle Corporation
c6ade8a5a12fad69394e7223b7ea170bd729f0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c6ade8a5a12fad69394e7223b7ea170bd729f0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * you can redistribute it and/or modify it under the terms of the GNU
c6ade8a5a12fad69394e7223b7ea170bd729f0f4vboxsync * General Public License (GPL) as published by the Free Software
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
c6ade8a5a12fad69394e7223b7ea170bd729f0f4vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * The contents of this file may alternatively be used under the terms
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * of the Common Development and Distribution License Version 1.0
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * VirtualBox OSE distribution, in which case the provisions of the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * CDDL are applicable instead of those of the GPL.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * You may elect to license modified versions of this file under the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * terms and conditions of either the GPL or the CDDL or both.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/*******************************************************************************
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync* Header Files *
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync*******************************************************************************/
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/*******************************************************************************
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync* Defined Constants And Macros *
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync*******************************************************************************/
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** The support service name. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** The Pool tag (VBox). */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** NT device name for system access. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** NT device name for user access. */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync/** NT device name for hardened stub access. */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync# define DEVICE_NAME_NT_STUB L"\\Device\\VBoxDrvStub"
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync/** Macro for checking for deflecting calls to the stub device. */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync# define VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(a_pDevObj, a_pIrp) \
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync do { if ((a_pDevObj) == g_pDevObjStub) supdrvNtCompleteRequest(STATUS_ACCESS_DENIED, a_pIrp); } while (0)
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync# define VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(a_pDevObj, a_pIrp) do {} while (0)
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync/** Enables the fast I/O control code path. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/*******************************************************************************
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync* Structures and Typedefs *
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync*******************************************************************************/
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Device extension used by VBoxDrvU.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Global cookie (same location as in SUPDRVDEVEXT, different value). */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Pointer to the main driver extension. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncAssertCompileMembersAtSameOffset(SUPDRVDEVEXT, u32Cookie, SUPDRVDEVEXTUSR, u32Cookie);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to the VBoxDrvU device extension. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Value of SUPDRVDEVEXTUSR::u32Cookie. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Get the main device extension. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync : ((PSUPDRVDEVEXTUSR)pDevObj->DeviceExtension)->pMainDrvExt )
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync * Device extension used by VBoxDrvS.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Common header. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to the VBoxDrvS device extension. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Value of SUPDRVDEVEXTSTUB::Common.u32Cookie. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#define SUPDRVDEVEXTSTUB_COOKIE UINT32_C(0x90abcdef)
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * The kind of process we're protecting.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Stub process protection while performing process verification.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Next: StubSpawning (or free) */
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync /** Stub process protection before it creates the VM process.
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync * Next: StubParent, StubDead. */
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync /** Stub process protection while having a VM process as child.
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync * Next: StubDead */
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync /** Dead stub process. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Potential VM process.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Next: VmProcessConfirmed, VmProcessDead. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Confirmed VM process.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Next: VmProcessDead. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Dead VM process. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** End of valid protection kinds. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * A NT process protection structure.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** The AVL node core structure. The process ID is the pid. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Magic value (SUPDRVNTPROTECT_MAGIC). */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Reference counter. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** The kind of process we're protecting. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Vista, 7 & 8: Hack to allow more rights to the handle returned by
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** Vista, 7 & 8: Hack to allow more rights to the handle returned by
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** 8.1: Hack to allow more rights to the handle returned by
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * NtCreateUserProcess. Only applicable to VmProcessUnconfirmed. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** Vista, 7 & 8: Hack to allow more rights to the handle duplicated by CSR
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * during process creation. Only applicable to VmProcessUnconfirmed. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** 7,: Hack to allow the supid themes service duplicate handle privileges to
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * our process. */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync /** The parent PID for VM processes, otherwise NULL. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** The PID of the CSRSS process associated with this process. */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync /** Pointer to the CSRSS process structure (referenced). */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync /** State dependent data. */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync /** A stub process in the StubParent state will keep a reference to a child
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * while it's in the VmProcessUnconfirmed state so that it can be cleaned up
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * correctly if things doesn't work out. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /** A process in the VmProcessUnconfirmed state will keep a weak
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * reference to the parent's protection structure so it can clean up the pChild
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * refernece the parent has to it. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to a NT process protection record. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The SUPDRVNTPROTECT::u32Magic value (Robert A. Heinlein). */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** The SUPDRVNTPROTECT::u32Magic value of a dead structure. */
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync# define SUPDRVNTPROTECT_MAGIC_DEAD UINT32_C(0x19880508)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to ObGetObjectType. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef POBJECT_TYPE (NTAPI *PFNOBGETOBJECTTYPE)(PVOID);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to ObRegisterCallbacks. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef NTSTATUS (NTAPI *PFNOBREGISTERCALLBACKS)(POB_CALLBACK_REGISTRATION, PVOID *);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to ObUnregisterCallbacks. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef VOID (NTAPI *PFNOBUNREGISTERCALLBACKS)(PVOID);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to PsSetCreateProcessNotifyRoutineEx. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef NTSTATUS (NTAPI *PFNPSSETCREATEPROCESSNOTIFYROUTINEEX)(PCREATE_PROCESS_NOTIFY_ROUTINE_EX, BOOLEAN);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to PsReferenceProcessFilePointer. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef NTSTATUS (NTAPI *PFNPSREFERENCEPROCESSFILEPOINTER)(PEPROCESS, PFILE_OBJECT *);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to PsIsProtectedProcessLight. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef BOOLEAN (NTAPI *PFNPSISPROTECTEDPROCESSLIGHT)(PEPROCESS);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** Pointer to ZwAlpcCreatePort. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsynctypedef NTSTATUS (NTAPI *PFNZWALPCCREATEPORT)(PHANDLE, POBJECT_ATTRIBUTES, struct _ALPC_PORT_ATTRIBUTES *);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync#endif /* VBOX_WITH_HARDENINIG */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/*******************************************************************************
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync* Internal Functions *
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync*******************************************************************************/
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void _stdcall VBoxDrvNtUnload(PDRIVER_OBJECT pDrvObj);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtCleanup(PDEVICE_OBJECT pDevObj, PIRP pIrp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic BOOLEAN _stdcall VBoxDrvNtFastIoDeviceControl(PFILE_OBJECT pFileObj, BOOLEAN fWait, PVOID pvInput, ULONG cbInput,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PIO_STATUS_BLOCK pIoStatus, PDEVICE_OBJECT pDevObj);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic int VBoxDrvNtDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtInternalDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic VOID _stdcall VBoxPowerDispatchCallback(PVOID pCallbackContext, PVOID pArgument1, PVOID pArgument2);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic NTSTATUS _stdcall VBoxDrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic void supdrvNtProtectTerm(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic int supdrvNtProtectCreate(PSUPDRVNTPROTECT *ppNtProtect, HANDLE hPid,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic void supdrvNtProtectRelease(PSUPDRVNTPROTECT pNtProtect);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic PSUPDRVNTPROTECT supdrvNtProtectLookup(HANDLE hPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic int supdrvNtProtectFindAssociatedCsrss(PSUPDRVNTPROTECT pNtProtect);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic int supdrvNtProtectVerifyProcess(PSUPDRVNTPROTECT pNtProtect);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic bool supdrvNtIsDebuggerAttached(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/*******************************************************************************
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync* Exported Functions *
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync*******************************************************************************/
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/*******************************************************************************
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync* Global Variables *
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync*******************************************************************************/
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to the system device instance. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to the user device instance. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Fast I/O dispatch table. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic FAST_IO_DISPATCH const g_VBoxDrvFastIoDispatch =
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* .SizeOfFastIoDispatch = */ sizeof(g_VBoxDrvFastIoDispatch),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* .FastIoDeviceControl = */ VBoxDrvNtFastIoDeviceControl,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#endif /* VBOXDRV_WITH_FAST_IO */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to the stub device instance. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Spinlock protecting g_NtProtectTree as well as the releasing of protection
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * structures. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic RTSPINLOCK g_hNtProtectLock = NIL_RTSPINLOCK;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** AVL tree of SUPDRVNTPROTECT structures. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Cookie returned by ObRegisterCallbacks for the callbacks. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Combined windows NT version number. See SUP_MAKE_NT_VER_COMBINED. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to ObGetObjectType if available.. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic PFNOBGETOBJECTTYPE g_pfnObGetObjectType = NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to ObRegisterCallbacks if available.. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic PFNOBREGISTERCALLBACKS g_pfnObRegisterCallbacks = NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to ObUnregisterCallbacks if available.. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic PFNOBUNREGISTERCALLBACKS g_pfnObUnRegisterCallbacks = NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to PsSetCreateProcessNotifyRoutineEx if available.. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic PFNPSSETCREATEPROCESSNOTIFYROUTINEEX g_pfnPsSetCreateProcessNotifyRoutineEx = NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to PsReferenceProcessFilePointer if available. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic PFNPSREFERENCEPROCESSFILEPOINTER g_pfnPsReferenceProcessFilePointer = NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to PsIsProtectedProcessLight. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic PFNPSISPROTECTEDPROCESSLIGHT g_pfnPsIsProtectedProcessLight = NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to ZwAlpcCreatePort. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic PFNZWALPCCREATEPORT g_pfnZwAlpcCreatePort = NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncextern "C" {
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to KiServiceLinkage (used to fake missing ZwQueryVirtualMemory on
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * XP64 / W2K3-64). */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Pointer to KiServiceInternal (used to fake missing ZwQueryVirtualMemory on
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * XP64 / W2K3-64) */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** The primary ALPC port object type. (LpcPortObjectType at init time.) */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** The secondary ALPC port object type. (Sampled at runtime.) */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic POBJECT_TYPE volatile g_pAlpcPortObjectType2 = NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Takes care of creating the devices and their symbolic links.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns NT status code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDrvObj Pointer to driver object.
de8636fc8bdeb02161ee5b329c407dd0c48b0885vboxsyncstatic NTSTATUS vboxdrvNtCreateDevices(PDRIVER_OBJECT pDrvObj)
de8636fc8bdeb02161ee5b329c407dd0c48b0885vboxsync * System device.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&DevName, DEVICE_NAME_NT_SYS);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync NTSTATUS rcNt = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXT), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDevObjSys);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * User device.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&DevName, DEVICE_NAME_NT_USR);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rcNt = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXTUSR), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDevObjUsr);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXTUSR pDevExtUsr = (PSUPDRVDEVEXTUSR)g_pDevObjUsr->DeviceExtension;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pDevExtUsr->pMainDrvExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Hardened stub device.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&DevName, DEVICE_NAME_NT_STUB);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rcNt = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXTSTUB), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDevObjStub);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXTSTUB pDevExtStub = (PSUPDRVDEVEXTSTUB)g_pDevObjStub->DeviceExtension;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pDevExtStub->Common.pMainDrvExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pDevExtStub->Common.u32Cookie = SUPDRVDEVEXTSTUB_COOKIE;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Done. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Bail out. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Destroys the devices and links created by vboxdrvNtCreateDevices.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic void vboxdrvNtDestroyDevices(void)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXTUSR pDevExtUsr = (PSUPDRVDEVEXTUSR)g_pDevObjUsr->DeviceExtension;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXTSTUB pDevExtStub = (PSUPDRVDEVEXTSTUB)g_pDevObjStub->DeviceExtension;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Driver entry point.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns appropriate status code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDrvObj Pointer to driver object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pRegPath Registry base path.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Sanity checks.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (g_VBoxDrvFastIoDispatch.FastIoDeviceControl != VBoxDrvNtFastIoDeviceControl)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync DbgPrint("VBoxDrv: FastIoDeviceControl=%p instead of %p\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync g_VBoxDrvFastIoDispatch.FastIoDeviceControl, VBoxDrvNtFastIoDeviceControl);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Initialize the runtime (IPRT).
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Initialize process protection.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Create device.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * (That means creating a device object and a symbolic link so the DOS
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * subsystems (OS/2, win32, ++) can access the device.)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Initialize the device extension.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync vrc = supdrvInitDevExt(pDevExt, sizeof(SUPDRVSESSION));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Setup the driver entry points in pDrvObj.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxDrvNtCreate;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDrvObj->MajorFunction[IRP_MJ_CLEANUP] = VBoxDrvNtCleanup;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxDrvNtClose;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxDrvNtDeviceControl;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VBoxDrvNtInternalDeviceControl;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDrvObj->MajorFunction[IRP_MJ_READ] = VBoxDrvNtNotSupportedStub;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDrvObj->MajorFunction[IRP_MJ_WRITE] = VBoxDrvNtNotSupportedStub;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Fast I/O to speed up guest execution roundtrips. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pDrvObj->FastIoDispatch = (PFAST_IO_DISPATCH)&g_VBoxDrvFastIoDispatch;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Register ourselves for power state changes. We don't
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * currently care if this fails.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState");
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync InitializeObjectAttributes(&Attr, &CallbackName, OBJ_CASE_INSENSITIVE, NULL, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rcNt = ExCreateCallback(&pDevExt->pObjPowerCallback, &Attr, TRUE, TRUE);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pDevExt->hPowerCallback = ExRegisterCallback(pDevExt->pObjPowerCallback,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Done! Returning success!
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n"));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("supdrvInitDevExit failed with vrc=%d!\n", vrc));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Unload the driver.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDrvObj Driver object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncvoid _stdcall VBoxDrvNtUnload(PDRIVER_OBJECT pDrvObj)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtUnload at irql %d\n", KeGetCurrentIrql()));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Clean up the power callback registration. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * We ASSUME that it's not possible to unload a driver with open handles.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * For simplifying request completion into a simple return statement, extended
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns rcNt
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param rcNt The status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param uInfo Extra info value.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIrp The IRP.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLINLINE(NTSTATUS) supdrvNtCompleteRequestEx(NTSTATUS rcNt, ULONG_PTR uInfo, PIRP pIrp)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * For simplifying request completion into a simple return statement.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns rcNt
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param rcNt The status code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIrp The IRP.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLINLINE(NTSTATUS) supdrvNtCompleteRequest(NTSTATUS rcNt, PIRP pIrp)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequestEx(rcNt, 0 /*uInfo*/, pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Create (i.e. Open) file entry point.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevObj Device object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIrp Request packet.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncNTSTATUS _stdcall VBoxDrvNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtCreate: RequestorMode=%d\n", pIrp->RequestorMode));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PSUPDRVDEVEXT pDevExt = SUPDRVNT_GET_DEVEXT(pDevObj);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * We are not remotely similar to a directory...
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * (But this is possible.)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequest(STATUS_NOT_A_DIRECTORY, pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Don't create a session for kernel clients, they'll close the handle
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * immediately and work with the file object via
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * VBoxDrvNtInternalDeviceControl. The first request will be one to
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * create a session.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#if defined(VBOX_WITH_HARDENING) && !defined(VBOX_WITHOUT_DEBUGGER_CHECKS)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Make sure no debuggers are attached to non-user processes.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: Process %p is being debugged, access to vboxdrv / vboxdrvu declined.\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Access to the stub device is only granted to processes which
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * passes verification.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Note! The stub device has no need for a SUPDRVSESSION structure,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * so the it uses the SUPDRVNTPROTECT directly instead.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvNtProtectCreate(&pNtProtect, PsGetProcessId(PsGetCurrentProcess()),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync kSupDrvNtProtectKind_StubUnverified, true /*fLink*/);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvNtProtectFindAssociatedCsrss(pNtProtect);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pFileObj->FsContext = pNtProtect; /* Keeps reference. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: Declined %p access to VBoxDrvStub: rc=%d\n", PsGetProcessId(PsGetCurrentProcess()), rc));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Unrestricted access is only granted to a process in the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * VmProcessUnconfirmed state that checks out correctly and is
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * allowed to transition to VmProcessConfirmed. Again, only one
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * session per process.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtProtect = supdrvNtProtectLookup(PsGetProcessId(PsGetCurrentProcess()));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Create a session. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvCreateSession(pDevExt, true /*fUser*/, pDevObj == g_pDevObjSys /*fUnrestricted*/,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pSession->pNtProtect = pNtProtect; /* Keeps reference. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* No second attempt. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessConfirmed)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtProtect->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: supdrvCreateSession failed for process %p: rc=%d.\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: Process %p failed process verification: rc=%d.\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: %p is not a budding VM process (enmProcessKind=%d).\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessId(PsGetCurrentProcess()), pNtProtect->enmProcessKind));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: %p is not a budding VM process.\n", PsGetProcessId(PsGetCurrentProcess())));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Call common code to create an unprivileged session.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvCreateSession(pDevExt, true /*fUser*/, false /*fUnrestricted*/, &pSession);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync pFileObj->FsContext = pSession; /* Keeps reference. No race. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync#else /* !VBOX_WITH_HARDENING */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * Call common code to create a session.
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync rc = supdrvCreateSession(pDevExt, true /*fUser*/, pDevObj == g_pDevObjSys /*fUnrestricted*/, &pSession);
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL);
326ffe46af8b56e4a0b9648193c1c0681104f127vboxsync return supdrvNtCompleteRequestEx(STATUS_SUCCESS, FILE_OPENED, pIrp);
326ffe46af8b56e4a0b9648193c1c0681104f127vboxsync#endif /* !VBOX_WITH_HARDENING */
326ffe46af8b56e4a0b9648193c1c0681104f127vboxsync /* bail out */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequest(rcNt, pIrp); /* Note. the IoStatus is completely ignored on error. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Clean up file handle entry point.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevObj Device object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIrp Request packet.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncNTSTATUS _stdcall VBoxDrvNtCleanup(PDEVICE_OBJECT pDevObj, PIRP pIrp)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXT pDevExt = SUPDRVNT_GET_DEVEXT(pDevObj);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtProtect = (PSUPDRVNTPROTECT)pFileObj->FsContext;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtCleanup: pDevExt=%p pFileObj=%p pNtProtect=%p\n", pDevExt, pFileObj, pNtProtect));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVSESSION pSession = supdrvSessionHashTabLookup(pDevExt, RTProcSelf(), RTR0ProcHandleSelf(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtCleanup: pDevExt=%p pFileObj=%p pSession=%p\n", pDevExt, pFileObj, pSession));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvSessionHashTabRemove(pDevExt, pSession, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvSessionRelease(pSession); /* Drops the reference from supdrvSessionHashTabLookup. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequest(STATUS_SUCCESS, pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Close file entry point.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevObj Device object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIrp Request packet.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncNTSTATUS _stdcall VBoxDrvNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXT pDevExt = SUPDRVNT_GET_DEVEXT(pDevObj);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtProtect = (PSUPDRVNTPROTECT)pFileObj->FsContext;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtClose: pDevExt=%p pFileObj=%p pNtProtect=%p\n", pDevExt, pFileObj, pNtProtect));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVSESSION pSession = supdrvSessionHashTabLookup(pDevExt, RTProcSelf(), RTR0ProcHandleSelf(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtCleanup: pDevExt=%p pFileObj=%p pSession=%p\n", pDevExt, pFileObj, pSession));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvSessionHashTabRemove(pDevExt, pSession, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvSessionRelease(pSession); /* Drops the reference from supdrvSessionHashTabLookup. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequest(STATUS_SUCCESS, pIrp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Fast I/O device control callback.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * This performs no buffering, neither on the way in or out.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns TRUE if handled, FALSE if the normal I/O control routine should be
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pFileObj The file object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param fWait Whether it's a blocking call
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pvInput The input buffer as specified by the user.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param cbInput The size of the input buffer.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pvOutput The output buffer as specfied by the user.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param cbOutput The size of the output buffer.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param uFunction The function.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIoStatus Where to return the status of the operation.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevObj The device object..
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic BOOLEAN _stdcall VBoxDrvNtFastIoDeviceControl(PFILE_OBJECT pFileObj, BOOLEAN fWait, PVOID pvInput, ULONG cbInput,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PIO_STATUS_BLOCK pIoStatus, PDEVICE_OBJECT pDevObj)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXT pDevExt = SUPDRVNT_GET_DEVEXT(pDevObj);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Check the input a little bit and get a the session references.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVSESSION pSession = supdrvSessionHashTabLookup(pDevExt, RTProcSelf(), RTR0ProcHandleSelf(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#if defined(VBOX_WITH_HARDENING) && !defined(VBOX_WITHOUT_DEBUGGER_CHECKS)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Deal with the 2-3 high-speed IOCtl that takes their arguments from
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * the session and iCmd, and does not return anything.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync int rc = supdrvIOCtlFast(uCmd, (unsigned)(uintptr_t)pvOutput/* VMCPU id */, pDevExt, pSession);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pIoStatus->Status = RT_SUCCESS(rc) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pIoStatus->Information = 0; /* Could be used to pass rc if we liked. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * The normal path.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync unsigned cbOut = 0;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log2(("VBoxDrvNtFastIoDeviceControl(%p): ioctl=%#x pvIn=%p cbIn=%#x pvOut=%p cbOut=%#x pSession=%p\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pDevExt, uCmd, pvInput, cbInput, pvOutput, cbOutput, pSession));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Don't allow 32-bit processes to do any I/O controls. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * In this fast I/O device control path we have to do our own buffering.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Verify that the I/O control function matches our pattern. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Get the header so we can validate it a little bit against the
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync parameters before allocating any memory kernel for the reqest. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (cbInput >= sizeof(Hdr) && cbOutput >= sizeof(Hdr))
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync /* Verify that the sizes in the request header are correct. */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync /* Allocate a buffer and copy all the input into it. */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync PSUPREQHDR pHdr = (PSUPREQHDR)ExAllocatePoolWithTag(NonPagedPool, cbBuf, 'VBox');
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlZeroMemory((uint8_t *)pHdr + cbInput, cbBuf - cbInput);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Now call the common code to do the real work.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvIOCtl(uCmd, pDevExt, pSession, pHdr, cbBuf);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Copy back the result.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync OSDBGPRINT(("VBoxDrvNtFastIoDeviceControl: too much output! %#x > %#x; uCmd=%#x!\n",
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log2(("VBoxDrvNtFastIoDeviceControl: returns %#x cbOut=%d rc=%#x\n", rcNt, cbOut, rc));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Log(("VBoxDrvNtFastIoDeviceControl: Mismatching sizes (%#x) - Hdr=%#lx/%#lx Irp=%#lx/%#lx!\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtFastIoDeviceControl: not buffered request (%#x) - not supported\n", uCmd));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtFastIoDeviceControl: WOW64 req - not supported\n"));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* complete the request. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#endif /* VBOXDRV_WITH_FAST_IO */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Device I/O Control entry point.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevObj Device object.
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync * @param pIrp Request packet.
0802b726efeabba46f90cb2b285de4dadaac9507vboxsyncNTSTATUS _stdcall VBoxDrvNtDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(pDevObj, pIrp);
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync PSUPDRVDEVEXT pDevExt = SUPDRVNT_GET_DEVEXT(pDevObj);
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVSESSION pSession = supdrvSessionHashTabLookup(pDevExt, RTProcSelf(), RTR0ProcHandleSelf(),
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync return supdrvNtCompleteRequest(STATUS_TRUST_FAILURE, pIrp);
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync * Deal with the 2-3 high-speed IOCtl that takes their arguments from
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * the session and iCmd, and does not return anything.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#if defined(VBOX_WITH_HARDENING) && !defined(VBOX_WITHOUT_DEBUGGER_CHECKS)
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync return supdrvNtCompleteRequest(STATUS_TRUST_FAILURE, pIrp);
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync ULONG ulCmd = pStack->Parameters.DeviceIoControl.IoControlCode;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync int rc = supdrvIOCtlFast(ulCmd, (unsigned)(uintptr_t)pIrp->UserBuffer /* VMCPU id */, pDevExt, pSession);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Complete the I/O request. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return supdrvNtCompleteRequest(RT_SUCCESS(rc) ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER, pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return VBoxDrvNtDeviceControlSlow(pDevExt, pSession, pIrp, pStack);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Worker for VBoxDrvNtDeviceControl that takes the slow IOCtl functions.
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync * @returns NT status code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevObj Device object.
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync * @param pSession The session.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIrp Request packet.
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync * @param pStack The stack location containing the DeviceControl parameters.
0802b726efeabba46f90cb2b285de4dadaac9507vboxsyncstatic int VBoxDrvNtDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync unsigned cbOut = 0;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log2(("VBoxDrvNtDeviceControlSlow(%p,%p): ioctl=%#x pBuf=%p cbIn=%#x cbOut=%#x pSession=%p\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pDevExt, pIrp, pStack->Parameters.DeviceIoControl.IoControlCode,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pIrp->AssociatedIrp.SystemBuffer, pStack->Parameters.DeviceIoControl.InputBufferLength,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength, pSession));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Don't allow 32-bit processes to do any I/O controls. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Verify that it's a buffered CTL. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ((pStack->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Verify that the sizes in the request header are correct. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPREQHDR pHdr = (PSUPREQHDR)pIrp->AssociatedIrp.SystemBuffer;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pStack->Parameters.DeviceIoControl.InputBufferLength == pHdr->cbIn
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pStack->Parameters.DeviceIoControl.OutputBufferLength == pHdr->cbOut)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Zero extra output bytes to make sure we don't leak anything. */
cb39011e69667689c166f1cdf95247b46fff324dvboxsync RtlZeroMemory((uint8_t *)pHdr + pHdr->cbIn, pHdr->cbOut - pHdr->cbIn);
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * Do the job.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvIOCtl(pStack->Parameters.DeviceIoControl.IoControlCode, pDevExt, pSession, pHdr,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (cbOut > pStack->Parameters.DeviceIoControl.OutputBufferLength)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync OSDBGPRINT(("VBoxDrvLinuxIOCtl: too much output! %#x > %#x; uCmd=%#x!\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pHdr->cbOut, cbOut, pStack->Parameters.DeviceIoControl.IoControlCode));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log2(("VBoxDrvNtDeviceControlSlow: returns %#x cbOut=%d rc=%#x\n", rcNt, cbOut, rc));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtDeviceControlSlow: Mismatching sizes (%#x) - Hdr=%#lx/%#lx Irp=%#lx/%#lx!\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr) ? pHdr->cbIn : 0,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr) ? pHdr->cbOut : 0,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.InputBufferLength,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtDeviceControlSlow: not buffered request (%#x) - not supported\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.IoControlCode));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtDeviceControlSlow: WOW64 req - not supported\n"));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* complete the request. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Internal Device I/O Control entry point, used for IDC.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevObj Device object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIrp Request packet.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncNTSTATUS _stdcall VBoxDrvNtInternalDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync VBOXDRV_COMPLETE_IRP_AND_RETURN_IF_STUB_DEV(pDevObj, pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXT pDevExt = SUPDRVNT_GET_DEVEXT(pDevObj);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PFILE_OBJECT pFileObj = pStack ? pStack->FileObject : NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVSESSION pSession = pFileObj ? (PSUPDRVSESSION)pFileObj->FsContext : NULL;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync unsigned cbOut = 0;
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync Log2(("VBoxDrvNtInternalDeviceControl(%p,%p): ioctl=%#x pBuf=%p cbIn=%#x cbOut=%#x pSession=%p\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pDevExt, pIrp, pStack->Parameters.DeviceIoControl.IoControlCode,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pIrp->AssociatedIrp.SystemBuffer, pStack->Parameters.DeviceIoControl.InputBufferLength,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength, pSession));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Verify that it's a buffered CTL. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ((pStack->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Verify the pDevExt in the session. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( pStack->Parameters.DeviceIoControl.IoControlCode != SUPDRV_IDC_REQ_CONNECT
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync ? VALID_PTR(pSession) && pSession->pDevExt == pDevExt
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Verify that the size in the request header is correct. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVIDCREQHDR pHdr = (PSUPDRVIDCREQHDR)pIrp->AssociatedIrp.SystemBuffer;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pStack->Parameters.DeviceIoControl.InputBufferLength == pHdr->cb
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pStack->Parameters.DeviceIoControl.OutputBufferLength == pHdr->cb)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Call the generic code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Note! Connect and disconnect requires some extra attention
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * in order to get the session handling right.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pStack->Parameters.DeviceIoControl.IoControlCode == SUPDRV_IDC_REQ_DISCONNECT)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvIDC(pStack->Parameters.DeviceIoControl.IoControlCode, pDevExt, pSession, pHdr);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pStack->Parameters.DeviceIoControl.IoControlCode == SUPDRV_IDC_REQ_CONNECT)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pFileObj->FsContext = ((PSUPDRVIDCREQCONNECT)pHdr)->u.Out.pSession;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pStack->Parameters.DeviceIoControl.IoControlCode == SUPDRV_IDC_REQ_DISCONNECT)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log2(("VBoxDrvNtInternalDeviceControl: returns %#x/rc=%#x\n", rcNt, rc));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtInternalDeviceControl: Mismatching sizes (%#x) - Hdr=%#lx Irp=%#lx/%#lx!\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr) ? pHdr->cb : 0,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.InputBufferLength,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.OutputBufferLength));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxDrvNtInternalDeviceControl: not buffered request (%#x) - not supported\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pStack->Parameters.DeviceIoControl.IoControlCode));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* complete the request. */
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync * Stub function for functions we don't implemented.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns STATUS_NOT_SUPPORTED
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevObj Device object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pIrp IRP.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncNTSTATUS _stdcall VBoxDrvNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * ExRegisterCallback handler for power events
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pCallbackContext User supplied parameter (pDevObj)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pArgument1 First argument
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pArgument2 Second argument
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncVOID _stdcall VBoxPowerDispatchCallback(PVOID pCallbackContext, PVOID pArgument1, PVOID pArgument2)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pCallbackContext;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxPowerDispatchCallback: %x %x\n", pArgument1, pArgument2));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Power change imminent? */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ((unsigned)pArgument1 == PO_CB_SYSTEM_STATE_LOCK)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ((unsigned)pArgument2 == 0)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("VBoxPowerDispatchCallback: about to go into suspend mode!\n"));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Inform any clients that have registered themselves with IPRT. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RTPowerSignalEvent(((unsigned)pArgument2 == 0) ? RTPOWEREVENT_SUSPEND : RTPOWEREVENT_RESUME);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Called to clean up the session structure before it's freed.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pDevExt The device globals.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pSession The session that's being cleaned up.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncvoid VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncvoid VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncvoid VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Initializes any OS specific object creator fields.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncvoid VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Checks if the session can access the object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns true if a decision has been made.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns false if the default access policy should be applied.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pObj The object in question.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pSession The session wanting to access the object.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pszObjName The object name, can be NULL.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param prc Where to store the result when returning true.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncbool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Force async tsc mode (stub).
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncbool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#define MY_SystemLoadGdiDriverInSystemSpaceInformation 54
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PVOID EntryPointer; /**< Out: entry point address. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PVOID ExportSectionPointer; /**< Out: export directory/section. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncextern "C" __declspec(dllimport) NTSTATUS NTAPI ZwSetSystemInformation(ULONG, PVOID, ULONG);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncint VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync# error "VBOX_WITHOUT_NATIVE_R0_LOADER is only safe on x86."
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Convert the filename from DOS UTF-8 to NT UTF-16.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync int rc = RTStrCalcUtf16LenEx(pszFilename, RTSTR_MAX, &cwcFilename);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PRTUTF16 pwcsFilename = (PRTUTF16)RTMemTmpAlloc((4 + cwcFilename + 1) * sizeof(RTUTF16));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = RTStrToUtf16Ex(pszFilename, RTSTR_MAX, &pwcsTmp, cwcFilename + 1, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Try load it.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemLoadGdiDriverInSystemSpaceInformation, &Info, sizeof(Info));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("ImageAddress=%p SectionPointer=%p ImageLength=%#x cbImageBits=%#x rcNt=%#x '%ls'\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync SUPR0Printf("ImageAddress=%p SectionPointer=%p ImageLength=%#x cbImageBits=%#x rcNt=%#x '%ws'\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Lock down the entire image, just to be on the safe side.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = RTR0MemObjLockKernel(&pImage->hMemLock, pImage->pvImage, pImage->cbImageBits, RTMEM_PROT_READ);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync SUPR0Printf("VBoxDrv: rcNt=%x '%ws'\n", rcNt, pwcsFilename);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Unwind will crash and BSOD, so no fallback here! */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Use the old way of loading the modules.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Note! We do *NOT* try class 26 because it will probably
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * not work correctly on terminal servers and such.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case /* 0xc0000034 */ STATUS_OBJECT_NAME_NOT_FOUND:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case /* 0xC0000263 */ STATUS_DRIVER_ENTRYPOINT_NOT_FOUND:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("WARNING: see @bugref{4853} for cause of this failure on Windows 7 x64\n"));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncvoid VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncint VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * memcmp + log.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns Same as memcmp.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pImage The image.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pbImageBits The image bits ring-3 uploads.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param uRva The RVA to start comparing at.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param cb The number of bytes to compare.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic int supdrvNtCompare(PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, uint32_t uRva, uint32_t cb)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync int iDiff = memcmp((uint8_t const *)pImage->pvImage + uRva, pbImageBits + uRva, cb);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync const uint8_t *pbNativeBits = (const uint8_t *)pImage->pvImage;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync for (size_t off = uRva; cbLeft > 0; off++, cbLeft--)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RTStrPrintf(szBytes, sizeof(szBytes), "native: %.*Rhxs our: %.*Rhxs",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync SUPR0Printf("VBoxDrv: Mismatch at %#x of %s: %s\n", off, pImage->szName, szBytes);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncint VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Usually, the entire image matches exactly.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (!memcmp(pImage->pvImage, pbImageBits, pImage->cbImageBits))
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * However, on Windows Server 2003 (sp2 x86) both import thunk tables
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * are fixed up and we typically get a mismatch in the INIT section.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * So, lets see if everything matches when excluding the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * OriginalFirstThunk tables. To make life simpler, set the max number
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * of imports to 16 and just record and sort the locations that needs
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * to be excluded from the comparison.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync + ( *(uint16_t *)pbImageBits == IMAGE_DOS_SIGNATURE
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync ? ((IMAGE_DOS_HEADER const *)pbImageBits)->e_lfanew
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtHdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtHdrs->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size >= sizeof(IMAGE_IMPORT_DESCRIPTOR)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress > sizeof(IMAGE_NT_HEADERS)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress < pImage->cbImageBits
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync unsigned cExcludeRgns = 0;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync uint32_t cImpsLeft = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pImp = (IMAGE_IMPORT_DESCRIPTOR const *)(pbImageBits
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync + pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync while ( cImpsLeft-- > 0
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && uRvaThunk <= pImage->cbImageBits - sizeof(IMAGE_THUNK_DATA)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Find the size of the thunk table. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync IMAGE_THUNK_DATA const *paThunk = (IMAGE_THUNK_DATA const *)(pbImageBits + uRvaThunk);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync uint32_t cMaxThunks = (pImage->cbImageBits - uRvaThunk) / sizeof(IMAGE_THUNK_DATA);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync while (cThunks < cMaxThunks && paThunk[cThunks].u1.Function != 0)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Ordered table insert. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync unsigned i = 0;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync for (; i < cExcludeRgns; i++)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync memmove(&aExcludeRgns[i + 1], &aExcludeRgns[i], (cExcludeRgns - i) * sizeof(aExcludeRgns[0]));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync aExcludeRgns[i].cb = cThunks * sizeof(IMAGE_THUNK_DATA);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* advance */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Ok, do the comparison.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync for (unsigned i = 0; !iDiff && i < cExcludeRgns; i++)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync iDiff = supdrvNtCompare(pImage, pbImageBits, uRvaNext, aExcludeRgns[i].uRva - uRvaNext);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync uRvaNext = aExcludeRgns[i].uRva + aExcludeRgns[i].cb;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync iDiff = supdrvNtCompare(pImage, pbImageBits, uRvaNext, pImage->cbImageBits - uRvaNext);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvNtCompare(pImage, pbImageBits, 0, pImage->cbImageBits);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncvoid VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RTR0MemObjFree(pImage->hMemLock, false /*fFreeMappings*/);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemUnloadGdiDriverInformation,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync &pImage->pvNtSectionObj, sizeof(pImage->pvNtSectionObj));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync SUPR0Printf("VBoxDrv: failed to unload '%s', rcNt=%#x\n", pImage->szName, rcNt);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** @todo make this selectable. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Argument package used by supdrvOSMsrProberRead and supdrvOSMsrProberWrite.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** @callback_method_impl{FNRTMPWORKER, Worker for supdrvOSMsrProberRead.} */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic DECLCALLBACK(void) supdrvNtMsProberReadOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * rdmsr and wrmsr faults can be caught even with interrupts disabled.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * (At least on 32-bit XP.)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync SUPDRVNTMSPROBERARGS *pArgs = (SUPDRVNTMSPROBERARGS *)pvUser1; NOREF(idCpu); NOREF(pvUser2);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pArgs->uValue = ASMRdMsrEx(pArgs->uMsr, AMD_MSR_PASSCODE);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncint VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync int rc = RTMpOnSpecific(idCpu, supdrvNtMsProberReadOnCpu, &Args, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** @callback_method_impl{FNRTMPWORKER, Worker for supdrvOSMsrProberWrite.} */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic DECLCALLBACK(void) supdrvNtMsProberWriteOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * rdmsr and wrmsr faults can be caught even with interrupts disabled.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * (At least on 32-bit XP.)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync SUPDRVNTMSPROBERARGS *pArgs = (SUPDRVNTMSPROBERARGS *)pvUser1; NOREF(idCpu); NOREF(pvUser2);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync ASMWrMsrEx(pArgs->uMsr, AMD_MSR_PASSCODE, pArgs->uValue);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncint VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync int rc = RTMpOnSpecific(idCpu, supdrvNtMsProberReadOnCpu, &Args, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** @callback_method_impl{FNRTMPWORKER, Worker for supdrvOSMsrProberModify.} */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic DECLCALLBACK(void) supdrvNtMsProberModifyOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync bool const fFaster = pReq->u.In.enmOp == SUPMSRPROBEROP_MODIFY_FASTER;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync bool fAfterGp = true;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Do the job.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Modify. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Read modified value. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Restore original value. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Invalid everything we can. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Write out the results.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pReq->u.Out.uResults.Modify.fRestoreGp = fRestoreGp;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncint VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return RTMpOnSpecific(idCpu, supdrvNtMsProberModifyOnCpu, pReq, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#endif /* SUPDRV_WITH_MSR_PROBER */
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * Converts an IPRT error code to an nt status code.
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * @returns corresponding nt status code.
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * @param rc IPRT error status code.
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case VERR_GENERAL_FAILURE: return STATUS_NOT_SUPPORTED;
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case VERR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case VERR_INVALID_MAGIC: return STATUS_UNKNOWN_REVISION;
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case VERR_INVALID_HANDLE: return STATUS_INVALID_HANDLE;
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case VERR_INVALID_POINTER: return STATUS_INVALID_ADDRESS;
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case VERR_ALREADY_LOADED: return STATUS_IMAGE_ALREADY_LOADED;
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case VERR_PERMISSION_DENIED: return STATUS_ACCESS_DENIED;
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case VERR_VERSION_MISMATCH: return STATUS_REVISION_MISMATCH;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync if (((uint32_t)rc & UINT32_C(0xffff0000)) == UINT32_C(0xffff0000))
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return (NTSTATUS)( ((uint32_t)rc & UINT32_C(0xffff)) | SUP_NT_STATUS_BASE );
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync#if 0 /* See alternative in SUPDrvA-win.asm */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Alternative version of SUPR0Printf for Windows.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * @returns 0.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * @param pszFormat The format string.
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsyncSUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync size_t cch = RTStrPrintfV(szMsg, sizeof(szMsg) - 1, pszFormat, va);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Returns configuration flags of the host kernel.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** @name Identifying Special Processes: CSRSS.EXE
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Checks if the process is a system32 process by the given name.
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync * @returns true / false.
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync * @param pProcess The process to check.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * @param pszName The lower case process name (no path!).
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsyncstatic bool supdrvNtProtectIsSystem32ProcessMatch(PEPROCESS pProcess, const char *pszName)
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync Assert(strlen(pszName) < 16); /* see buffer below */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * This test works on XP+.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync const char *pszImageFile = (const char *)PsGetProcessImageFileName(pProcess);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return false;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * This test requires a Vista+ API.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync NTSTATUS rcNt = g_pfnPsReferenceProcessFilePointer(pProcess, &pFile);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync uint8_t abBuffer[sizeof(g_System32NtPath) + 16 * sizeof(WCHAR)];
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync rcNt = ObQueryNameString(pFile, &Buf.Info, sizeof(Buf) - sizeof(WCHAR), &cbIgn);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync /* Terminate the name. */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync pwszName[Buf.Info.Name.Length / sizeof(RTUTF16)] = '\0';
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync /* Match the name against the system32 directory path. */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync uint32_t cbSystem32 = g_System32NtPath.UniStr.Length;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync if (memcmp(pwszName, g_System32NtPath.UniStr.Buffer, cbSystem32))
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync return false;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync /* Compare the name. */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return true;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Checks if the current process is likely to be CSRSS.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pProcess The process.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsyncstatic bool supdrvNtProtectIsCsrssByProcess(PEPROCESS pProcess)
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * On Windows 8.1 CSRSS.EXE is a protected process.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * The name tests.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync if (!supdrvNtProtectIsSystem32ProcessMatch(pProcess, "csrss.exe"))
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync /** @todo Could extend the CSRSS.EXE check with that the TokenUser of the
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * current process must be "NT AUTHORITY\SYSTEM" (S-1-5-18). */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return true;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic bool supdrvNtProtectGetAlpcPortObjectType2(PCRTUTF16 pwszPortNm, POBJECT_TYPE *ppObjType)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync bool fDone = false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync UniStrPortNm.Length = (USHORT)(RTUtf16Len(pwszPortNm) * sizeof(WCHAR));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync UniStrPortNm.MaximumLength = UniStrPortNm.Length + sizeof(WCHAR);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync InitializeObjectAttributes(&ObjAttr, &UniStrPortNm, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync NTSTATUS rcNt = g_pfnZwAlpcCreatePort(&hPort, &ObjAttr, NULL /*pPortAttribs*/);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync rcNt = ObReferenceObjectByHandle(hPort, 0 /*DesiredAccess*/, NULL /*pObjectType*/,
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync POBJECT_TYPE pObjType = g_pfnObGetObjectType(pvObject);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync SUPR0Printf("vboxdrv: ALPC Port Object Type %p (vs %p)\n", pObjType, *ppObjType);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic POBJECT_TYPE supdrvNtProtectGetAlpcPortObjectType(uint32_t uSessionId, const char *pszSessionId)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * First attempt is in the session directory.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = RTUtf16CopyAscii(wszPortNm, RT_ELEMENTS(wszPortNm), "\\Sessions\\");
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), pszSessionId);
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), "\\VBoxDrv-");
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync cchTmp = RTStrFormatU32(szTmp, sizeof(szTmp), (uint32_t)(uintptr_t)PsGetProcessId(PsGetCurrentProcess()), 16, 0, 0, 0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), szTmp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), "-");
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cchTmp = RTStrFormatU32(szTmp, sizeof(szTmp), RTRandU32(), 16, 0, 0, 0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), szTmp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool fDone = supdrvNtProtectGetAlpcPortObjectType2(wszPortNm, &pObjType);
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync cchTmp = RTStrFormatU32(szTmp, sizeof(szTmp), RTRandU32(), 16, 0, 0, 0); Assert(cchTmp > 0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), szTmp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync fDone = supdrvNtProtectGetAlpcPortObjectType2(wszPortNm, &pObjType);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Try base names.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = RTUtf16CopyAscii(wszPortNm, RT_ELEMENTS(wszPortNm), "\\BaseNamedObjects\\VBoxDrv-");
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = RTUtf16CopyAscii(wszPortNm, RT_ELEMENTS(wszPortNm), "\\Sessions\\");
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), pszSessionId);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), "\\BaseNamedObjects\\VBoxDrv-");
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cchTmp = RTStrFormatU32(szTmp, sizeof(szTmp), (uint32_t)(uintptr_t)PsGetProcessId(PsGetCurrentProcess()), 16, 0, 0, 0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), szTmp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), "-");
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync cchTmp = RTStrFormatU32(szTmp, sizeof(szTmp), RTRandU32(), 16, 0, 0, 0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), szTmp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool fDone = supdrvNtProtectGetAlpcPortObjectType2(wszPortNm, &pObjType);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync cchTmp = RTStrFormatU32(szTmp, sizeof(szTmp), RTRandU32(), 16, 0, 0, 0);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc |= RTUtf16CatAscii(wszPortNm, RT_ELEMENTS(wszPortNm), szTmp);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync fDone = supdrvNtProtectGetAlpcPortObjectType2(wszPortNm, &pObjType);
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync /* Cache the result in g_pAlpcPortObjectType2. */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Called in the context of VBoxDrvNtCreate to determin the CSRSS for the
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * current process.
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * The Client/Server Runtime Subsystem (CSRSS) process needs to be allowed some
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * additional access right so we need to make 101% sure we correctly identify
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * the CSRSS process a process is associated with.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns IPRT status code.
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync * @param pNtProtect The NT protected process structure. The
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync * hCsrssPid member will be updated on success.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsyncstatic int supdrvNtProtectFindAssociatedCsrss(PSUPDRVNTPROTECT pNtProtect)
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync Assert(pNtProtect->AvlCore.Key == PsGetCurrentProcessId());
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * We'll try use the ApiPort LPC object for the session we're in to track
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * down the CSRSS process. So, we start by constructing a path to it.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync uint32_t uSessionId = PsGetProcessSessionId(PsGetCurrentProcess());
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync rc = RTUtf16CopyAscii(wszApiPort, RT_ELEMENTS(wszApiPort), "\\Windows\\ApiPort");
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync ssize_t cchTmp = RTStrFormatU32(szSessionId, sizeof(szSessionId), uSessionId, 10, 0, 0, 0);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync rc = RTUtf16CopyAscii(wszApiPort, RT_ELEMENTS(wszApiPort), "\\Sessions\\");
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync rc = RTUtf16CatAscii(wszApiPort, RT_ELEMENTS(wszApiPort), szSessionId);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync rc = RTUtf16CatAscii(wszApiPort, RT_ELEMENTS(wszApiPort), "\\Windows\\ApiPort");
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync ApiPortStr.Length = (USHORT)(RTUtf16Len(wszApiPort) * sizeof(RTUTF16));
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync ApiPortStr.MaximumLength = ApiPortStr.Length + sizeof(RTUTF16);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * The object cannot be opened, but we can reference it by name.
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync NTSTATUS rcNt = ObReferenceObjectByName(&ApiPortStr,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync supdrvNtProtectGetAlpcPortObjectType(uSessionId, szSessionId),
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync SUPR0Printf("vboxdrv: Error opening '%ls': %#x\n", wszApiPort, rcNt);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return rcNt == STATUS_OBJECT_TYPE_MISMATCH ? VERR_SUPDRV_APIPORT_OPEN_ERROR_TYPE : VERR_SUPDRV_APIPORT_OPEN_ERROR;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Query the processes in the system so we can locate CSRSS.EXE candidates.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Note! Attempts at using SystemSessionProcessInformation failed with
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * STATUS_ACCESS_VIOLATION.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Note! The 32 bytes on the size of to counteract the allocation header
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync * that rtR0MemAllocEx slaps on everything.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync#if 0 /* doesn't work. */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync rcNt = NtQuerySystemInformation(SystemSessionProcessInformation, &Req, sizeof(Req), &cbNeeded);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync rcNt = NtQuerySystemInformation(SystemProcessInformation, pbBuf, cbBuf, &cbNeeded);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Walk the returned data and look for the process associated with the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * ApiPort object. The ApiPort object keeps the EPROCESS address of
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * the owner process (i.e. CSRSS) relatively early in the structure. On
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * 64-bit windows 8.1 it's at offset 0x18. So, obtain the EPROCESS
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * pointer to likely CSRSS processes and check for a match in the first
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * 0x40 bytes of the ApiPort object.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync for (uint32_t offBuf = 0; offBuf <= cbNeeded - sizeof(SYSTEM_PROCESS_INFORMATION);)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PRTNT_SYSTEM_PROCESS_INFORMATION pProcInfo = (PRTNT_SYSTEM_PROCESS_INFORMATION)&pbBuf[offBuf];
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( pProcInfo->ProcessName.Length == 9 * sizeof(WCHAR)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pProcInfo->NumberOfThreads > 2 /* Very low guess. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pProcInfo->HandleCount > 32 /* Very low guess, I hope. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && (uintptr_t)pProcInfo->ProcessName.Buffer - (uintptr_t)pbBuf < cbNeeded
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[0]) == 'c'
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[1]) == 's'
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[2]) == 'r'
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[3]) == 's'
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[4]) == 's'
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[6]) == 'e'
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[7]) == 'x'
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && RT_C_TO_LOWER(pProcInfo->ProcessName.Buffer[8]) == 'e' )
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync /* Get the process structure and perform some more thorough
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync process checks. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rcNt = PsLookupProcessByProcessId(pProcInfo->UniqueProcessId, &pProcess);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Final test, check the ApiPort.
c6ade8a5a12fad69394e7223b7ea170bd729f0f4vboxsync Note! The old LPC (pre Vista) objects has the PID
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync much earlier in the structure. Might be
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync worth looking for it instead. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync bool fThatsIt = false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync uint32_t cTests = g_uNtVerCombined >= SUP_NT_VER_VISTA ? 16 : 38; /* ALPC since Vista. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Ok, we found it! Keep the process structure
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync reference as well as the PID so we can
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync safely identify it later on. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pNtProtect->hCsrssPid = pProcInfo->UniqueProcessId;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Advance. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Checks that the given process is the CSRSS process associated with protected
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns true / false.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pNtProtect The NT protection structure.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pCsrss The process structure of the alleged CSRSS.EXE
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic bool supdrvNtProtectIsAssociatedCsrss(PSUPDRVNTPROTECT pNtProtect, PEPROCESS pCsrss)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pNtProtect->hCsrssPid == PsGetProcessId(pCsrss))
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return true;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Checks if the given process is the stupid themes service.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * The caller does some screening of access masks and what not. We do the rest.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns true / false.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pNtProtect The NT protection structure.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * @param pAnnoyingProcess The process structure of an process that might
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * happen to be the annoying themes process.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic bool supdrvNtProtectIsFrigginThemesService(PSUPDRVNTPROTECT pNtProtect, PEPROCESS pAnnoyingProcess)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Check the process name.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (!supdrvNtProtectIsSystem32ProcessMatch(pAnnoyingProcess, "svchost.exe"))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** @todo Come up with more checks. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return true;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Checks if the given process is one of the whitelisted debuggers.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns true / false.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pProcess The process to check.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsyncstatic bool supdrvNtProtectIsWhitelistedDebugger(PEPROCESS pProcess)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync const char *pszImageFile = (const char *)PsGetProcessImageFileName(pProcess);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pszImageFile[0] == 'w' || pszImageFile[0] == 'W')
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return true;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return true;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (RTStrICmp(pszImageFile, "werfaultsecure.exe") == 0)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return true;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync else if (pszImageFile[0] == 'd' || pszImageFile[0] == 'D')
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync return true;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return true;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync return false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync#endif /* VBOX_WITHOUT_DEBUGGER_CHECKS */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync/** @name Process Creation Callbacks.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Common worker used by the process creation hooks as well as the process
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * handle creation hooks to check if a VM process is being created.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns true if likely to be a VM process, false if not.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pNtStub The NT protection structure for the possible
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * stub process.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param hParentPid The parent pid.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param hChildPid The child pid.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic bool supdrvNtProtectIsSpawningStubProcess(PSUPDRVNTPROTECT pNtStub, HANDLE hParentPid, HANDLE hChildPid)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool fRc = false;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pNtStub->AvlCore.Key == hParentPid) /* paranoia */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pNtStub->enmProcessKind == kSupDrvNtProtectKind_StubSpawning)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Compare short names. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync NTSTATUS rcNt = PsLookupProcessByProcessId(hParentPid, &pStubProcess);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rcNt = PsLookupProcessByProcessId(hChildPid, &pChildProcess);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync const char *pszStub = (const char *)PsGetProcessImageFileName(pStubProcess);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync const char *pszChild = (const char *)PsGetProcessImageFileName(pChildProcess);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /** @todo check that the full image names matches. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Common code used by the notifies to protect a child process.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @returns VBox status code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pNtStub The NT protect structure for the parent.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param hChildPid The child pid.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic int supdrvNtProtectProtectNewStubChild(PSUPDRVNTPROTECT pNtParent, HANDLE hChildPid)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Create a child protection struction.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync int rc = supdrvNtProtectCreate(&pNtChild, hChildPid, kSupDrvNtProtectKind_VmProcessUnconfirmed, false /*fLink*/);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtChild->fCsrssFirstProcessDuplicateHandle = true;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtChild->pCsrssProcess = pNtParent->pCsrssProcess;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Take the spinlock, recheck parent conditions and link things.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pNtParent->enmProcessKind == kSupDrvNtProtectKind_StubSpawning)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync bool fSuccess = RTAvlPVInsert(&g_NtProtectTree, &pNtChild->AvlCore);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtParent->u.pChild = pNtChild; /* Parent keeps the initial reference. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtParent->enmProcessKind = kSupDrvNtProtectKind_StubParent;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Common process termination code.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Transitions protected process to the dead states, protecting against handle
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * PID reuse (esp. with unconfirmed VM processes) and handle cleanup issues.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * @param hDeadPid The PID of the dead process.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic void supdrvNtProtectUnprotectDeadProcess(HANDLE hDeadPid)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtProtect = supdrvNtProtectLookup(hDeadPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * If this is an unconfirmed VM process, we must release the reference
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * the parent structure holds.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtParent = pNtProtect->u.pParent;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync AssertRelease(pNtParent); AssertRelease(pNtParent->u.pChild == pNtProtect);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * If this is a stub exitting before the VM process gets confirmed,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * release the protection of the potential VM process as this is not
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * the prescribed behavior.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync else if ( pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubParent
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtChild->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Transition it to the dead state to prevent it from opening the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * support driver again or be posthumously abused as a vm process parent.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync || pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessConfirmed)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtProtect->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if ( pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubParent
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync || pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubSpawning
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync || pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubUnverified)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtProtect->enmProcessKind = kSupDrvNtProtectKind_StubDead;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Do session cleanups.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync AssertReturnVoid((HANDLE)(uintptr_t)RTProcSelf() == hDeadPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVSESSION pSession = supdrvSessionHashTabLookup(pDevExt, (RTPROCESS)(uintptr_t)hDeadPid,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvSessionHashTabRemove(pDevExt, pSession, NULL);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvSessionRelease(pSession); /* Drops the reference from supdrvSessionHashTabLookup. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Common worker for the process creation callback that verifies a new child
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * being created by the handle creation callback code.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pNtStub The parent.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param pNtVm The child.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @param fCallerChecks The result of any additional tests the caller made.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * This is in order to avoid duplicating the failure
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * path code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic void supdrvNtProtectVerifyNewChildProtection(PSUPDRVNTPROTECT pNtStub, PSUPDRVNTPROTECT pNtVm, bool fCallerChecks)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtStub->enmProcessKind == kSupDrvNtProtectKind_StubParent
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtVm->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync /* Fine, reset the CSRSS hack (fixes ViRobot APT Shield 2.0 issue). */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: Misdetected vm stub; hParentPid=%p hChildPid=%p\n", pNtStub->AvlCore.Key, pNtVm->AvlCore.Key));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pNtStub->enmProcessKind != kSupDrvNtProtectKind_VmProcessConfirmed)
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync supdrvNtProtectUnprotectDeadProcess(pNtVm->AvlCore.Key);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Old style callback (since forever).
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync * @param hParentPid The parent PID.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param hNewPid The PID of the new child.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param fCreated TRUE if it's a creation notification,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * FALSE if termination.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @remarks ASSUMES this arrives before the handle creation callback.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsyncsupdrvNtProtectCallback_ProcessCreateNotify(HANDLE hParentPid, HANDLE hNewPid, BOOLEAN fCreated)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Is it a new process that needs protection?
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync PSUPDRVNTPROTECT pNtStub = supdrvNtProtectLookup(hParentPid);
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync PSUPDRVNTPROTECT pNtVm = supdrvNtProtectLookup(hNewPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (supdrvNtProtectIsSpawningStubProcess(pNtStub, hParentPid, hNewPid))
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvNtProtectProtectNewStubChild(pNtStub, hNewPid);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync supdrvNtProtectVerifyNewChildProtection(pNtStub, pNtVm, true);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Process termination, do clean ups.
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * New style callback (Vista SP1+ / w2k8).
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pNewProcess The new process.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param hNewPid The PID of the new process.
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync * @param pInfo Process creation details. NULL if process
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * termination notification.
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync * @remarks ASSUMES this arrives before the handle creation callback.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncsupdrvNtProtectCallback_ProcessCreateNotifyEx(PEPROCESS pNewProcess, HANDLE hNewPid, PPS_CREATE_NOTIFY_INFO pInfo)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Is it a new process that needs protection?
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtStub = supdrvNtProtectLookup(pInfo->CreatingThreadId.UniqueProcess);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("vboxdrv/NewProcessEx: ctx=%04zx/%p pid=%04zx ppid=%04zx ctor=%04zx/%04zx rcNt=%#x %.*ls\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pInfo->CreatingThreadId.UniqueProcess, pInfo->CreatingThreadId.UniqueThread, pInfo->CreationStatus,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pInfo->FileOpenNameAvailable && pInfo->ImageFileName ? (size_t)pInfo->ImageFileName->Length / 2 : 0,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pInfo->FileOpenNameAvailable && pInfo->ImageFileName ? pInfo->ImageFileName->Buffer : NULL));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtVm = supdrvNtProtectLookup(hNewPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Parent must be creator. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pInfo->CreatingThreadId.UniqueProcess == pInfo->ParentProcessId)
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync if (supdrvNtProtectIsSpawningStubProcess(pNtStub, pInfo->ParentProcessId, hNewPid))
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvNtProtectProtectNewStubChild(pNtStub, hNewPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Parent must be creator (as above). */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvNtProtectVerifyNewChildProtection(pNtStub, pNtVm,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pInfo->CreatingThreadId.UniqueProcess == pInfo->ParentProcessId);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Process termination, do clean ups.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** @name Process Handle Callbacks.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Process rights that we allow for handles to stub and VM processes. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Evil process rights. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncAssertCompile((SUPDRV_NT_ALLOW_PROCESS_RIGHTS & SUPDRV_NT_EVIL_PROCESS_RIGHTS) == 0);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncsupdrvNtProtectCallback_ProcessHandlePre(PVOID pvUser, POB_PRE_OPERATION_INFORMATION pOpInfo)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync * Protected? Kludge required for NtOpenProcess calls comming in before
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * the create process hook triggers on Windows 8.1 (possibly others too).
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync HANDLE hObjPid = PsGetProcessId((PEPROCESS)pOpInfo->Object);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtProtect = supdrvNtProtectLookup(hObjPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync HANDLE hParentPid = PsGetProcessInheritedFromUniqueProcessId((PEPROCESS)pOpInfo->Object);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtStub = supdrvNtProtectLookup(hParentPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (supdrvNtProtectIsSpawningStubProcess(pNtStub, hParentPid, hObjPid))
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync supdrvNtProtectProtectNewStubChild(pNtStub, hObjPid);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync pOpInfo->CallContext = pNtProtect; /* Just for reference. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Ok, it's a protected process. Strip rights as required or possible.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync static ACCESS_MASK const s_fCsrssStupidDesires = 0x1fffff;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync ACCESS_MASK fAllowedRights = SUPDRV_NT_ALLOW_PROCESS_RIGHTS;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Don't restrict the process accessing itself. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ((PEPROCESS)pOpInfo->Object == PsGetCurrentProcess())
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("vboxdrv/ProcessHandlePre: %sctx=%04zx/%p wants %#x to %p in pid=%04zx [%d] %s\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessImageFileName(PsGetCurrentProcess()) ));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Allow debuggers full access. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync else if (supdrvNtProtectIsWhitelistedDebugger(PsGetCurrentProcess()))
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync Log(("vboxdrv/ProcessHandlePre: %sctx=%04zx/%p wants %#x to %p in pid=%04zx [%d] %s [debugger]\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessImageFileName(PsGetCurrentProcess()) ));
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync /* Special case 1 on Vista, 7 & 8:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync The CreateProcess code passes the handle over to CSRSS.EXE
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync and the code inBaseSrvCreateProcess will duplicate the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync handle with 0x1fffff as access mask. NtDuplicateObject will
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync fail this call before it ever gets down here.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Special case 2 on 8.1:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync The CreateProcess code requires additional rights for
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync something, we'll drop these in the stub code. */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync if ( pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtProtect->hParentPid == PsGetProcessId(PsGetCurrentProcess())
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync if (g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 3))
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync pOpInfo->CallContext = NULL; /* don't assert this. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Special case 3 on 8.1:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync The interaction between the CreateProcess code and CSRSS.EXE
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync has changed to the better with Windows 8.1. CSRSS.EXE no
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync longer duplicates the process (thread too) handle, but opens
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync it, thus allowing us to do our job. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && supdrvNtProtectIsAssociatedCsrss(pNtProtect, PsGetCurrentProcess()) )
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtProtect->fCsrssFirstProcessCreateHandle = false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Not needed: PROCESS_CREATE_THREAD, PROCESS_SET_SESSIONID,
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync PROCESS_CREATE_PROCESS */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync | PROCESS_DUP_HANDLE /* Needed for CreateProcess/VBoxTestOGL. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->CallContext = NULL; /* don't assert this. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Special case 4, Windows 7, Vista, possibly 8, but not 8.1:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync The Themes service requires PROCESS_DUP_HANDLE access to our
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync process or we won't get any menus and dialogs will be half
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync unreadable. This is _very_ unfortunate and more work will
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync go into making this more secure. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == 0x1478 /* 6.1.7600.16385 (win7_rtm.090713-1255) */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && supdrvNtProtectIsFrigginThemesService(pNtProtect, PsGetCurrentProcess()) )
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtProtect->fThemesFirstProcessCreateHandle = true; /* Only once! */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->CallContext = NULL; /* don't assert this. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("vboxdrv/ProcessHandlePre: %sctx=%04zx/%p wants %#x to %p/pid=%04zx [%d], allow %#x => %#x; %s [prev=%#x]\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind, fAllowedRights,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess & fAllowedRights,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessImageFileName(PsGetCurrentProcess()), ExGetPreviousMode() ));
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess &= fAllowedRights;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Don't restrict the process accessing itself. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( (PEPROCESS)pOpInfo->Object == PsGetCurrentProcess()
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess == pOpInfo->Object)
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync Log(("vboxdrv/ProcessHandlePre: ctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] %s\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessImageFileName(PsGetCurrentProcess()) ));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Special case 5 on Vista, 7 & 8:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync This is the CSRSS.EXE end of special case #1. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 3)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync == PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess == PsGetCurrentProcess()
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && supdrvNtProtectIsAssociatedCsrss(pNtProtect, PsGetCurrentProcess()) )
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pNtProtect->fCsrssFirstProcessDuplicateHandle = false;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Not needed: PROCESS_CREATE_THREAD, PROCESS_SET_SESSIONID,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PROCESS_CREATE_PROCESS, PROCESS_DUP_HANDLE */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync | PROCESS_DUP_HANDLE /* Needed for launching VBoxTestOGL. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->CallContext = NULL; /* don't assert this. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("vboxdrv/ProcessHandlePre: %sctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] %s\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessImageFileName(PsGetCurrentProcess()) ));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess &= fAllowedRights;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsyncsupdrvNtProtectCallback_ProcessHandlePost(PVOID pvUser, POB_POST_OPERATION_INFORMATION pOpInfo)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync ACCESS_MASK const fGrantedAccess = pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync ? pOpInfo->Parameters->CreateHandleInformation.GrantedAccess
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync : pOpInfo->Parameters->DuplicateHandleInformation.GrantedAccess;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync AssertReleaseMsg( !(fGrantedAccess & ~( SUPDRV_NT_ALLOW_PROCESS_RIGHTS
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync | WRITE_OWNER | WRITE_DAC /* these two might be forced upon us */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /*| PROCESS_UNKNOWN_8000 */ ) )
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync ("GrantedAccess=%#x - we allow %#x - we did not allow %#x\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync fGrantedAccess, SUPDRV_NT_ALLOW_PROCESS_RIGHTS, fGrantedAccess & ~SUPDRV_NT_ALLOW_PROCESS_RIGHTS));
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync/** @name Thread Handle Callbacks
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsyncextern "C" NTKERNELAPI PEPROCESS __stdcall IoThreadToProcess(PETHREAD);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync/** Thread rights that we allow for handles to stub and VM processes. */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync/** @todo consider THREAD_SET_LIMITED_INFORMATION & THREAD_RESUME */
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync/** Evil thread rights.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @remarks THREAD_RESUME is not included as it seems to be forced upon us by
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Windows 8.1, at least for some processes. We dont' actively
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * allow it though, just tollerate it when forced to. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /*| THREAD_RESUME - see remarks. */ \
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncAssertCompile((SUPDRV_NT_EVIL_THREAD_RIGHTS & SUPDRV_NT_ALLOWED_THREAD_RIGHTS) == 0);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsyncsupdrvNtProtectCallback_ThreadHandlePre(PVOID pvUser, POB_PRE_OPERATION_INFORMATION pOpInfo)
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PEPROCESS pProcess = IoThreadToProcess((PETHREAD)pOpInfo->Object);
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync PSUPDRVNTPROTECT pNtProtect = supdrvNtProtectLookup(PsGetProcessId(pProcess));
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync pOpInfo->CallContext = pNtProtect; /* Just for reference. */
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync static ACCESS_MASK const s_fCsrssStupidDesires = 0x1fffff;
c598affb4a1578b0e7be124835a70c4f08c5d2bdvboxsync ACCESS_MASK fAllowedRights = SUPDRV_NT_ALLOWED_THREAD_RIGHTS;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Don't restrict the process accessing its own threads. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("vboxdrv/ThreadHandlePre: %sctx=%04zx/%p wants %#x to %p in pid=%04zx [%d] self\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Allow debuggers full access. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync else if (supdrvNtProtectIsWhitelistedDebugger(PsGetCurrentProcess()))
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync Log(("vboxdrv/ThreadHandlePre: %sctx=%04zx/%p wants %#x to %p in pid=%04zx [%d] %s [debugger]\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync PsGetProcessImageFileName(PsGetCurrentProcess()) ));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Special case 1 on Vista, 7, 8:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync The CreateProcess code passes the handle over to CSRSS.EXE
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync and the code inBaseSrvCreateProcess will duplicate the
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync handle with 0x1fffff as access mask. NtDuplicateObject will
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync fail this call before it ever gets down here. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 3)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed
c049162517778158b3507c0389358a7342622b99vboxsync && pNtProtect->hParentPid == PsGetProcessId(PsGetCurrentProcess()) )
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->CallContext = NULL; /* don't assert this. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Special case 2 on 8.1, possibly also Vista, 7, 8:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync When creating a process like VBoxTestOGL from the VM process,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync CSRSS.EXE will try talk to the calling thread and, it
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync appears, impersonate it. We unfortunately need to allow
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync this or there will be no 3D support. Typical DbgPrint:
c049162517778158b3507c0389358a7342622b99vboxsync "SXS: BasepCreateActCtx() Calling csrss server failed. Status = 0xc00000a5" */
c049162517778158b3507c0389358a7342622b99vboxsync if ( g_uNtVerCombined >= SUP_MAKE_NT_VER_COMBINED(6, 0, 0, 0, 0)
c049162517778158b3507c0389358a7342622b99vboxsync && ( (enmProcessKind = pNtProtect->enmProcessKind) == kSupDrvNtProtectKind_VmProcessConfirmed
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync || enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && supdrvNtProtectIsAssociatedCsrss(pNtProtect, PsGetCurrentProcess()) )
c049162517778158b3507c0389358a7342622b99vboxsync //fAllowedRights |= THREAD_SET_LIMITED_INFORMATION; - try without this one
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->CallContext = NULL; /* don't assert this. */
c049162517778158b3507c0389358a7342622b99vboxsync Log(("vboxdrv/ThreadHandlePre: %sctx=%04zx/%p wants %#x to %p in pid=%04zx [%d], allow %#x => %#x; %s [prev=%#x]\n",
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind, fAllowedRights,
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess & fAllowedRights,
c049162517778158b3507c0389358a7342622b99vboxsync PsGetProcessImageFileName(PsGetCurrentProcess()), ExGetPreviousMode()));
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Parameters->CreateHandleInformation.DesiredAccess &= fAllowedRights;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Don't restrict the process accessing its own threads. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && (PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess == pProcess)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync Log(("vboxdrv/ThreadHandlePre: %sctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] self\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PsGetProcessImageFileName(PsGetCurrentProcess()) ));
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync /* Special case 3 on Vista, 7, 8:
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync This is the follow up to special case 1. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if ( g_uNtVerCombined >= SUP_MAKE_NT_VER_COMBINED(6, 0, 0, 0, 0)
c049162517778158b3507c0389358a7342622b99vboxsync && ( (enmProcessKind = pNtProtect->enmProcessKind) == kSupDrvNtProtectKind_VmProcessConfirmed
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync || enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess == PsGetCurrentProcess()
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && supdrvNtProtectIsAssociatedCsrss(pNtProtect, PsGetCurrentProcess()) )
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync //fAllowedRights |= THREAD_SET_LIMITED_INFORMATION; - try without this one
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->CallContext = NULL; /* don't assert this. */
c049162517778158b3507c0389358a7342622b99vboxsync Log(("vboxdrv/ThreadHandlePre: %sctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d], allow %#x => %#x; %s\n",
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Parameters->DuplicateHandleInformation.TargetProcess,
c049162517778158b3507c0389358a7342622b99vboxsync PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind, fAllowedRights,
c049162517778158b3507c0389358a7342622b99vboxsync pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess & fAllowedRights,
c049162517778158b3507c0389358a7342622b99vboxsync PsGetProcessImageFileName(PsGetCurrentProcess()) ));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess &= fAllowedRights;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncsupdrvNtProtectCallback_ThreadHandlePost(PVOID pvUser, POB_POST_OPERATION_INFORMATION pOpInfo)
c049162517778158b3507c0389358a7342622b99vboxsync Assert(pOpInfo->Operation == OB_OPERATION_HANDLE_CREATE || pOpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE);
2b114c590cf5a19f8047cd7bde9c7e5ae00aa22bvboxsync ACCESS_MASK const fGrantedAccess = pOpInfo->Parameters->CreateHandleInformation.GrantedAccess;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReleaseMsg( !(fGrantedAccess & ~( SUPDRV_NT_ALLOWED_THREAD_RIGHTS
c049162517778158b3507c0389358a7342622b99vboxsync | WRITE_OWNER | WRITE_DAC /* these two might be forced upon us */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync | THREAD_RESUME /* This seems to be force upon us too with 8.1. */
c049162517778158b3507c0389358a7342622b99vboxsync ("GrantedAccess=%#x - we allow %#x - we did not allow %#x\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync fGrantedAccess, SUPDRV_NT_ALLOWED_THREAD_RIGHTS, fGrantedAccess & ~SUPDRV_NT_ALLOWED_THREAD_RIGHTS));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Creates a new process protection structure.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns VBox status code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param ppNtProtect Where to return the pointer to the structure
c049162517778158b3507c0389358a7342622b99vboxsync * on success.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param hPid The process ID of the process to protect.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param enmProcessKind The kind of process we're protecting.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param fLink Whether to link the structure into the tree.
c049162517778158b3507c0389358a7342622b99vboxsyncstatic int supdrvNtProtectCreate(PSUPDRVNTPROTECT *ppNtProtect, HANDLE hPid, SUPDRVNTPROTECTKIND enmProcessKind, bool fLink)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync AssertReturn(g_hNtProtectLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pNtProtect = (PSUPDRVNTPROTECT)RTMemAllocZ(sizeof(*pNtProtect));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync bool fSuccess = RTAvlPVInsert(&g_NtProtectTree, &pNtProtect->AvlCore);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Duplicate entry, fail. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("supdrvNtProtectCreate: Duplicate (%#x).\n", pNtProtect->AvlCore.Key));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Releases a reference to a NT protection structure.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pNtProtect The NT protection structure.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic void supdrvNtProtectRelease(PSUPDRVNTPROTECT pNtProtect)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync AssertReturnVoid(pNtProtect->u32Magic == SUPDRVNTPROTECT_MAGIC);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync uint32_t cRefs = ASMAtomicDecU32(&pNtProtect->cRefs);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * That was the last reference. Remove it from the tree, invalidate it
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * and free the resources associated with it. Also, release any
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * child/parent references related to this protection structure.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync ASMAtomicWriteU32(&pNtProtect->u32Magic, SUPDRVNTPROTECT_MAGIC_DEAD);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PSUPDRVNTPROTECT pRemoved = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pNtProtect->AvlCore.Key);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubParent)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pChild->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync uint32_t cChildRefs = ASMAtomicIncU32(&pChild->cRefs);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pRemovedChild = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pChild->AvlCore.Key);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync AssertRelease(pNtProtect->enmProcessKind != kSupDrvNtProtectKind_VmProcessUnconfirmed);
cb39011e69667689c166f1cdf95247b46fff324dvboxsync * Looks up a PID in the NT protect tree.
cb39011e69667689c166f1cdf95247b46fff324dvboxsync * @returns Pointer to a NT protection structure (with a referenced) on success,
cb39011e69667689c166f1cdf95247b46fff324dvboxsync * NULL if not found.
cb39011e69667689c166f1cdf95247b46fff324dvboxsync * @param hPid The process ID.
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncstatic PSUPDRVNTPROTECT supdrvNtProtectLookup(HANDLE hPid)
cb39011e69667689c166f1cdf95247b46fff324dvboxsync PSUPDRVNTPROTECT pFound = (PSUPDRVNTPROTECT)RTAvlPVGet(&g_NtProtectTree, hPid);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Worker for supdrvNtProtectVerifyProcess that verifies the handles to a VM
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * process and its thread.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns VBox status code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pNtProtect The NT protect structure for getting information
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * about special processes.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncstatic int supdrvNtProtectRestrictHandlesToProcessAndThread(PSUPDRVNTPROTECT pNtProtect)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * What to protect.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync PEPROCESS pProtectedProcess = PsGetCurrentProcess();
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync HANDLE hProtectedPid = PsGetProcessId(pProtectedProcess);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync AssertReturn(pNtProtect->AvlCore.Key == hProtectedPid, VERR_INTERNAL_ERROR_5);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Take a snapshot of all the handles in the system.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Note! The 32 bytes on the size of to counteract the allocation header
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync * that rtR0MemAllocEx slaps on everything.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync NTSTATUS rcNt = NtQuerySystemInformation(SystemExtendedHandleInformation, pbBuf, cbBuf, &cbNeeded);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rcNt = NtQuerySystemInformation(SystemExtendedHandleInformation, pbBuf, cbBuf, &cbNeeded);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Walk the information and look for handles to the two objects we're protecting.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SYSTEM_HANDLE_INFORMATION_EX const *pInfo = (SYSTEM_HANDLE_INFORMATION_EX const *)pbBuf;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertRelease(RT_OFFSETOF(SYSTEM_HANDLE_INFORMATION_EX, Handles[i]) == cbNeeded);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync while (i-- > 0)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync const char *pszType;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync SYSTEM_HANDLE_ENTRY_INFO_EX const *pHandleInfo = &pInfo->Handles[i];
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Handles within the protected process is fine. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( !(pHandleInfo->GrantedAccess & SUPDRV_NT_EVIL_PROCESS_RIGHTS)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* CSRSS is allowed to have one evil process handle.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync See the special cases in the hook code. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && pHandleInfo->UniqueProcessId == pNtProtect->hCsrssPid)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The system process is allowed having one open process handle in
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync Windows 8.1 and later. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pHandleInfo->UniqueProcessId == PsGetProcessId(PsInitialSystemProcess))
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Handles within the protected process is fine. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( !(pHandleInfo->GrantedAccess & SUPDRV_NT_EVIL_THREAD_RIGHTS)
cb39011e69667689c166f1cdf95247b46fff324dvboxsync /* CSRSS is allowed to have one evil handle to the primary thread
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync for LPC purposes. See the hook for special case. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync && pHandleInfo->UniqueProcessId == pNtProtect->hCsrssPid)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Ignore whitelisted debuggers. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pHandleInfo->UniqueProcessId == idLastDebugger)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync NTSTATUS rcNt = PsLookupProcessByProcessId(pHandleInfo->UniqueProcessId, &pDbgProc);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync bool fIsDebugger = supdrvNtProtectIsWhitelistedDebugger(pDbgProc);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Found evil handle. Currently ignoring on pre-Vista. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if ( g_uNtVerCombined >= SUP_MAKE_NT_VER_COMBINED(6, 0, 6001, 0, 0)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: Found evil handle to budding VM process: pid=%p h=%p acc=%#x attr=%#x type=%s\n",
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pHandleInfo->UniqueProcessId, pHandleInfo->HandleValue,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync pHandleInfo->GrantedAccess, pHandleInfo->HandleAttributes, pszType));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Checks if the current process checks out as a VM process stub.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns VBox status code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @param pNtProtect The NT protect structure. This is upgraded to a
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * final protection kind (state) on success.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic int supdrvNtProtectVerifyProcess(PSUPDRVNTPROTECT pNtProtect)
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReturn(PsGetProcessId(PsGetCurrentProcess()) == pNtProtect->AvlCore.Key, VERR_INTERNAL_ERROR_3);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Do the verification. The handle restriction checks are only preformed
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * on VM processes.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (pNtProtect->enmProcessKind >= kSupDrvNtProtectKind_VmProcessUnconfirmed)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supdrvNtProtectRestrictHandlesToProcessAndThread(pNtProtect);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_VERIFY_ONLY,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Upgrade and return.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Stub process verficiation is pretty much straight forward. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubUnverified)
cb39011e69667689c166f1cdf95247b46fff324dvboxsync pNtProtect->enmProcessKind = RT_SUCCESS(rc) ? kSupDrvNtProtectKind_StubSpawning : kSupDrvNtProtectKind_StubDead;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* The VM process verification is a little bit more complicated
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync because we need to drop the parent process reference as well. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync else if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessUnconfirmed)
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync AssertRelease(pNtProtect->cRefs >= 2); /* Parent + Caller */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertRelease(pParent->enmProcessKind == kSupDrvNtProtectKind_StubParent);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pNtProtect->enmProcessKind = kSupDrvNtProtectKind_VmProcessConfirmed;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync pNtProtect->enmProcessKind = kSupDrvNtProtectKind_VmProcessDead;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync /* Since the stub and VM processes are only supposed to have one thread,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync we're not supposed to be subject to any races from within the processes.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync There is a race between VM process verification and the stub process
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync exiting, though. We require the stub process to be alive until the new
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync VM process has made it thru the validation. So, when the stub
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync terminates the notification handler will change the state of both stub
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync and VM process to dead.
cb39011e69667689c166f1cdf95247b46fff324dvboxsync Also, I'm not entirely certain where the process
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync termination notification is triggered from, so that can theorically
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync create a race in both cases. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync AssertReleaseMsg( pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubDead
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync || pNtProtect->enmProcessKind == kSupDrvNtProtectKind_VmProcessDead,
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync ("enmProcessKind=%d rc=%Rrc\n", pNtProtect->enmProcessKind, rc));
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rc = VERR_INVALID_STATE; /* There should be no races here. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Checks if the current process is being debugged.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * @return @c true if debugged, @c false if not.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync return PsIsProcessBeingDebugged(PsGetCurrentProcess()) != FALSE;
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync# endif /* !VBOX_WITHOUT_DEBUGGER_CHECKS */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Terminates the hardening bits.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncstatic void supdrvNtProtectTerm(void)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Stop intercepting process and thread handle creation calls.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Stop intercepting process creation and termination notifications.
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rcNt = g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, TRUE /*fRemove*/);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync rcNt = PsSetCreateProcessNotifyRoutine(supdrvNtProtectCallback_ProcessCreateNotify, TRUE /*fRemove*/);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync * Clean up globals.
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xAF(void);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB0(void);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB1(void);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB2(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB3(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB4(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB5(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB6(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB7(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB8(void);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xB9(void);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xBA(void);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xBB(void);
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xBC(void);
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xBD(void);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0xBE(void);
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0x1F(void);
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0x20(void);
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0x21(void);
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0x22(void);
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncDECLASM(void) supdrvNtQueryVirtualMemory_0x23(void);
cb39011e69667689c166f1cdf95247b46fff324dvboxsyncextern "C" NTSYSAPI NTSTATUS NTAPI ZwRequestWaitReplyPort(HANDLE, PVOID, PVOID);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Initalizes the hardening bits.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * @returns NT status code.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Initialize the globals.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* The NT version. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync g_uNtVerCombined = SUP_MAKE_NT_VER_COMBINED(uMajor, uMinor, uBuild, 0, 0);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Resolve methods we want but isn't available everywhere. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&RoutineName, L"ObGetObjectType");
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync g_pfnObGetObjectType = (PFNOBGETOBJECTTYPE)MmGetSystemRoutineAddress(&RoutineName);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&RoutineName, L"ObRegisterCallbacks");
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync g_pfnObRegisterCallbacks = (PFNOBREGISTERCALLBACKS)MmGetSystemRoutineAddress(&RoutineName);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&RoutineName, L"ObUnRegisterCallbacks");
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync g_pfnObUnRegisterCallbacks = (PFNOBUNREGISTERCALLBACKS)MmGetSystemRoutineAddress(&RoutineName);
cb39011e69667689c166f1cdf95247b46fff324dvboxsync RtlInitUnicodeString(&RoutineName, L"PsSetCreateProcessNotifyRoutineEx");
cb39011e69667689c166f1cdf95247b46fff324dvboxsync g_pfnPsSetCreateProcessNotifyRoutineEx = (PFNPSSETCREATEPROCESSNOTIFYROUTINEEX)MmGetSystemRoutineAddress(&RoutineName);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&RoutineName, L"PsReferenceProcessFilePointer");
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync g_pfnPsReferenceProcessFilePointer = (PFNPSREFERENCEPROCESSFILEPOINTER)MmGetSystemRoutineAddress(&RoutineName);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync RtlInitUnicodeString(&RoutineName, L"PsIsProtectedProcessLight");
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync g_pfnPsIsProtectedProcessLight = (PFNPSISPROTECTEDPROCESSLIGHT)MmGetSystemRoutineAddress(&RoutineName);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RtlInitUnicodeString(&RoutineName, L"ZwAlpcCreatePort");
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync g_pfnZwAlpcCreatePort = (PFNZWALPCCREATEPORT)MmGetSystemRoutineAddress(&RoutineName);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync RtlInitUnicodeString(&RoutineName, L"ZwQueryVirtualMemory"); /* Yes, using Zw version here. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)MmGetSystemRoutineAddress(&RoutineName);
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync if (!g_pfnNtQueryVirtualMemory && g_uNtVerCombined < SUP_NT_VER_VISTA)
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync /* XP & W2K3 doesn't have this function exported, so we've cooked up a
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync few alternative in the assembly helper file that uses the code in
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync ZwReadFile with a different eax value. We figure the syscall number
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync by inspecting ZwQueryVolumeInformationFile as it's the next number. */
3194da424708abdd288b28d96892b3a5f3f7df0bvboxsync uint8_t const *pbCode = (uint8_t const *)(uintptr_t)ZwQueryVolumeInformationFile;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb0: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xAF; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb1: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB0; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb2: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB1; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb3: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB2; break; /* XP SP3 */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb4: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB2; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb5: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB3; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb6: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB4; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb7: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB5; break; /* just in case */
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync case 0xb8: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB6; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xb9: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB7; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xba: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xB8; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xbb: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBA; break; /* W2K3 R2 SP2 */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xbc: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBB; break; /* just in case */
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync case 0xbd: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBC; break; /* just in case */
9a379ef11a4bb232c8e41c12b82ec94c8e10d9a0vboxsync case 0xbe: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBD; break; /* just in case */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync case 0xbf: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0xBE; break; /* just in case */
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync uint8_t const *pbCode = (uint8_t const *)(uintptr_t)ZwRequestWaitReplyPort;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pbCode[12] == 0x48 /* lea rax, [nt!KiServiceLinkage] */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync && pbCode[20] == 0xb8 /* mov eax,1fh <- the syscall no. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /*&& pbCode[21] == 0x1f*/
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync uint8_t const *pbKiServiceInternal = &pbCode[30] + *(int32_t const *)&pbCode[26];
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync uint8_t const *pbKiServiceLinkage = &pbCode[19] + *(int32_t const *)&pbCode[15];
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync g_pfnKiServiceInternal = (PFNRT)pbKiServiceInternal;
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync case 0x1e: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x1F; break;
36c3589d6411416bba897f2595f1812b9d9ff4b3vboxsync case 0x1f: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x20; break;
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync case 0x20: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x21; break;
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync case 0x21: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x22; break;
c66e448632d5ef48cf6b896f02e750440f5c6586vboxsync case 0x22: g_pfnNtQueryVirtualMemory = (PFNNTQUERYVIRTUALMEMORY)supdrvNtQueryVirtualMemory_0x23; break;
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: Cannot locate ZwQueryVirtualMemory in ntoskrnl, nor were we able to cook up a replacement.\n"));
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync LogRel(("vboxdrv: g_pfnObGetObjectType=%p g_pfnZwAlpcCreatePort=%p.\n", g_pfnObGetObjectType, g_pfnZwAlpcCreatePort));
0802b726efeabba46f90cb2b285de4dadaac9507vboxsync /* The spinlock protecting our structures. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync int rc = RTSpinlockCreate(&g_hNtProtectLock, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "NtProtectLock");
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync /* Image stuff + certificates. */
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Intercept process creation and termination.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rcNt = g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, FALSE /*fRemove*/);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync rcNt = PsSetCreateProcessNotifyRoutine(supdrvNtProtectCallback_ProcessCreateNotify, FALSE /*fRemove*/);
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * Intercept process and thread handle creation calls.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync * The preferred method is only available on Vista SP1+.
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync if (g_pfnObRegisterCallbacks && g_pfnObUnRegisterCallbacks)
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync static OB_OPERATION_REGISTRATION s_aObOperations[] =
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE,
ae94ad7e769e467419ab99cab5403bdb39bc544fvboxsync OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE,
for (uint32_t i = 0; i < RT_ELEMENTS(s_apwszAltitudes) && rcNt == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION; i++)
return STATUS_SUCCESS;
# ifndef VBOX_WITH_VISTA_NO_SP
DbgPrint("vboxdrv: ObRegisterCallbacks was not found. Please make sure you got the latest updates and service packs installed\n");
g_pfnPsSetCreateProcessNotifyRoutineEx(supdrvNtProtectCallback_ProcessCreateNotifyEx, TRUE /*fRemove*/);
return rcNt;