Changeset 91559 in vbox for trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
- Timestamp:
- Oct 5, 2021 8:28:55 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
r90780 r91559 90 90 #define VBOXDRV_WITH_FAST_IO 91 91 92 /** Enables generating UID from NT SIDs so the GMM can share free memory 93 * among VMs running as the same user. */ 94 //#define VBOXDRV_WITH_SID_TO_UID_MAPPING 95 92 96 /* Missing if we're compiling against older WDKs. */ 93 97 #ifndef NonPagedPoolNx … … 99 103 * Structures and Typedefs * 100 104 *********************************************************************************************************************************/ 105 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 106 /** 107 * SID to User ID mapping. 108 * 109 * This is used to generate a RTUID value for a NT security identifier. 110 * Normally, the UID is the hash of the SID string, but due to collisions it may 111 * differ. See g_NtUserIdHashTree and g_NtUserIdUidTree. 112 */ 113 typedef struct SUPDRVNTUSERID 114 { 115 /** Hash tree node, key: RTStrHash1 of szSid. */ 116 AVLLU32NODECORE HashCore; 117 /** UID three node, key: The UID. */ 118 AVLU32NODECORE UidCore; 119 /** Reference counter. */ 120 uint32_t volatile cRefs; 121 /** The length of the SID string. */ 122 uint16_t cchSid; 123 /** The SID string for the user. */ 124 char szSid[RT_FLEXIBLE_ARRAY]; 125 } SUPDRVNTUSERID; 126 /** Pointer to a SID to UID mapping. */ 127 typedef SUPDRVNTUSERID *PSUPDRVNTUSERID; 128 #endif 129 101 130 /** 102 131 * Device extension used by VBoxDrvU. … … 404 433 static PFNKEGETPROCESSORNUMBERFROMINDEX g_pfnKeGetProcessorNumberFromIndex = NULL; 405 434 435 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 436 /** Spinlock protecting g_NtUserIdHashTree and g_NtUserIdUidTree. */ 437 static RTSPINLOCK g_hNtUserIdLock = NIL_RTSPINLOCK; 438 /** AVL tree of SUPDRVNTUSERID structures by hash value. */ 439 static PAVLLU32NODECORE g_NtUserIdHashTree = NULL; 440 /** AVL tree of SUPDRVNTUSERID structures by UID. */ 441 static PAVLU32NODECORE g_NtUserIdUidTree = NULL; 442 #endif 443 406 444 #ifdef VBOX_WITH_HARDENING 407 445 /** Pointer to the stub device instance. */ … … 657 695 #endif 658 696 { 697 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 659 698 /* 660 * Create device. 661 * (That means creating a device object and a symbolic link so the DOS 662 * subsystems (OS/2, win32, ++) can access the device.) 699 * Create the spinlock for the SID -> UID mappings. 663 700 */ 664 rcNt = vboxdrvNtCreateDevices(pDrvObj); 665 if (NT_SUCCESS(rcNt)) 701 vrc = RTSpinlockCreate(&g_hNtUserIdLock, RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE, "NtUserId"); 702 if (RT_SUCCESS(vrc)) 703 #endif 666 704 { 667 705 /* 668 * Initialize the device extension. 706 * Create device. 707 * (That means creating a device object and a symbolic link so the DOS 708 * subsystems (OS/2, win32, ++) can access the device.) 669 709 */ 670 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension; 671 memset(pDevExt, 0, sizeof(*pDevExt)); 672 673 vrc = supdrvInitDevExt(pDevExt, sizeof(SUPDRVSESSION)); 674 if (!vrc) 710 rcNt = vboxdrvNtCreateDevices(pDrvObj); 711 if (NT_SUCCESS(rcNt)) 675 712 { 676 713 /* 677 * Setup the driver entry points in pDrvObj.714 * Initialize the device extension. 678 715 */ 679 pDrvObj->DriverUnload = VBoxDrvNtUnload; 680 pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxDrvNtCreate; 681 pDrvObj->MajorFunction[IRP_MJ_CLEANUP] = VBoxDrvNtCleanup; 682 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxDrvNtClose; 683 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxDrvNtDeviceControl; 684 pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VBoxDrvNtInternalDeviceControl; 685 pDrvObj->MajorFunction[IRP_MJ_READ] = VBoxDrvNtRead; 686 pDrvObj->MajorFunction[IRP_MJ_WRITE] = VBoxDrvNtNotSupportedStub; 716 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)g_pDevObjSys->DeviceExtension; 717 memset(pDevExt, 0, sizeof(*pDevExt)); 718 719 vrc = supdrvInitDevExt(pDevExt, sizeof(SUPDRVSESSION)); 720 if (!vrc) 721 { 722 /* 723 * Setup the driver entry points in pDrvObj. 724 */ 725 pDrvObj->DriverUnload = VBoxDrvNtUnload; 726 pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxDrvNtCreate; 727 pDrvObj->MajorFunction[IRP_MJ_CLEANUP] = VBoxDrvNtCleanup; 728 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxDrvNtClose; 729 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxDrvNtDeviceControl; 730 pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VBoxDrvNtInternalDeviceControl; 731 pDrvObj->MajorFunction[IRP_MJ_READ] = VBoxDrvNtRead; 732 pDrvObj->MajorFunction[IRP_MJ_WRITE] = VBoxDrvNtNotSupportedStub; 687 733 688 734 #ifdef VBOXDRV_WITH_FAST_IO 689 /* Fast I/O to speed up guest execution roundtrips. */690 pDrvObj->FastIoDispatch = (PFAST_IO_DISPATCH)&g_VBoxDrvFastIoDispatch;735 /* Fast I/O to speed up guest execution roundtrips. */ 736 pDrvObj->FastIoDispatch = (PFAST_IO_DISPATCH)&g_VBoxDrvFastIoDispatch; 691 737 #endif 692 738 739 /* 740 * Register ourselves for power state changes. We don't 741 * currently care if this fails. 742 */ 743 UNICODE_STRING CallbackName; 744 RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState"); 745 746 OBJECT_ATTRIBUTES Attr; 747 InitializeObjectAttributes(&Attr, &CallbackName, OBJ_CASE_INSENSITIVE, NULL, NULL); 748 749 rcNt = ExCreateCallback(&pDevExt->pObjPowerCallback, &Attr, TRUE, TRUE); 750 if (rcNt == STATUS_SUCCESS) 751 pDevExt->hPowerCallback = ExRegisterCallback(pDevExt->pObjPowerCallback, 752 VBoxPowerDispatchCallback, 753 g_pDevObjSys); 754 755 /* 756 * Done! Returning success! 757 */ 758 Log(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n")); 759 return STATUS_SUCCESS; 760 } 761 693 762 /* 694 * Register ourselves for power state changes. We don't 695 * currently care if this fails. 763 * Failed. Clean up. 696 764 */ 697 UNICODE_STRING CallbackName; 698 RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState"); 699 700 OBJECT_ATTRIBUTES Attr; 701 InitializeObjectAttributes(&Attr, &CallbackName, OBJ_CASE_INSENSITIVE, NULL, NULL); 702 703 rcNt = ExCreateCallback(&pDevExt->pObjPowerCallback, &Attr, TRUE, TRUE); 704 if (rcNt == STATUS_SUCCESS) 705 pDevExt->hPowerCallback = ExRegisterCallback(pDevExt->pObjPowerCallback, 706 VBoxPowerDispatchCallback, 707 g_pDevObjSys); 708 709 /* 710 * Done! Returning success! 711 */ 712 Log(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n")); 713 return STATUS_SUCCESS; 765 Log(("supdrvInitDevExit failed with vrc=%d!\n", vrc)); 766 rcNt = VBoxDrvNtErr2NtStatus(vrc); 767 768 vboxdrvNtDestroyDevices(); 714 769 } 715 716 Log(("supdrvInitDevExit failed with vrc=%d!\n", vrc)); 770 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 771 RTSpinlockDestroy(g_hNtUserIdLock); 772 g_hNtUserIdLock = NIL_RTSPINLOCK; 773 #endif 774 } 775 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 776 else 717 777 rcNt = VBoxDrvNtErr2NtStatus(vrc); 718 719 vboxdrvNtDestroyDevices(); 720 } 778 #endif 721 779 #ifdef VBOX_WITH_HARDENING 722 780 supdrvNtProtectTerm(); … … 758 816 */ 759 817 supdrvDeleteDevExt(pDevExt); 818 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 819 RTSpinlockDestroy(g_hNtUserIdLock); 820 g_hNtUserIdLock = NIL_RTSPINLOCK; 821 #endif 760 822 #ifdef VBOX_WITH_HARDENING 761 823 supdrvNtProtectTerm(); … … 768 830 } 769 831 832 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 833 834 /** 835 * Worker for supdrvNtUserIdMakeForSession. 836 */ 837 static bool supdrvNtUserIdMakeUid(PSUPDRVNTUSERID pNtUserId) 838 { 839 pNtUserId->UidCore.Key = pNtUserId->HashCore.Key; 840 for (uint32_t cTries = 0; cTries < _4K; cTries++) 841 { 842 bool fRc = RTAvlU32Insert(&g_NtUserIdUidTree, &pNtUserId->UidCore); 843 if (fRc) 844 return true; 845 pNtUserId->UidCore.Key += pNtUserId->cchSid | 1; 846 } 847 return false; 848 } 849 850 851 /** 852 * Try create a RTUID value for the session. 853 * 854 * @returns VBox status code. 855 * @param pSession The session to try set SUPDRVSESSION::Uid for. 856 */ 857 static int supdrvNtUserIdMakeForSession(PSUPDRVSESSION pSession) 858 { 859 /* 860 * Get the current security context and query the User SID for it. 861 */ 862 SECURITY_SUBJECT_CONTEXT Ctx = { NULL, SecurityIdentification, NULL, NULL }; 863 SeCaptureSubjectContext(&Ctx); 864 865 int rc; 866 TOKEN_USER *pTokenUser = NULL; 867 NTSTATUS rcNt = SeQueryInformationToken(SeQuerySubjectContextToken(&Ctx) /* or always PrimaryToken?*/, 868 TokenUser, (PVOID *)&pTokenUser); 869 if (NT_SUCCESS(rcNt)) 870 { 871 /* 872 * Convert the user SID to a string to make it easier to handle, then prepare 873 * a user ID entry for it as that way we can combine lookup and insertion and 874 * avoid needing to deal with races. 875 */ 876 UNICODE_STRING UniStr = RTNT_NULL_UNISTR(); 877 rcNt = RtlConvertSidToUnicodeString(&UniStr, &pTokenUser->User.Sid, TRUE /*AllocateDesitnationString*/); 878 if (NT_SUCCESS(rcNt)) 879 { 880 size_t cchSid = 0; 881 rc = RTUtf16CalcUtf8LenEx(UniStr.Buffer, UniStr.Length / sizeof(RTUTF16), &cchSid); 882 if (RT_SUCCESS(rc)) 883 { 884 PSUPDRVNTUSERID const pNtUserIdNew = (PSUPDRVNTUSERID)RTMemAlloc(RT_UOFFSETOF_DYN(SUPDRVNTUSERID, szSid[cchSid + 1])); 885 if (pNtUserIdNew) 886 { 887 char *pszSid = pNtUserIdNew->szSid; 888 rc = RTUtf16ToUtf8Ex(UniStr.Buffer, UniStr.Length / sizeof(RTUTF16), &pszSid, cchSid + 1, NULL); 889 if (RT_SUCCESS(rc)) 890 { 891 pNtUserIdNew->HashCore.Key = RTStrHash1(pNtUserIdNew->szSid); 892 pNtUserIdNew->cchSid = (uint16_t)cchSid; 893 pNtUserIdNew->cRefs = 1; 894 895 /* 896 * Do the lookup / insert. 897 */ 898 RTSpinlockAcquire(g_hNtUserIdLock); 899 AssertCompileMemberOffset(SUPDRVNTUSERID, HashCore, 0); 900 PSUPDRVNTUSERID pNtUserId = (PSUPDRVNTUSERID)RTAvllU32Get(&g_NtUserIdHashTree, pNtUserIdNew->HashCore.Key); 901 if (pNtUserId) 902 { 903 /* Match the strings till we reach the end of the collision list. */ 904 PSUPDRVNTUSERID const pNtUserIdHead = pNtUserId; 905 while ( pNtUserId 906 && ( pNtUserId->cchSid != cchSid 907 || memcmp(pNtUserId->szSid, pNtUserId->szSid, cchSid) != 0)) 908 pNtUserId = (PSUPDRVNTUSERID)pNtUserId->HashCore.pList; 909 if (pNtUserId) 910 { 911 /* Found matching: Retain reference and free the new entry we prepared. */ 912 uint32_t cRefs = ASMAtomicIncU32(&pNtUserId->cRefs); 913 Assert(cRefs < _16K); 914 RTSpinlockRelease(g_hNtUserIdLock); 915 } 916 else 917 { 918 /* No match: Try insert prepared entry after the head node. */ 919 if (supdrvNtUserIdMakeUid(pNtUserIdNew)) 920 { 921 pNtUserIdNew->HashCore.pList = pNtUserIdHead->HashCore.pList; 922 pNtUserIdHead->HashCore.pList = &pNtUserIdNew->HashCore; 923 pNtUserId = pNtUserIdNew; 924 } 925 RTSpinlockRelease(g_hNtUserIdLock); 926 } 927 } 928 else 929 { 930 /* No matching hash: Try insert the prepared entry. */ 931 pNtUserIdNew->UidCore.Key = pNtUserIdNew->HashCore.Key; 932 if (supdrvNtUserIdMakeUid(pNtUserIdNew)) 933 { 934 RTAvllU32Insert(&g_NtUserIdHashTree, &pNtUserIdNew->HashCore); 935 pNtUserId = pNtUserIdNew; 936 } 937 RTSpinlockRelease(g_hNtUserIdLock); 938 } 939 940 if (pNtUserId != pNtUserIdNew) 941 RTMemFree(pNtUserIdNew); 942 943 /* 944 * Update the session info. 945 */ 946 pSession->pNtUserId = pNtUserId; 947 pSession->Uid = pNtUserId ? (RTUID)pNtUserId->UidCore.Key : NIL_RTUID; 948 } 949 else 950 RTMemFree(pNtUserIdNew); 951 } 952 else 953 rc = VERR_NO_MEMORY; 954 } 955 RtlFreeUnicodeString(&UniStr); 956 } 957 else 958 rc = RTErrConvertFromNtStatus(rcNt); 959 ExFreePool(pTokenUser); 960 } 961 else 962 rc = RTErrConvertFromNtStatus(rcNt); 963 964 SeReleaseSubjectContext(&Ctx); 965 return rc; 966 } 967 968 969 /** 970 * Releases a reference to @a pNtUserId. 971 * 972 * @param pNtUserId The NT user ID entry to release. 973 */ 974 static void supdrvNtUserIdRelease(PSUPDRVNTUSERID pNtUserId) 975 { 976 if (pNtUserId) 977 { 978 uint32_t cRefs = ASMAtomicDecU32(&pNtUserId->cRefs); 979 Assert(cRefs < _8K); 980 if (cRefs == 0) 981 { 982 RTSpinlockAcquire(g_hNtUserIdLock); 983 if (pNtUserId->cRefs == 0) 984 { 985 PAVLLU32NODECORE pAssert1 = RTAvllU32RemoveNode(&g_NtUserIdHashTree, &pNtUserId->HashCore); 986 PAVLU32NODECORE pAssert2 = RTAvlU32Remove(&g_NtUserIdUidTree, pNtUserId->UidCore.Key); 987 988 RTSpinlockRelease(g_hNtUserIdLock); 989 990 Assert(pAssert1 == &pNtUserId->HashCore); 991 Assert(pAssert2 == &pNtUserId->UidCore); 992 RT_NOREF(pAssert1, pAssert2); 993 994 RTMemFree(pNtUserId); 995 } 996 else 997 RTSpinlockRelease(g_hNtUserIdLock); 998 } 999 } 1000 } 1001 1002 #endif /* VBOXDRV_WITH_SID_TO_UID_MAPPING */ 770 1003 771 1004 /** … … 912 1145 if (RT_SUCCESS(rc)) 913 1146 { 914 rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL); 1147 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 1148 rc = supdrvNtUserIdMakeForSession(pSession); 1149 if (RT_SUCCESS(rc)) 1150 #endif 1151 rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL); 915 1152 supdrvSessionRelease(pSession); 916 1153 if (RT_SUCCESS(rc)) … … 957 1194 if (RT_SUCCESS(rc)) 958 1195 { 959 rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL); 1196 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 1197 rc = supdrvNtUserIdMakeForSession(pSession); 1198 if (RT_SUCCESS(rc)) 1199 #endif 1200 rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL); 960 1201 supdrvSessionRelease(pSession); 961 1202 if (RT_SUCCESS(rc)) … … 977 1218 if (RT_SUCCESS(rc)) 978 1219 { 979 rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL); 1220 # ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 1221 rc = supdrvNtUserIdMakeForSession(pSession); 1222 if (RT_SUCCESS(rc)) 1223 # endif 1224 rc = supdrvSessionHashTabInsert(pDevExt, pSession, (PSUPDRVSESSION *)&pFileObj->FsContext, NULL); 980 1225 supdrvSessionRelease(pSession); 981 1226 if (RT_SUCCESS(rc)) … … 1725 1970 RT_NOREF2(pDevExt, pSession); 1726 1971 #endif 1972 #ifdef VBOXDRV_WITH_SID_TO_UID_MAPPING 1973 if (pSession->pNtUserId) 1974 { 1975 supdrvNtUserIdRelease(pSession->pNtUserId); 1976 pSession->pNtUserId = NULL; 1977 } 1978 #endif 1727 1979 } 1728 1980
Note:
See TracChangeset
for help on using the changeset viewer.