BOOLEAN XenLowerBackendInit( PXEN_LOWER XenLower) { PCHAR path; NTSTATUS status; // Note this is split from the XenLowerInit so it can be called on the resume // path in case backend values change. XXX_TODO("--XT-- All the backend path handling assumes dom0 is the backend, this will change for device domains") // XXX TODO all the backend path handling assumes dom0 is the backend. This will // not necessarily be true with device domains. The changes to support this go // beyond this module though. path = XenLowerReadXenstoreValue(XenLower->FrontendPath, "backend"); if (path == NULL) { TraceError((__FUNCTION__ ": XenLowerReadXenstoreValue() failed to return the back end path, fatal.\n")); return FALSE; } status = RtlStringCchCopyA(XenLower->BackendPath, sizeof(XenLower->BackendPath), path); XmFreeMemory(path); if (status != STATUS_SUCCESS) { XenLower->BackendPath[0] = 0; TraceError((__FUNCTION__ ": Failed to copy back end path - status: 0x%x\n", status)); return FALSE; } status = xenbus_read_domain_id(XBT_NIL, XenLower->FrontendPath, "backend-id", &XenLower->BackendDomid); if (!NT_SUCCESS(status)) { TraceWarning((__FUNCTION__ ": Failed to read backend id from %s (%x), setting to dom0\n", XenLower->FrontendPath, status)); XenLower->BackendDomid = DOMAIN_ID_0(); } // XXX TODO for now we only support a dom0 backend so check that here. Later // when we support a device domain for vusb, other domids will be fine. XXX_TODO("--XT-- For now we only support a dom0 backend so check that here"); if (unwrap_DOMAIN_ID(XenLower->BackendDomid) != unwrap_DOMAIN_ID(DOMAIN_ID_0())) { TraceError((XENTARGET ": cannot connect to backend Domid: %d, only dom0 supported currently\n", XenLower->BackendDomid)); return FALSE; } TraceInfo((__FUNCTION__ ": XenLower initialized - FrontendPath: %s BackendPath: %s BackendDomid: %d\n", XenLower->FrontendPath, XenLower->BackendPath, unwrap_DOMAIN_ID(XenLower->BackendDomid))); return TRUE; }
// Buffer the log entry to the log buffer. EXTERN_C static NTSTATUS LogpBufferMessage(_In_ const char *Message, _In_opt_ LogBufferInfo *Info) { NT_ASSERT(Info); // Acquire a spin lock to add the log safely. const auto oldIrql = KeGetCurrentIrql(); if (oldIrql < DISPATCH_LEVEL) { KeAcquireSpinLockRaiseToDpc(&Info->SpinLock); } NT_ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); // Copy the current log to the buffer. size_t usedBufferSize = Info->LogBufferTail - Info->LogBufferHead; auto status = RtlStringCchCopyA(const_cast<char *>(Info->LogBufferTail), LOGP_BUFFER_USABLE_SIZE - usedBufferSize, Message); // Update Info.LogMaximumUsage if necessary. if (NT_SUCCESS(status)) { const auto messageLength = strlen(Message) + 1; Info->LogBufferTail += messageLength; usedBufferSize += messageLength; if (usedBufferSize > Info->LogMaximumUsage) { Info->LogMaximumUsage = usedBufferSize; // Update } } else { Info->LogMaximumUsage = LOGP_BUFFER_SIZE; // Indicates overflow } *Info->LogBufferTail = '\0'; if (oldIrql < DISPATCH_LEVEL) { KeReleaseSpinLock(&Info->SpinLock, oldIrql); } return status; }
BOOLEAN XenLowerInit( PXEN_LOWER XenLower, PVOID XenUpper, PDEVICE_OBJECT Pdo) { PCHAR path; NTSTATUS status; XenLower->XenUpper = XenUpper; XenLower->Pdo = Pdo; // // Wait for xenbus to come up. SMP guests sometimes try and // initialise xennet and xenvbd in parallel when they come back // from hibernation, and that causes problems. // if (!xenbus_await_initialisation()) { TraceError((__FUNCTION__ ": xenbus_await_initialisation() failed?\n")); return FALSE; } path = xenbus_find_frontend(Pdo); if (path == NULL) { TraceError((__FUNCTION__ ": xenbus_find_frontend() failed to return the front end path, fatal.\n")); return FALSE; } status = RtlStringCchCopyA(XenLower->FrontendPath, sizeof(XenLower->FrontendPath), path); XmFreeMemory(path); if (status != STATUS_SUCCESS) { XenLower->FrontendPath[0] = 0; TraceError((__FUNCTION__ ": Failed to copy front end path - status: 0x%x\n", status)); return FALSE; } return TRUE; }
// Buffer the log entry to the log buffer. _Use_decl_annotations_ static NTSTATUS LogpBufferMessage(const char *message, LogBufferInfo *info) { NT_ASSERT(info); // Acquire a spin lock to add the log safely. KLOCK_QUEUE_HANDLE lock_handle = {}; const auto old_irql = KeGetCurrentIrql(); if (old_irql < DISPATCH_LEVEL) { KeAcquireInStackQueuedSpinLock(&info->spin_lock, &lock_handle); } else { KeAcquireInStackQueuedSpinLockAtDpcLevel(&info->spin_lock, &lock_handle); } NT_ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); // Copy the current log to the buffer. SIZE_T used_buffer_size = info->log_buffer_tail - info->log_buffer_head; auto status = RtlStringCchCopyA(const_cast<char *>(info->log_buffer_tail), kLogpBufferUsableSize - used_buffer_size, message); // Update info.log_max_usage if necessary. if (NT_SUCCESS(status)) { const auto message_length = strlen(message) + 1; info->log_buffer_tail += message_length; used_buffer_size += message_length; if (used_buffer_size > info->log_max_usage) { info->log_max_usage = used_buffer_size; // Update } } else { info->log_max_usage = kLogpBufferSize; // Indicates overflow } *info->log_buffer_tail = '\0'; if (old_irql < DISPATCH_LEVEL) { KeReleaseInStackQueuedSpinLock(&lock_handle); } else { KeReleaseInStackQueuedSpinLockFromDpcLevel(&lock_handle); } return status; }
NTSTATUS DiskGenerateDeviceName( IN ULONG DeviceNumber, OUT PCCHAR *RawName ) /*++ Routine Description: This routine will allocate a unicode string buffer and then fill it in with a generated name for the specified device object. It is the responsibility of the user to allocate a UNICODE_STRING structure to pass in and to free UnicodeName->Buffer when done with it. Arguments: DeviceObject - a pointer to the device object UnicodeName - a unicode string to put the name buffer into Return Value: status --*/ #define FDO_NAME_FORMAT "\\Device\\Harddisk%d\\DR%d" { CHAR rawName[64] = { 0 }; NTSTATUS status; PAGED_CODE(); status = RtlStringCchPrintfA(rawName, sizeof(rawName) - 1, FDO_NAME_FORMAT, DeviceNumber, diskDeviceSequenceNumber++); if (!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskGenerateDeviceName: Format FDO name failed with error: 0x%X\n", status)); return status; } *RawName = ExAllocatePoolWithTag(PagedPool, strlen(rawName) + 1, DISK_TAG_NAME); if(*RawName == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } status = RtlStringCchCopyA(*RawName, strlen(rawName) + 1, rawName); if (!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_ERROR, TRACE_FLAG_PNP, "DiskGenerateDeviceName: Device name copy failed with error: 0x%X\n", status)); FREE_POOL(*RawName); return status; } TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskGenerateDeviceName: generated \"%s\"\n", rawName)); return STATUS_SUCCESS; }
/*++ * @method: AddListEntry * * @description: Add an entry to the list of specified type * * @input: eListType eTypeOfList, PVOID pItemToAdd, BOOLEAN bFind * * @output: NTSTATUS * *--*/ NTSTATUS AddListEntry( eListType eTypeOfList, PVOID pItemToAdd, BOOLEAN bFind ) { NTSTATUS retVal = STATUS_UNSUCCESSFUL; __try { // Check if the entry is already present if( bFind && ( STATUS_SUCCESS == FindEntry( eTypeOfList, pItemToAdd ) ) ) { retVal = STATUS_DUPLICATE_OBJECTID; return retVal; } // Insert into a list based on type of list switch( eTypeOfList ) { case eProcList: { if( MmIsAddressValid( g_lstArray.pProcListHead ) ) { PPROCLISTENTRY pNewEntry = NULL; pNewEntry = ExAllocatePoolWithTag( NonPagedPool, sizeof( PROCLISTENTRY ), ARKITLISTTAG ); if( pNewEntry ) { RtlZeroMemory( pNewEntry, sizeof( PROCLISTENTRY ) ); pNewEntry->dwPID = ((PPROCLISTENTRY)pItemToAdd)->dwPID; RtlStringCchCopyA( pNewEntry->szProcName, ARKITLIB_STR_LEN, ((PPROCLISTENTRY)pItemToAdd)->szProcName ); InsertHeadList( g_lstArray.pProcListHead, &( pNewEntry->lEntry ) ); retVal = STATUS_SUCCESS; } } } break; case eDllList: { if( MmIsAddressValid( g_lstArray.pDllListHead ) ) { PDLLLISTENTRY pNewEntry = ExAllocatePoolWithTag( NonPagedPool, sizeof( DLLLISTENTRY ), ARKITLISTTAG ); if( pNewEntry ) { RtlZeroMemory( pNewEntry, sizeof( DLLLISTENTRY ) ); pNewEntry->dwBase = ((PDLLLISTENTRY)pItemToAdd)->dwBase; RtlStringCchCopyA( pNewEntry->szDllName, ARKITLIB_STR_LEN, ((PDLLLISTENTRY)pItemToAdd)->szDllName ); InsertHeadList( g_lstArray.pDllListHead, &( pNewEntry->lEntry ) ); retVal = STATUS_SUCCESS; } } } break; case eDrvList: { if( MmIsAddressValid( g_lstArray.pDrvListHead ) ) { PDRIVERLISTENTRY pNewEntry = NULL; pNewEntry = ExAllocatePoolWithTag( NonPagedPool, sizeof( DRIVERLISTENTRY ), ARKITLISTTAG ); if( pNewEntry ) { RtlZeroMemory( pNewEntry, sizeof( DRIVERLISTENTRY ) ); pNewEntry->dwBase = ((PDRIVERLISTENTRY)pItemToAdd)->dwBase; pNewEntry->dwEnd = ((PDRIVERLISTENTRY)pItemToAdd)->dwEnd; pNewEntry->dwEntryPoint = ((PDRIVERLISTENTRY)pItemToAdd)->dwEntryPoint; RtlStringCchCopyA( pNewEntry->szDrvName, ARKITLIB_STR_LEN, ((PDRIVERLISTENTRY)pItemToAdd)->szDrvName ); InsertHeadList( g_lstArray.pDrvListHead, &( pNewEntry->lEntry ) ); retVal = STATUS_SUCCESS; } } } break; case eSsdtList: { if( MmIsAddressValid( g_lstArray.pSsdtListHead ) ) { PSSDTHOOKLISTENTRY pNewEntry = NULL; pNewEntry = ExAllocatePoolWithTag( NonPagedPool, sizeof( SSDTHOOKLISTENTRY ), ARKITLISTTAG ); if( pNewEntry ) { RtlZeroMemory( pNewEntry, sizeof( SSDTHOOKLISTENTRY ) ); pNewEntry->unIndex = ((PSSDTHOOKLISTENTRY)pItemToAdd)->unIndex; pNewEntry->dwHookAddr = ((PSSDTHOOKLISTENTRY)pItemToAdd)->dwHookAddr; pNewEntry->dwBase = ((PSSDTHOOKLISTENTRY)pItemToAdd)->dwBase; pNewEntry->dwEnd = ((PSSDTHOOKLISTENTRY)pItemToAdd)->dwEnd; RtlStringCchCopyA( pNewEntry->szDrvName, ARKITLIB_STR_LEN, ((PSSDTHOOKLISTENTRY)pItemToAdd)->szDrvName ); InsertHeadList( g_lstArray.pSsdtListHead, &( pNewEntry->lEntry ) ); retVal = STATUS_SUCCESS; } } } break; default: { retVal = STATUS_UNSUCCESSFUL; } break; } } __except( EXCEPTION_EXECUTE_HANDLER ) { DbgPrint( "Exception caught in AddListEntry()" ); retVal = STATUS_UNSUCCESSFUL; } return retVal; }
/*++ * @method: DrvDispatch * * @description: IOCTL dispatch routine * * @input: IN PDEVICE_OBJECT pDevice, IN PIRP pIrp * * @output: NTSTATUS * *--*/ NTSTATUS DrvDispatch( IN PDEVICE_OBJECT pDevice, IN PIRP pIrp ) { NTSTATUS retVal = STATUS_UNSUCCESSFUL; __try { UINT nIndex = 0; DWORD dwInBuffSize = 0; DWORD dwOutBuffSize = 0; PIO_STACK_LOCATION pIoStackIrp = NULL; if( MmIsAddressValid( pIrp ) ) { pIoStackIrp = IoGetCurrentIrpStackLocation( pIrp ); } if( MmIsAddressValid( pIoStackIrp ) ) { dwInBuffSize = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; dwOutBuffSize = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength; } switch( pIoStackIrp->Parameters.DeviceIoControl.IoControlCode ) { case IOCTL_OS_VER_INFO: { // Set OS and SP versions got from usermode, in our globals PMYOSVERINFO pOSVerInfo = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pOSVerInfo ) ) { if( STATUS_SUCCESS == InitGlobals( pOSVerInfo ) ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = dwInBuffSize; } } } break; case IOCTL_GET_DATA_CNT: { // Get the count of items requested by usermode PARKDATACOUNT pArkDataCout = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pArkDataCout ) ) { switch( pArkDataCout->typeOfArkData ) { case eArkDataProcList: { // Get the count of running processes pArkDataCout->dataCount = ScanAndGetProcessCount(); } break; case eArkDataDllList: { // Get the count of DLLs pArkDataCout->dataCount = ScanAndGetDllCount( pArkDataCout->miscData ); } break; case eArkDataDriverList: { // Get the count of loaded drivers pArkDataCout->dataCount = ScanAndGetDriverCount(); } break; case eArkDataSsdtList: { // Get the count of SSDT hooks pArkDataCout->dataCount = ScanAndGetSSDTHooksCount(); } break; default: { pArkDataCout->dataCount = 0; } break; } // Set the IO status based on count of items if( pArkDataCout->dataCount > 0 ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = sizeof( ARKDATACOUNT ); } } } break; case IOCTL_GET_PROCESS: { // Copy all processes info from our internal list to usermode array PARKPROCESS pArkProcData = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pArkProcData ) && VALIDATE_LIST_BUFF_SIZE( dwOutBuffSize, ARKPROCESS, eProcList ) ) { PPROCLISTENTRY pProcListEntry = NULL; while( STATUS_SUCCESS == GetListEntry( eProcList, nIndex, &pProcListEntry ) ) { if( MmIsAddressValid( pProcListEntry ) ) { pArkProcData[nIndex].procId = pProcListEntry->dwPID; RtlStringCchCopyA( pArkProcData[nIndex].procName, ARKITLIB_STR_LEN, pProcListEntry->szProcName ); ++nIndex; } else { break; } } if( nIndex > 0 ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = dwOutBuffSize; } } // Free our internal process list DelList( eProcList ); } break; case IOCTL_GET_DLLS: { // Copy all DLLs info from our internal list to usermode array PARKDLL pArkDllData = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pArkDllData ) && VALIDATE_LIST_BUFF_SIZE( dwOutBuffSize, ARKDLL, eDllList ) ) { PDLLLISTENTRY pDllListEntry = NULL; while( STATUS_SUCCESS == GetListEntry( eDllList, nIndex, &pDllListEntry ) ) { if( MmIsAddressValid( pDllListEntry ) ) { pArkDllData[nIndex].baseAddr = pDllListEntry->dwBase; RtlStringCchCopyA( pArkDllData[nIndex].dllName, ARKITLIB_STR_LEN, pDllListEntry->szDllName ); ++nIndex; } else { break; } } if( nIndex > 0 ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = dwOutBuffSize; } } // Free our internal DLL list DelList( eDllList ); } break; case IOCTL_GET_DRIVERS: { // Copy all drivers info from our internal list to usermode array PARKDRIVER pArkDrvData = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pArkDrvData ) && VALIDATE_LIST_BUFF_SIZE( dwOutBuffSize, ARKDRIVER, eDrvList ) ) { PDRIVERLISTENTRY pDrvListEntry = NULL; while( STATUS_SUCCESS == GetListEntry( eDrvList, nIndex, &pDrvListEntry ) ) { if( MmIsAddressValid( pDrvListEntry ) ) { pArkDrvData[nIndex].baseAddr = pDrvListEntry->dwBase; pArkDrvData[nIndex].endAddr = pDrvListEntry->dwEnd; pArkDrvData[nIndex].entryPoint = pDrvListEntry->dwEntryPoint; RtlStringCchCopyA( pArkDrvData[nIndex].driverName, ARKITLIB_STR_LEN, pDrvListEntry->szDrvName ); ++nIndex; } else { break; } } if( nIndex > 0 ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = dwOutBuffSize; } } // Free our internal driver list DelList( eDrvList ); } break; case IOCTL_GET_SSDTHOOKS: { // Copy all SSDT hooks info from our internal list to usermode array PARKSSDTHOOK pArkSsdtData = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pArkSsdtData ) && VALIDATE_LIST_BUFF_SIZE( dwOutBuffSize, ARKSSDTHOOK, eSsdtList ) ) { PSSDTHOOKLISTENTRY pSsdtListEntry = NULL; while( STATUS_SUCCESS == GetListEntry( eSsdtList, nIndex, &pSsdtListEntry ) ) { if( MmIsAddressValid( pSsdtListEntry ) ) { pArkSsdtData[nIndex].unSsdtIndex = pSsdtListEntry->unIndex; pArkSsdtData[nIndex].baseAddr = pSsdtListEntry->dwBase; pArkSsdtData[nIndex].endAddr = pSsdtListEntry->dwEnd; pArkSsdtData[nIndex].hookAddr = pSsdtListEntry->dwHookAddr; RtlStringCchCopyA( pArkSsdtData[nIndex].driverName, ARKITLIB_STR_LEN, pSsdtListEntry->szDrvName ); ++nIndex; } else { break; } } if( nIndex > 0 ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = dwOutBuffSize; } } // Free our internal driver and SSDT list DelList( eDrvList ); DelList( eSsdtList ); } break; case IOCTL_GET_SYSENTERHOOK: { // Copy sysenter hook data to usermode buffer PARKSYSENTERHOOK pSysenterHookData = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pSysenterHookData ) ) { if( ScanAndGetSysenterHook( pSysenterHookData ) ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = dwOutBuffSize; } } // Free driver list DelList( eDrvList ); } break; case IOCTL_GET_KINLINEHOOK: { PARKINLINEHOOK pKernelFuncData = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pKernelFuncData ) ) { if( ScanFunctionInlineHook( pKernelFuncData ) ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = dwOutBuffSize; } } } break; case IOCTL_NT_API_INFO: { PARKNTAPI pNtApiData = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pNtApiData ) ) { if( STATUS_SUCCESS == InitNtApiData( pNtApiData ) ) { retVal = STATUS_SUCCESS; pIrp->IoStatus.Information = dwInBuffSize; } } } break; case IOCTL_FIX_ISSUES: { PARKFIX pFixData = pIrp->AssociatedIrp.SystemBuffer; if( MmIsAddressValid( pFixData ) ) { switch( pFixData->eType ) { case eArkKillProcess: { PDWORD pdwPid = (PDWORD)(pFixData->cFixData); if( KillProcess( pdwPid ) ) { retVal = STATUS_SUCCESS; } } break; case eArkFixSsdtHook: { PARKFIXSSDT pFixSsdtHookData = (PARKFIXSSDT)(pFixData->cFixData); if( FixSSDTHook( pFixSsdtHookData ) ) { retVal = STATUS_SUCCESS; } } break; case eArkFixInlineHook: { PARKFIXINLINEHOOK pFixInlineHook = (PARKFIXINLINEHOOK)(pFixData->cFixData); if( FixInlineHook( pFixInlineHook ) ) { retVal = STATUS_SUCCESS; } } break; } if( STATUS_SUCCESS == retVal ) { pIrp->IoStatus.Information = dwInBuffSize; } } } break; default: { retVal = STATUS_UNSUCCESSFUL; pIrp->IoStatus.Information = 0; } break; } pIrp->IoStatus.Status = retVal; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); } __except( EXCEPTION_EXECUTE_HANDLER ) { retVal = STATUS_UNSUCCESSFUL; DbgPrint( "Exception caught in DrvDispatch()" ); } return retVal; }