Changeset 76091 in vbox for trunk/src/VBox/Main/src-server
- Timestamp:
- Dec 9, 2018 11:02:49 PM (6 years ago)
- Location:
- trunk/src/VBox/Main/src-server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
r75663 r76091 29 29 #include <iprt/string.h> 30 30 #include <iprt/stream.h> 31 #include <iprt/system.h> 31 32 #include <iprt/thread.h> 32 33 #include <iprt/uuid.h> … … 172 173 //////////////////////////////////////////////////////////////////////////////// 173 174 175 #if defined(RT_OS_WINDOWS) && defined(VBOXSVC_WITH_CLIENT_WATCHER) 176 /** 177 * Client process watcher data. 178 */ 179 class WatchedClientProcess 180 { 181 public: 182 WatchedClientProcess(RTPROCESS a_pid, HANDLE a_hProcess) RT_NOEXCEPT 183 : m_pid(a_pid) 184 , m_cRefs(1) 185 , m_hProcess(a_hProcess) 186 { 187 } 188 189 ~WatchedClientProcess() 190 { 191 if (m_hProcess != NULL) 192 { 193 ::CloseHandle(m_hProcess); 194 m_hProcess = NULL; 195 } 196 m_pid = NIL_RTPROCESS; 197 } 198 199 /** The client PID. */ 200 RTPROCESS m_pid; 201 /** Number of references to this structure. */ 202 uint32_t volatile m_cRefs; 203 /** Handle of the client process. 204 * Ideally, we've got full query privileges, but we'll settle for waiting. */ 205 HANDLE m_hProcess; 206 }; 207 typedef std::map<RTPROCESS, WatchedClientProcess *> WatchedClientProcessMap; 208 #endif 209 210 174 211 typedef ObjectsList<Medium> MediaOList; 175 212 typedef ObjectsList<GuestOSType> GuestOSTypesOList; … … 181 218 typedef std::map<Guid, ComObjPtr<Medium> > HardDiskMap; 182 219 220 183 221 /** 184 222 * Main VirtualBox data structure. … … 189 227 { 190 228 Data() 191 : pMainConfigFile(NULL), 192 uuidMediaRegistry("48024e5c-fdd9-470f-93af-ec29f7ea518c"), 193 uRegistryNeedsSaving(0), 194 lockMachines(LOCKCLASS_LISTOFMACHINES), 195 allMachines(lockMachines), 196 lockGuestOSTypes(LOCKCLASS_LISTOFOTHEROBJECTS), 197 allGuestOSTypes(lockGuestOSTypes), 198 lockMedia(LOCKCLASS_LISTOFMEDIA), 199 allHardDisks(lockMedia), 200 allDVDImages(lockMedia), 201 allFloppyImages(lockMedia), 202 lockSharedFolders(LOCKCLASS_LISTOFOTHEROBJECTS), 203 allSharedFolders(lockSharedFolders), 204 lockDHCPServers(LOCKCLASS_LISTOFOTHEROBJECTS), 205 allDHCPServers(lockDHCPServers), 206 lockNATNetworks(LOCKCLASS_LISTOFOTHEROBJECTS), 207 allNATNetworks(lockNATNetworks), 208 mtxProgressOperations(LOCKCLASS_PROGRESSLIST), 209 pClientWatcher(NULL), 210 threadAsyncEvent(NIL_RTTHREAD), 211 pAsyncEventQ(NULL), 212 pAutostartDb(NULL), 213 fSettingsCipherKeySet(false) 214 { 229 : pMainConfigFile(NULL) 230 , uuidMediaRegistry("48024e5c-fdd9-470f-93af-ec29f7ea518c") 231 , uRegistryNeedsSaving(0) 232 , lockMachines(LOCKCLASS_LISTOFMACHINES) 233 , allMachines(lockMachines) 234 , lockGuestOSTypes(LOCKCLASS_LISTOFOTHEROBJECTS) 235 , allGuestOSTypes(lockGuestOSTypes) 236 , lockMedia(LOCKCLASS_LISTOFMEDIA) 237 , allHardDisks(lockMedia) 238 , allDVDImages(lockMedia) 239 , allFloppyImages(lockMedia) 240 , lockSharedFolders(LOCKCLASS_LISTOFOTHEROBJECTS) 241 , allSharedFolders(lockSharedFolders) 242 , lockDHCPServers(LOCKCLASS_LISTOFOTHEROBJECTS) 243 , allDHCPServers(lockDHCPServers) 244 , lockNATNetworks(LOCKCLASS_LISTOFOTHEROBJECTS) 245 , allNATNetworks(lockNATNetworks) 246 , mtxProgressOperations(LOCKCLASS_PROGRESSLIST) 247 , pClientWatcher(NULL) 248 , threadAsyncEvent(NIL_RTTHREAD) 249 , pAsyncEventQ(NULL) 250 , pAutostartDb(NULL) 251 , fSettingsCipherKeySet(false) 252 #if defined(RT_OS_WINDOWS) && defined(VBOXSVC_WITH_CLIENT_WATCHER) 253 , fWatcherIsReliable(RTSystemGetNtVersion() >= RTSYSTEM_MAKE_NT_VERSION(6, 0, 0)) 254 #endif 255 { 256 #if defined(RT_OS_WINDOWS) && defined(VBOXSVC_WITH_CLIENT_WATCHER) 257 RTCritSectRwInit(&WatcherCritSect); 258 #endif 215 259 } 216 260 … … 310 354 bool fSettingsCipherKeySet; 311 355 uint8_t SettingsCipherKey[RTSHA512_HASH_SIZE]; 356 357 #if defined(RT_OS_WINDOWS) && defined(VBOXSVC_WITH_CLIENT_WATCHER) 358 /** Critical section protecting WatchedProcesses. */ 359 RTCRITSECTRW WatcherCritSect; 360 /** Map of processes being watched, key is the PID. */ 361 WatchedClientProcessMap WatchedProcesses; 362 /** Set if the watcher is reliable, otherwise cleared. 363 * The watcher goes unreliable when we run out of memory, fail open a client 364 * process, or if the watcher thread gets messed up. */ 365 bool fWatcherIsReliable; 366 #endif 312 367 }; 313 368 … … 5552 5607 #endif /* !RT_OS_WINDOWS */ 5553 5608 5609 #if defined(RT_OS_WINDOWS) && defined(VBOXSVC_WITH_CLIENT_WATCHER) 5610 5611 # include <psapi.h> /* for GetProcessImageFileNameW */ 5612 5613 /** 5614 * Callout from the wrapper. 5615 */ 5616 void VirtualBox::i_callHook(const char *a_pszFunction) 5617 { 5618 RT_NOREF(a_pszFunction); 5619 5620 /* 5621 * Let'see figure out who is calling. 5622 * Note! Requires Vista+, so skip this entirely on older systems. 5623 */ 5624 if (RTSystemGetNtVersion() >= RTSYSTEM_MAKE_NT_VERSION(6, 0, 0)) 5625 { 5626 RPC_CALL_ATTRIBUTES_V2_W CallAttribs = { RPC_CALL_ATTRIBUTES_VERSION, RPC_QUERY_CLIENT_PID | RPC_QUERY_IS_CLIENT_LOCAL }; 5627 RPC_STATUS rcRpc = RpcServerInqCallAttributesW(NULL, &CallAttribs); 5628 if ( rcRpc == RPC_S_OK 5629 && CallAttribs.ClientPID != 0) 5630 { 5631 RTPROCESS const pidClient = (RTPROCESS)(uintptr_t)CallAttribs.ClientPID; 5632 if (pidClient != RTProcSelf()) 5633 { 5634 /** @todo LogRel2 later: */ 5635 LogRel(("i_callHook: %Rfn [ClientPID=%#zx/%zu IsClientLocal=%d ProtocolSequence=%#x CallStatus=%#x CallType=%#x OpNum=%#x InterfaceUuid=%RTuuid]\n", 5636 a_pszFunction, CallAttribs.ClientPID, CallAttribs.ClientPID, CallAttribs.IsClientLocal, 5637 CallAttribs.ProtocolSequence, CallAttribs.CallStatus, CallAttribs.CallType, CallAttribs.OpNum, 5638 &CallAttribs.InterfaceUuid)); 5639 5640 /* 5641 * Do we know this client PID already? 5642 */ 5643 RTCritSectRwEnterShared(&m->WatcherCritSect); 5644 WatchedClientProcessMap::iterator It = m->WatchedProcesses.find(pidClient); 5645 if (It != m->WatchedProcesses.end()) 5646 RTCritSectRwLeaveShared(&m->WatcherCritSect); /* Known process, nothing to do. */ 5647 else 5648 { 5649 /* This is a new client process, start watching it. */ 5650 RTCritSectRwLeaveShared(&m->WatcherCritSect); 5651 i_watchClientProcess(pidClient, a_pszFunction); 5652 } 5653 } 5654 } 5655 else 5656 LogRel(("i_callHook: %Rfn - rcRpc=%#x ClientPID=%#zx/%zu !! [IsClientLocal=%d ProtocolSequence=%#x CallStatus=%#x CallType=%#x OpNum=%#x InterfaceUuid=%RTuuid]\n", 5657 a_pszFunction, rcRpc, CallAttribs.ClientPID, CallAttribs.ClientPID, CallAttribs.IsClientLocal, 5658 CallAttribs.ProtocolSequence, CallAttribs.CallStatus, CallAttribs.CallType, CallAttribs.OpNum, 5659 &CallAttribs.InterfaceUuid)); 5660 } 5661 } 5662 5663 5664 /** 5665 * Wathces @a a_pidClient for termination. 5666 * 5667 * @returns true if successfully enabled watching of it, false if not. 5668 * @param a_pidClient The PID to watch. 5669 * @param a_pszFunction The function we which we detected the client in. 5670 */ 5671 bool VirtualBox::i_watchClientProcess(RTPROCESS a_pidClient, const char *a_pszFunction) 5672 { 5673 RT_NOREF_PV(a_pszFunction); 5674 5675 /* 5676 * Open the client process. 5677 */ 5678 HANDLE hClient = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE /*fInherit*/, a_pidClient); 5679 if (hClient == NULL) 5680 hClient = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION, FALSE , a_pidClient); 5681 if (hClient == NULL) 5682 hClient = OpenProcess(SYNCHRONIZE, FALSE , a_pidClient); 5683 AssertLogRelMsgReturn(hClient != NULL, ("pidClient=%d (%#x) err=%d\n", a_pidClient, a_pidClient, GetLastError()), 5684 m->fWatcherIsReliable = false); 5685 5686 /* 5687 * Create a new watcher structure and try add it to the map. 5688 */ 5689 bool fRet = true; 5690 WatchedClientProcess *pWatched = new (std::nothrow) WatchedClientProcess(a_pidClient, hClient); 5691 if (pWatched) 5692 { 5693 RTCritSectRwEnterExcl(&m->WatcherCritSect); 5694 5695 WatchedClientProcessMap::iterator It = m->WatchedProcesses.find(a_pidClient); 5696 if (It == m->WatchedProcesses.end()) 5697 { 5698 try 5699 { 5700 m->WatchedProcesses.insert(WatchedClientProcessMap::value_type(a_pidClient, pWatched)); 5701 } 5702 catch (std::bad_alloc &) 5703 { 5704 fRet = false; 5705 } 5706 if (fRet) 5707 { 5708 /* 5709 * Schedule it on a watcher thread. 5710 */ 5711 /** @todo later. */ 5712 RTCritSectRwLeaveExcl(&m->WatcherCritSect); 5713 } 5714 else 5715 { 5716 RTCritSectRwLeaveExcl(&m->WatcherCritSect); 5717 delete pWatched; 5718 LogRel(("VirtualBox::i_watchClientProcess: out of memory inserting into client map!\n")); 5719 } 5720 } 5721 else 5722 { 5723 /* 5724 * Someone raced us here, we lost. 5725 */ 5726 RTCritSectRwLeaveExcl(&m->WatcherCritSect); 5727 delete pWatched; 5728 } 5729 } 5730 else 5731 { 5732 LogRel(("VirtualBox::i_watchClientProcess: out of memory!\n")); 5733 CloseHandle(hClient); 5734 m->fWatcherIsReliable = fRet = false; 5735 } 5736 return fRet; 5737 } 5738 5739 5740 /** Logs the RPC caller info to the release log. */ 5741 /*static*/ void VirtualBox::i_logCaller(const char *a_pszFormat, ...) 5742 { 5743 if (RTSystemGetNtVersion() >= RTSYSTEM_MAKE_NT_VERSION(6, 0, 0)) 5744 { 5745 char szTmp[80]; 5746 va_list va; 5747 va_start(va, a_pszFormat); 5748 RTStrPrintfV(szTmp, sizeof(szTmp), a_pszFormat, va); 5749 va_end(va); 5750 5751 RPC_CALL_ATTRIBUTES_V2_W CallAttribs = { RPC_CALL_ATTRIBUTES_VERSION, RPC_QUERY_CLIENT_PID | RPC_QUERY_IS_CLIENT_LOCAL }; 5752 RPC_STATUS rcRpc = RpcServerInqCallAttributesW(NULL, &CallAttribs); 5753 5754 RTUTF16 wszProcName[256]; 5755 wszProcName[0] = '\0'; 5756 if (rcRpc == 0 && CallAttribs.ClientPID != 0) 5757 { 5758 HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)(uintptr_t)CallAttribs.ClientPID); 5759 if (hProcess) 5760 { 5761 RT_ZERO(wszProcName); 5762 GetProcessImageFileNameW(hProcess, wszProcName, RT_ELEMENTS(wszProcName) - 1); 5763 CloseHandle(hProcess); 5764 } 5765 } 5766 LogRel(("%s [rcRpc=%#x ClientPID=%#zx/%zu (%ls) IsClientLocal=%d ProtocolSequence=%#x CallStatus=%#x CallType=%#x OpNum=%#x InterfaceUuid=%RTuuid]\n", 5767 szTmp, rcRpc, CallAttribs.ClientPID, CallAttribs.ClientPID, wszProcName, CallAttribs.IsClientLocal, 5768 CallAttribs.ProtocolSequence, CallAttribs.CallStatus, CallAttribs.CallType, CallAttribs.OpNum, 5769 &CallAttribs.InterfaceUuid)); 5770 } 5771 } 5772 5773 #endif /* RT_OS_WINDOWS && VBOXSVC_WITH_CLIENT_WATCHER */ 5774 5775 5554 5776 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/src-server/win/svcmain.cpp
r76071 r76091 553 553 } 554 554 555 #ifdef DEBUG_bird556 # include <psapi.h> /* for GetProcessImageFileNameW */557 558 /** Logs the RPC caller info to the release log. */559 static void logCaller(const char *pszFormat, ...)560 {561 char szTmp[80];562 va_list va;563 va_start(va, pszFormat);564 RTStrPrintfV(szTmp, sizeof(szTmp), pszFormat, va);565 va_end(va);566 567 RPC_CALL_ATTRIBUTES_V2_W CallAttribs = { RPC_CALL_ATTRIBUTES_VERSION, RPC_QUERY_CLIENT_PID | RPC_QUERY_IS_CLIENT_LOCAL };568 RPC_STATUS rcRpc = RpcServerInqCallAttributesW(NULL, &CallAttribs);569 570 RTUTF16 wszProcName[256];571 wszProcName[0] = '\0';572 if (rcRpc == 0 && CallAttribs.ClientPID != 0)573 {574 HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, (DWORD)(uintptr_t)CallAttribs.ClientPID);575 if (hProcess)576 {577 RT_ZERO(wszProcName);578 GetProcessImageFileNameW(hProcess, wszProcName, RT_ELEMENTS(wszProcName) - 1);579 CloseHandle(hProcess);580 }581 }582 LogRel(("%s [rcRpc=%#x ClientPID=%#zx/%zu (%ls) IsClientLocal=%d ProtocolSequence=%#x CallStatus=%#x CallType=%#x OpNum=%#x InterfaceUuid=%RTuuid]\n",583 szTmp, rcRpc, CallAttribs.ClientPID, CallAttribs.ClientPID, wszProcName, CallAttribs.IsClientLocal,584 CallAttribs.ProtocolSequence, CallAttribs.CallStatus, CallAttribs.CallType, CallAttribs.OpNum,585 &CallAttribs.InterfaceUuid));586 }587 555 588 556 /** 589 * Caller watcher wrapper exploration wrapping CComObjectCached. 590 * @sa @bugref{3300} 557 * Custom instantiation of CComObjectCached. 558 * 559 * This catches certain QueryInterface callers for the purpose of watching for 560 * abnormal client process termination (@bugref{3300}). 561 * 562 * @todo just merge this into class VirtualBox VirtualBoxImpl.h 591 563 */ 592 template <class Base> class DebugWatcher : public Base 564 class VirtualBoxObjectCached : public VirtualBox 593 565 { 594 566 public: 595 DebugWatcher(void *a_pWhatever = NULL) : Base(a_pWhatever) 596 { 597 } 598 599 virtual ~DebugWatcher() 600 { 601 } 567 VirtualBoxObjectCached(void * = NULL) 568 : VirtualBox() 569 { 570 } 571 572 virtual ~VirtualBoxObjectCached() 573 { 574 m_iRef = LONG_MIN / 2; /* Catch refcount screwups by setting refcount something insane. */ 575 FinalRelease(); 576 } 577 578 /** @name IUnknown implementation for VirtualBox 579 * @{ */ 602 580 603 581 STDMETHOD_(ULONG, AddRef)() throw() 604 582 { 605 ULONG cRefs = Base::AddRef(); 606 logCaller("AddRef -> %u", cRefs); 583 ULONG cRefs = InternalAddRef(); 584 if (cRefs == 2) 585 { 586 AssertMsg(ATL::_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n")); 587 ATL::_pAtlModule->Lock(); 588 } 607 589 return cRefs; 608 590 } … … 610 592 STDMETHOD_(ULONG, Release)() throw() 611 593 { 612 ULONG cRefs = Base::Release(); 613 logCaller("Release -> %u", cRefs); 594 ULONG cRefs = InternalRelease(); 595 if (cRefs == 0) 596 delete this; 597 else if (cRefs == 1) 598 { 599 AssertMsg(ATL::_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n")); 600 ATL::_pAtlModule->Unlock(); 601 } 614 602 return cRefs; 615 603 } … … 617 605 STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj) throw() 618 606 { 619 HRESULT hrc = Base::QueryInterface(iid, ppvObj); 620 logCaller("QueryInterface %RTuuid -> %Rhrc %p", iid, hrc, *ppvObj); 607 HRESULT hrc = _InternalQueryInterface(iid, ppvObj); 608 #ifdef VBOXSVC_WITH_CLIENT_WATCHER 609 i_logCaller("QueryInterface %RTuuid -> %Rhrc %p", &iid, hrc, *ppvObj); 610 #endif 621 611 return hrc; 622 612 } 623 613 624 static HRESULT WINAPI CreateInstance(DebugWatcher<Base> **pp) throw() 625 { 626 AssertReturn(pp, E_POINTER); 627 *pp = NULL; 614 /** @} */ 615 616 static HRESULT WINAPI CreateInstance(VirtualBoxObjectCached **ppObj) throw() 617 { 618 AssertReturn(ppObj, E_POINTER); 619 *ppObj = NULL; 628 620 629 621 HRESULT hrc = E_OUTOFMEMORY; 630 DebugWatcher<Base> *p = new (std::nothrow) DebugWatcher<Base>();622 VirtualBoxObjectCached *p = new (std::nothrow) VirtualBoxObjectCached(); 631 623 if (p) 632 624 { … … 640 632 delete p; 641 633 else 642 *pp = p;634 *ppObj = p; 643 635 } 644 636 return hrc; 645 637 } 646 647 638 }; 648 639 649 #endif /* DEBUG_bird */650 640 651 641 /** … … 664 654 STDMETHODIMP VirtualBoxClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj) 665 655 { 666 # ifdef DEBUG_bird667 logCaller("VirtualBoxClassFactory::CreateInstance: %RTuuid", riid);656 # ifdef VBOXSVC_WITH_CLIENT_WATCHER 657 VirtualBox::i_logCaller("VirtualBoxClassFactory::CreateInstance: %RTuuid", riid); 668 658 # endif 669 659 HRESULT hrc = E_POINTER; … … 703 693 { 704 694 ATL::_pAtlModule->Lock(); 705 #ifdef DEBUG_bird 706 DebugWatcher<ATL::CComObjectCached<VirtualBox>> *p; 707 m_hrcCreate = hrc = DebugWatcher<ATL::CComObjectCached<VirtualBox>>::CreateInstance(&p); 708 #else 709 ATL::CComObjectCached<VirtualBox> *p; 710 m_hrcCreate = hrc = ATL::CComObjectCached<VirtualBox>::CreateInstance(&p); 711 #endif 695 VirtualBoxObjectCached *p; 696 m_hrcCreate = hrc = VirtualBoxObjectCached::CreateInstance(&p); 712 697 if (SUCCEEDED(hrc)) 713 698 {
Note:
See TracChangeset
for help on using the changeset viewer.