Changeset 78088 in vbox
- Timestamp:
- Apr 10, 2019 1:36:19 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 129944
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/com.h
r76585 r78088 39 39 { 40 40 41 /** @name VBOX_COM_INIT_F_XXX - flags for com::Initialize(). 42 * @{ */ 43 /** Windows: Caller is the GUI and needs a STA rather than MTA apartment. */ 44 #define VBOX_COM_INIT_F_GUI RT_BIT_32(0) 45 /** Windows: Auto registration updating, if privileged enough. */ 46 #define VBOX_COM_INIT_F_AUTO_REG_UPDATE RT_BIT_32(1) 47 /** Windows: Opt-out of COM patching (client code should do this). */ 48 #define VBOX_COM_INIT_F_NO_COM_PATCHING RT_BIT_32(2) 49 /** The default flags. */ 50 #define VBOX_COM_INIT_F_DEFAULT (VBOX_COM_INIT_F_AUTO_REG_UPDATE) 51 /** @} */ 52 41 53 /** 42 54 * Initializes the COM runtime. … … 46 58 * @param fGui if call is performed on the GUI thread 47 59 * @param fAutoRegUpdate if to do auto MS COM registration updates. 60 * @param fNoComPatching Set this to skip the COM patching. 48 61 * @return COM result code 49 62 */ 50 HRESULT Initialize( bool fGui = false, bool fAutoRegUpdate = true);63 HRESULT Initialize(uint32_t fInitFlags = VBOX_COM_INIT_F_DEFAULT); 51 64 52 65 /** … … 114 127 PRTERRINFO pErrInfo); 115 128 129 #ifdef RT_OS_WINDOWS 130 void PatchComBugs(void); 131 #endif 132 116 133 } /* namespace com */ 117 134 -
trunk/src/VBox/Frontends/VBoxBugReport/VBoxBugReport.cpp
r76553 r78088 737 737 throw RTCError("Out of memory\n"); 738 738 739 handleComError(com::Initialize( ), "Failed to initialize COM");739 handleComError(com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING), "Failed to initialize COM"); 740 740 741 741 MachineInfoList list; -
trunk/src/VBox/Frontends/VirtualBox/src/globals/COMDefs.cpp
r76606 r78088 90 90 LogFlowFuncEnter(); 91 91 92 HRESULT rc = com::Initialize(fGui );92 HRESULT rc = com::Initialize(fGui ? VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_GUI : VBOX_COM_INIT_F_DEFAULT); 93 93 94 94 #if defined (VBOX_WITH_XPCOM) -
trunk/src/VBox/Main/cbinding/VBoxCAPI.cpp
r76553 r78088 394 394 sessionIID = IID_ISession; 395 395 396 HRESULT rc = com::Initialize( );396 HRESULT rc = com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING); 397 397 if (FAILED(rc)) 398 398 { … … 669 669 virtualBoxClientIID = IID_IVirtualBoxClient; 670 670 671 HRESULT rc = com::Initialize( );671 HRESULT rc = com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING); 672 672 if (FAILED(rc)) 673 673 { … … 728 728 VBoxClientThreadInitialize(void) 729 729 { 730 return com::Initialize( );730 return com::Initialize(VBOX_COM_INIT_F_DEFAULT | VBOX_COM_INIT_F_NO_COM_PATCHING); 731 731 } 732 732 -
trunk/src/VBox/Main/glue/initterm.cpp
r76592 r78088 19 19 #if !defined(VBOX_WITH_XPCOM) 20 20 21 # if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x600 22 # undef _WIN32_WINNT 23 # define _WIN32_WINNT 0x600 /* GetModuleHandleExW */ 24 # endif 21 25 # include <iprt/nt/nt-and-windows.h> 22 26 # include <iprt/win/objbase.h> 27 # include <iprt/win/rpcproxy.h> 28 # include <rpcasync.h> 23 29 24 30 #else /* !defined(VBOX_WITH_XPCOM) */ … … 51 57 #include <iprt/path.h> 52 58 #include <iprt/string.h> 59 #include <iprt/system.h> 53 60 #include <iprt/thread.h> 54 61 … … 192 199 193 200 /** 201 * Replacement function for the InvokeStub method for the IRundown stub. 202 */ 203 static HRESULT STDMETHODCALLTYPE Rundown_InvokeStub(IRpcStubBuffer *pThis, RPCOLEMESSAGE *pMsg, IRpcChannelBuffer *pBuf) 204 { 205 /* 206 * Our mission here is to prevent remote calls to methods #8 and #9, 207 * as these contain raw pointers to callback functions. 208 * 209 * Note! APIs like I_RpcServerInqTransportType, I_RpcBindingInqLocalClientPID 210 * and RpcServerInqCallAttributesW are not usable in this context without 211 * a rpc binding handle (latter two). 212 * 213 * P.S. In more recent windows versions, the buffer implements a interface 214 * IID_IRpcChannelBufferMarshalingContext (undocumented) which has a 215 * GetIMarshallingContextAttribute() method that will return the client PID 216 * when asking for attribute #0x8000000e. 217 */ 218 uint32_t const iMethod = pMsg->iMethod & 0xffff; /* Uncertain, but there are hints that the upper bits are flags. */ 219 HRESULT hrc; 220 if ( ( iMethod != 8 221 && iMethod != 9) 222 || (pMsg->rpcFlags & RPCFLG_LOCAL_CALL) ) 223 hrc = CStdStubBuffer_Invoke(pThis, pMsg, pBuf); 224 else 225 { 226 LogRel(("Rundown_InvokeStub: Rejected call to CRundown::%s: rpcFlags=%#x cbBuffer=%#x dataRepresentation=%d buffer=%p:{%.*Rhxs} reserved1=%p reserved2={%p,%p,%p,%p,%p}\n", 227 pMsg->iMethod == 8 ? "DoCallback" : "DoNonreentrantCallback", pMsg->rpcFlags, pMsg->cbBuffer, 228 pMsg->dataRepresentation, pMsg->Buffer, RT_VALID_PTR(pMsg->Buffer) ? pMsg->cbBuffer : 0, pMsg->Buffer, 229 pMsg->reserved1, pMsg->reserved2[0], pMsg->reserved2[1], pMsg->reserved2[2], pMsg->reserved2[3], pMsg->reserved2[4])); 230 hrc = E_ACCESSDENIED; 231 } 232 return hrc; 233 } 234 235 /** 236 * Replaces the IRundown InvokeStub method with Rundown_InvokeStub so we can 237 * reject remote calls to a couple of misdesigned methods. 238 */ 239 void PatchComBugs(void) 240 { 241 static volatile bool s_fPatched = false; 242 if (s_fPatched) 243 return; 244 245 /* 246 * The combase.dll / ole32.dll is exporting a DllGetClassObject function 247 * that is implemented using NdrDllGetClassObject just like our own 248 * proxy/stub DLL. This means we can get at the stub interface lists, 249 * since what NdrDllGetClassObject has CStdPSFactoryBuffer as layout. 250 * 251 * Note! Tried using CoRegisterPSClsid instead of this mess, but no luck. 252 */ 253 /* Locate the COM DLL, it must be loaded by now: */ 254 HMODULE hmod = GetModuleHandleW(L"COMBASE.DLL"); 255 if (!hmod) 256 hmod = GetModuleHandleW(L"OLE32.DLL"); /* w7 */ 257 AssertReturnVoid(hmod != NULL); 258 259 /* Resolve the class getter: */ 260 LPFNGETCLASSOBJECT pfnGetClassObject = (LPFNGETCLASSOBJECT)GetProcAddress(hmod, "DllGetClassObject"); 261 AssertReturnVoid(pfnGetClassObject != NULL); 262 263 /* Get the factory instance: */ 264 static const CLSID s_PSOlePrx32ClsId = {0x00000320,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; 265 CStdPSFactoryBuffer *pFactoryBuffer = NULL; 266 HRESULT hrc = pfnGetClassObject(s_PSOlePrx32ClsId, IID_IPSFactoryBuffer, (void **)&pFactoryBuffer); 267 AssertMsgReturnVoid(SUCCEEDED(hrc), ("hrc=%Rhrc\n", hrc)); 268 AssertReturnVoid(pFactoryBuffer != NULL); 269 270 /* 271 * Search thru the file list for the interface we want to patch. 272 */ 273 static const IID s_IID_Rundown = {0x00000134,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; 274 decltype(CStdStubBuffer_Invoke) *pfnInvoke = (decltype(pfnInvoke))GetProcAddress(hmod, "CStdStubBuffer_Invoke"); 275 if (!pfnInvoke) 276 pfnInvoke = (decltype(pfnInvoke))GetProcAddress(GetModuleHandleW(L"RPCRT4.DLL"), "CStdStubBuffer_Invoke"); 277 278 unsigned cPatched = 0; 279 unsigned cAlreadyPatched = 0; 280 Assert(pFactoryBuffer->pProxyFileList != NULL); 281 for (ProxyFileInfo const **ppCur = pFactoryBuffer->pProxyFileList; *ppCur != NULL; ppCur++) 282 { 283 ProxyFileInfo const *pCur = *ppCur; 284 285 if (pCur->pStubVtblList) 286 { 287 for (PCInterfaceStubVtblList const *ppCurStub = pCur->pStubVtblList; *ppCurStub != NULL; ppCurStub++) 288 { 289 PCInterfaceStubVtblList const pCurStub = *ppCurStub; 290 IID const *piid = pCurStub->header.piid; 291 if (piid) 292 { 293 if (IsEqualIID(*piid, s_IID_Rundown)) 294 { 295 if (pCurStub->Vtbl.Invoke == pfnInvoke) 296 { 297 DWORD fOld = 0; 298 if (VirtualProtect(&pCurStub->Vtbl.Invoke, sizeof(pCurStub->Vtbl.Invoke), PAGE_READWRITE, &fOld)) 299 { 300 pCurStub->Vtbl.Invoke = Rundown_InvokeStub; 301 VirtualProtect(&pCurStub->Vtbl.Invoke, sizeof(pCurStub->Vtbl.Invoke), fOld, &fOld); 302 cPatched++; 303 } 304 else 305 AssertMsgFailed(("%d\n", GetLastError())); 306 } 307 else 308 cAlreadyPatched++; 309 } 310 } 311 } 312 } 313 } 314 315 /* done */ 316 pFactoryBuffer->lpVtbl->Release((IPSFactoryBuffer *)pFactoryBuffer); 317 318 /* 319 * If we patched anything we should try prevent being unloaded. 320 */ 321 if (cPatched > 0) 322 { 323 s_fPatched = true; 324 HMODULE hmodSelf; 325 AssertLogRelMsg(GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, 326 (LPCWSTR)(uintptr_t)Rundown_InvokeStub, &hmodSelf), 327 ("last error: %u; Rundown_InvokeStub=%p\n", GetLastError(), Rundown_InvokeStub)); 328 } 329 else 330 AssertLogRelMsg(cAlreadyPatched > 0, ("COM patching of IRundown failed!\n")); 331 } 332 333 334 /** 194 335 * The COM main thread handle. (The first caller of com::Initialize().) 195 336 */ … … 239 380 * @return S_OK on success and a COM result code in case of failure. 240 381 */ 241 HRESULT Initialize( bool fGui /*= false*/, bool fAutoRegUpdate /*= true*/)382 HRESULT Initialize(uint32_t fInitFlags /*=VBOX_COM_INIT_F_DEFAULT*/) 242 383 { 243 384 HRESULT rc = E_FAIL; 244 NOREF(fAutoRegUpdate);245 385 246 386 #if !defined(VBOX_WITH_XPCOM) … … 252 392 * API users already active, as that could lead to a bit of a mess. 253 393 */ 254 if ( fAutoRegUpdate394 if ( (fInitFlags & VBOX_COM_INIT_F_AUTO_REG_UPDATE) 255 395 && gCOMMainThread == NIL_RTTHREAD) 256 396 { … … 303 443 * !!!!! Please think twice before touching this code !!!!! 304 444 */ 305 DWORD flags = fGui ? 306 COINIT_APARTMENTTHREADED 307 | COINIT_SPEED_OVER_MEMORY 308 : 309 COINIT_MULTITHREADED 310 | COINIT_DISABLE_OLE1DDE 311 | COINIT_SPEED_OVER_MEMORY; 445 DWORD flags = fInitFlags & VBOX_COM_INIT_F_GUI 446 ? COINIT_APARTMENTTHREADED 447 | COINIT_SPEED_OVER_MEMORY 448 : COINIT_MULTITHREADED 449 | COINIT_DISABLE_OLE1DDE 450 | COINIT_SPEED_OVER_MEMORY; 312 451 313 452 rc = CoInitializeEx(NULL, flags); … … 316 455 * "already initialized using the same apartment model") */ 317 456 AssertMsg(rc == S_OK || rc == S_FALSE, ("rc=%08X\n", rc)); 457 458 /* 459 * IRundown has unsafe two methods we need to patch to prevent remote access. 460 * Do that before we start using COM and open ourselves to possible attacks. 461 */ 462 if (!(fInitFlags & VBOX_COM_INIT_F_NO_COM_PATCHING)) 463 PatchComBugs(); 318 464 319 465 /* To be flow compatible with the XPCOM case, we return here if this isn't … … 328 474 fRc = false; 329 475 330 if (f Gui)476 if (fInitFlags & VBOX_COM_INIT_F_GUI) 331 477 Assert(RTThreadIsMain(hSelf)); 332 478 … … 350 496 351 497 /* Unused here */ 352 NOREF(fGui);498 RT_NOREF(fInitFlags); 353 499 354 500 if (ASMAtomicXchgBool(&gIsXPCOMInitialized, true) == true) -
trunk/src/VBox/Main/src-server/win/svcmain.cpp
r76592 r78088 945 945 "BU", "IL", "DI", "D", RTBldCfgVersion(), RTBldCfgRevision(), "BU", "IL", "DI", "D"); 946 946 947 int nRet = 0;948 HRESULT hRes = com::Initialize(f alse /*fGui*/, fRun /*fAutoRegUpdate*/);947 AssertCompile(VBOX_COM_INIT_F_DEFAULT == VBOX_COM_INIT_F_AUTO_REG_UPDATE); 948 HRESULT hRes = com::Initialize(fRun ? VBOX_COM_INIT_F_AUTO_REG_UPDATE : 0); 949 949 AssertLogRelMsg(SUCCEEDED(hRes), ("SVCMAIN: init failed: %Rhrc\n", hRes)); 950 950 … … 955 955 g_pModule->dwThreadID = GetCurrentThreadId(); 956 956 957 int nRet = 0; 957 958 if (!fRun) 958 959 {
Note:
See TracChangeset
for help on using the changeset viewer.