OHCI 관련 취약점 내용이 있어서 간단 정리함.
int vusbUrbSubmit(PVUSBURB pUrb)
{
...
/*
* Check that the device is in a valid state.
*/
const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
if (enmState == VUSB_DEVICE_STATE_RESET)
{
LogRel(("VUSB: %s: power off ignored, the device is resetting!\n", pDev->pUsbIns->pszName));
pUrb->enmStatus = VUSBSTATUS_DNR;
/* This will postpone the TDs until we're done with the resetting. */
return VERR_VUSB_DEVICE_IS_RESETTING;
}
...
if (pUrb->EndPt >= VUSB_PIPE_MAX)
{
Log(("%s: pDev=%p[%s]: SUBMIT: ep %i >= %i!!!\n", pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, pUrb->EndPt, VUSB_PIPE_MAX));
return vusbUrbSubmitHardError(pUrb);
}
...
if (!pEndPtDesc)
{
Log(("%s: pDev=%p[%s]: SUBMIT: no endpoint!!! dir=%s e=%i\n",
pUrb->pszDesc, pDev, pDev->pUsbIns->pszName, vusbUrbDirName(pUrb->enmDir), pUrb->EndPt));
return vusbUrbSubmitHardError(pUrb);
}
...
pUrb->enmState = VUSBURBSTATE_IN_FLIGHT;
switch (pUrb->enmType)
{
case VUSBXFERTYPE_CTRL:
rc = vusbUrbSubmitCtrl(pUrb); //여기서 터지는 취약점임.
break;
case VUSBXFERTYPE_BULK:
rc = vusbUrbSubmitBulk(pUrb);
break;
case VUSBXFERTYPE_INTR:
rc = vusbUrbSubmitInterrupt(pUrb);
break;
case VUSBXFERTYPE_ISOC:
rc = vusbUrbSubmitIsochronous(pUrb);
break;
default:
AssertMsgFailed(("Unexpected pUrb type %d\n", pUrb->enmType));
return vusbUrbSubmitHardError(pUrb);
}
...
else if ( RT_FAILURE(rc)
&& !ASMAtomicReadU32(&pDev->aPipes[pUrb->EndPt].async)
/* && pUrb->enmType == VUSBXFERTYPE_BULK ?? */
&& !vusbUrbErrorRh(pUrb))
{
/* don't retry it anymore. */
pUrb->enmState = VUSBURBSTATE_REAPED;
pUrb->enmStatus = VUSBSTATUS_CRC;
vusbUrbCompletionRh(pUrb);
return VINF_SUCCESS;
}
return rc;
}
C++
복사
CVE-2020-2674 분석글에서 URB 패킷이 결국 전송될때 vusbUrbSubmit() 함수에 의해서 처리되고 OHCI 분석글에서 전송 종류가 4가지라고 했는데, 그에 따른 처리 로직이 switch-case에서 수행된다.
CVE-2020-2525 에서는 제일 복잡하다고 했던 전송처리 로직인 컨트롤 어쩌구에서 발생하는 취약점이다.
초기화 되지 않은 영역을 할당받게 되고 힙 스프레이를 이용해서 fake 객체를 할당받게 한뒤, RIP 컨트롤로 이어지게끔 할수 있다.