/** * Worker for VBoxDrvNtDeviceControl that takes the slow IOCtl functions. * * @returns NT status code. * * @param pDevObj Device object. * @param pSession The session. * @param pIrp Request packet. * @param pStack The stack location containing the DeviceControl parameters. */ static int VBoxDrvNtDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack) { NTSTATUS rcNt; unsigned cbOut = 0; int rc = 0; Log2(("VBoxDrvNtDeviceControlSlow(%p,%p): ioctl=%#x pBuf=%p cbIn=%#x cbOut=%#x pSession=%p\n", pDevExt, pIrp, pStack->Parameters.DeviceIoControl.IoControlCode, pIrp->AssociatedIrp.SystemBuffer, pStack->Parameters.DeviceIoControl.InputBufferLength, pStack->Parameters.DeviceIoControl.OutputBufferLength, pSession)); #ifdef RT_ARCH_AMD64 /* Don't allow 32-bit processes to do any I/O controls. */ if (!IoIs32bitProcess(pIrp)) #endif { /* Verify that it's a buffered CTL. */ if ((pStack->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED) { /* Verify that the sizes in the request header are correct. */ PSUPREQHDR pHdr = (PSUPREQHDR)pIrp->AssociatedIrp.SystemBuffer; if ( pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr) && pStack->Parameters.DeviceIoControl.InputBufferLength == pHdr->cbIn && pStack->Parameters.DeviceIoControl.OutputBufferLength == pHdr->cbOut) { /* * Do the job. */ rc = supdrvIOCtl(pStack->Parameters.DeviceIoControl.IoControlCode, pDevExt, pSession, pHdr); if (!rc) { rcNt = STATUS_SUCCESS; cbOut = pHdr->cbOut; if (cbOut > pStack->Parameters.DeviceIoControl.OutputBufferLength) { cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength; OSDBGPRINT(("VBoxDrvLinuxIOCtl: too much output! %#x > %#x; uCmd=%#x!\n", pHdr->cbOut, cbOut, pStack->Parameters.DeviceIoControl.IoControlCode)); } } else rcNt = STATUS_INVALID_PARAMETER; Log2(("VBoxDrvNtDeviceControlSlow: returns %#x cbOut=%d rc=%#x\n", rcNt, cbOut, rc)); } else { Log(("VBoxDrvNtDeviceControlSlow: Mismatching sizes (%#x) - Hdr=%#lx/%#lx Irp=%#lx/%#lx!\n", pStack->Parameters.DeviceIoControl.IoControlCode, pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr) ? pHdr->cbIn : 0, pStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(*pHdr) ? pHdr->cbOut : 0, pStack->Parameters.DeviceIoControl.InputBufferLength, pStack->Parameters.DeviceIoControl.OutputBufferLength)); rcNt = STATUS_INVALID_PARAMETER; } } else { Log(("VBoxDrvNtDeviceControlSlow: not buffered request (%#x) - not supported\n", pStack->Parameters.DeviceIoControl.IoControlCode)); rcNt = STATUS_NOT_SUPPORTED; } } #ifdef RT_ARCH_AMD64 else { Log(("VBoxDrvNtDeviceControlSlow: WOW64 req - not supported\n")); rcNt = STATUS_NOT_SUPPORTED; } #endif /* complete the request. */ pIrp->IoStatus.Status = rcNt; pIrp->IoStatus.Information = cbOut; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return rcNt; }
/** * Worker for VBoxSupDrvIOCtl that takes the slow IOCtl functions. * * @returns Solaris errno. * * @param pSession The session. * @param Cmd The IOCtl command. * @param Mode Information bitfield (for specifying ownership of data) * @param iArg User space address of the request buffer. */ static int VBoxDrvSolarisIOCtlSlow(PSUPDRVSESSION pSession, int iCmd, int Mode, intptr_t iArg) { int rc; uint32_t cbBuf = 0; union { SUPREQHDR Hdr; uint8_t abBuf[64]; } StackBuf; PSUPREQHDR pHdr; /* * Read the header. */ if (RT_UNLIKELY(IOCPARM_LEN(iCmd) != sizeof(StackBuf.Hdr))) { LogRel(("VBoxDrvSolarisIOCtlSlow: iCmd=%#x len %d expected %d\n", iCmd, IOCPARM_LEN(iCmd), sizeof(StackBuf.Hdr))); return EINVAL; } rc = ddi_copyin((void *)iArg, &StackBuf.Hdr, sizeof(StackBuf.Hdr), Mode); if (RT_UNLIKELY(rc)) { LogRel(("VBoxDrvSolarisIOCtlSlow: ddi_copyin(,%#lx,) failed; iCmd=%#x. rc=%d\n", iArg, iCmd, rc)); return EFAULT; } if (RT_UNLIKELY((StackBuf.Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) { LogRel(("VBoxDrvSolarisIOCtlSlow: bad header magic %#x; iCmd=%#x\n", StackBuf.Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK, iCmd)); return EINVAL; } cbBuf = RT_MAX(StackBuf.Hdr.cbIn, StackBuf.Hdr.cbOut); if (RT_UNLIKELY( StackBuf.Hdr.cbIn < sizeof(StackBuf.Hdr) || StackBuf.Hdr.cbOut < sizeof(StackBuf.Hdr) || cbBuf > _1M*16)) { LogRel(("VBoxDrvSolarisIOCtlSlow: max(%#x,%#x); iCmd=%#x\n", StackBuf.Hdr.cbIn, StackBuf.Hdr.cbOut, iCmd)); return EINVAL; } /* * Buffer the request. */ if (cbBuf <= sizeof(StackBuf)) pHdr = &StackBuf.Hdr; else { pHdr = RTMemTmpAlloc(cbBuf); if (RT_UNLIKELY(!pHdr)) { LogRel(("VBoxDrvSolarisIOCtlSlow: failed to allocate buffer of %d bytes for iCmd=%#x.\n", cbBuf, iCmd)); return ENOMEM; } } rc = ddi_copyin((void *)iArg, pHdr, cbBuf, Mode); if (RT_UNLIKELY(rc)) { LogRel(("VBoxDrvSolarisIOCtlSlow: copy_from_user(,%#lx, %#x) failed; iCmd=%#x. rc=%d\n", iArg, cbBuf, iCmd, rc)); if (pHdr != &StackBuf.Hdr) RTMemFree(pHdr); return EFAULT; } /* * Process the IOCtl. */ rc = supdrvIOCtl(iCmd, &g_DevExt, pSession, pHdr, cbBuf); /* * Copy ioctl data and output buffer back to user space. */ if (RT_LIKELY(!rc)) { uint32_t cbOut = pHdr->cbOut; if (RT_UNLIKELY(cbOut > cbBuf)) { LogRel(("VBoxDrvSolarisIOCtlSlow: too much output! %#x > %#x; iCmd=%#x!\n", cbOut, cbBuf, iCmd)); cbOut = cbBuf; } rc = ddi_copyout(pHdr, (void *)iArg, cbOut, Mode); if (RT_UNLIKELY(rc != 0)) { /* this is really bad */ LogRel(("VBoxDrvSolarisIOCtlSlow: ddi_copyout(,%p,%d) failed. rc=%d\n", (void *)iArg, cbBuf, rc)); rc = EFAULT; } } else rc = EINVAL; if (pHdr != &StackBuf.Hdr) RTMemTmpFree(pHdr); return rc; }
/** * Device I/O Control entry point. * * @param pFilp Associated file pointer. * @param uCmd The function specified to ioctl(). * @param ulArg The argument specified to ioctl(). * @param pSession The session instance. */ static int VBoxDrvLinuxIOCtlSlow(struct file *pFilp, unsigned int uCmd, unsigned long ulArg, PSUPDRVSESSION pSession) { int rc; SUPREQHDR Hdr; PSUPREQHDR pHdr; uint32_t cbBuf; Log6(("VBoxDrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p pid=%d/%d\n", pFilp, uCmd, (void *)ulArg, RTProcSelf(), current->pid)); /* * Read the header. */ if (RT_UNLIKELY(copy_from_user(&Hdr, (void *)ulArg, sizeof(Hdr)))) { Log(("VBoxDrvLinuxIOCtl: copy_from_user(,%#lx,) failed; uCmd=%#x\n", ulArg, uCmd)); return -EFAULT; } if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) { Log(("VBoxDrvLinuxIOCtl: bad header magic %#x; uCmd=%#x\n", Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK, uCmd)); return -EINVAL; } /* * Buffer the request. */ cbBuf = RT_MAX(Hdr.cbIn, Hdr.cbOut); if (RT_UNLIKELY(cbBuf > _1M*16)) { Log(("VBoxDrvLinuxIOCtl: too big cbBuf=%#x; uCmd=%#x\n", cbBuf, uCmd)); return -E2BIG; } if (RT_UNLIKELY(_IOC_SIZE(uCmd) ? cbBuf != _IOC_SIZE(uCmd) : Hdr.cbIn < sizeof(Hdr))) { Log(("VBoxDrvLinuxIOCtl: bad ioctl cbBuf=%#x _IOC_SIZE=%#x; uCmd=%#x\n", cbBuf, _IOC_SIZE(uCmd), uCmd)); return -EINVAL; } pHdr = RTMemAlloc(cbBuf); if (RT_UNLIKELY(!pHdr)) { OSDBGPRINT(("VBoxDrvLinuxIOCtl: failed to allocate buffer of %d bytes for uCmd=%#x\n", cbBuf, uCmd)); return -ENOMEM; } if (RT_UNLIKELY(copy_from_user(pHdr, (void *)ulArg, Hdr.cbIn))) { Log(("VBoxDrvLinuxIOCtl: copy_from_user(,%#lx, %#x) failed; uCmd=%#x\n", ulArg, Hdr.cbIn, uCmd)); RTMemFree(pHdr); return -EFAULT; } if (Hdr.cbIn < cbBuf) RT_BZERO((uint8_t *)pHdr + Hdr.cbIn, cbBuf - Hdr.cbIn); /* * Process the IOCtl. */ stac(); rc = supdrvIOCtl(uCmd, &g_DevExt, pSession, pHdr, cbBuf); clac(); /* * Copy ioctl data and output buffer back to user space. */ if (RT_LIKELY(!rc)) { uint32_t cbOut = pHdr->cbOut; if (RT_UNLIKELY(cbOut > cbBuf)) { OSDBGPRINT(("VBoxDrvLinuxIOCtl: too much output! %#x > %#x; uCmd=%#x!\n", cbOut, cbBuf, uCmd)); cbOut = cbBuf; } if (RT_UNLIKELY(copy_to_user((void *)ulArg, pHdr, cbOut))) { /* this is really bad! */ OSDBGPRINT(("VBoxDrvLinuxIOCtl: copy_to_user(%#lx,,%#x); uCmd=%#x!\n", ulArg, cbOut, uCmd)); rc = -EFAULT; } } else { Log(("VBoxDrvLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p failed, rc=%d\n", pFilp, uCmd, (void *)ulArg, rc)); rc = -EINVAL; } RTMemFree(pHdr); Log6(("VBoxDrvLinuxIOCtl: returns %d (pid=%d/%d)\n", rc, RTProcSelf(), current->pid)); return rc; }
/** * Deal with the 'slow' I/O control requests. * * @returns 0 on success, appropriate errno on failure. * @param pSession The session. * @param ulCmd The command. * @param pvData The request data. * @param pTd The calling thread. */ static int VBoxDrvFreeBSDIOCtlSlow(PSUPDRVSESSION pSession, u_long ulCmd, caddr_t pvData, struct thread *pTd) { PSUPREQHDR pHdr; uint32_t cbReq = IOCPARM_LEN(ulCmd); void *pvUser = NULL; /* * Buffered request? */ if ((IOC_DIRMASK & ulCmd) == IOC_INOUT) { pHdr = (PSUPREQHDR)pvData; if (RT_UNLIKELY(cbReq < sizeof(*pHdr))) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: cbReq=%#x < %#x; ulCmd=%#lx\n", cbReq, (int)sizeof(*pHdr), ulCmd)); return EINVAL; } if (RT_UNLIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: bad magic fFlags=%#x; ulCmd=%#lx\n", pHdr->fFlags, ulCmd)); return EINVAL; } if (RT_UNLIKELY( RT_MAX(pHdr->cbIn, pHdr->cbOut) != cbReq || pHdr->cbIn < sizeof(*pHdr) || pHdr->cbOut < sizeof(*pHdr))) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: max(%#x,%#x) != %#x; ulCmd=%#lx\n", pHdr->cbIn, pHdr->cbOut, cbReq, ulCmd)); return EINVAL; } } /* * Big unbuffered request? */ else if ((IOC_DIRMASK & ulCmd) == IOC_VOID && !cbReq) { /* * Read the header, validate it and figure out how much that needs to be buffered. */ SUPREQHDR Hdr; pvUser = *(void **)pvData; int rc = copyin(pvUser, &Hdr, sizeof(Hdr)); if (RT_UNLIKELY(rc)) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyin(%p,Hdr,) -> %#x; ulCmd=%#lx\n", pvUser, rc, ulCmd)); return rc; } if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: bad magic fFlags=%#x; ulCmd=%#lx\n", Hdr.fFlags, ulCmd)); return EINVAL; } cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut); if (RT_UNLIKELY( Hdr.cbIn < sizeof(Hdr) || Hdr.cbOut < sizeof(Hdr) || cbReq > _1M*16)) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: max(%#x,%#x); ulCmd=%#lx\n", Hdr.cbIn, Hdr.cbOut, ulCmd)); return EINVAL; } /* * Allocate buffer and copy in the data. */ pHdr = (PSUPREQHDR)RTMemTmpAlloc(cbReq); if (RT_UNLIKELY(!pHdr)) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: failed to allocate buffer of %d bytes; ulCmd=%#lx\n", cbReq, ulCmd)); return ENOMEM; } rc = copyin(pvUser, pHdr, Hdr.cbIn); if (RT_UNLIKELY(rc)) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyin(%p,%p,%#x) -> %#x; ulCmd=%#lx\n", pvUser, pHdr, Hdr.cbIn, rc, ulCmd)); RTMemTmpFree(pHdr); return rc; } } else { Log(("VBoxDrvFreeBSDIOCtlSlow: huh? cbReq=%#x ulCmd=%#lx\n", cbReq, ulCmd)); return EINVAL; } /* * Process the IOCtl. */ int rc = supdrvIOCtl(ulCmd, &g_VBoxDrvFreeBSDDevExt, pSession, pHdr); if (RT_LIKELY(!rc)) { /* * If unbuffered, copy back the result before returning. */ if (pvUser) { uint32_t cbOut = pHdr->cbOut; if (cbOut > cbReq) { OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbOut, cbReq, ulCmd)); cbOut = cbReq; } rc = copyout(pHdr, pvUser, cbOut); if (RT_UNLIKELY(rc)) OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyout(%p,%p,%#x) -> %d; uCmd=%#lx!\n", pHdr, pvUser, cbOut, rc, ulCmd)); Log(("VBoxDrvFreeBSDIOCtlSlow: returns %d / %d ulCmd=%lx\n", 0, pHdr->rc, ulCmd)); /* cleanup */ RTMemTmpFree(pHdr); } } else { /* * The request failed, just clean up. */ if (pvUser) RTMemTmpFree(pHdr); Log(("VBoxDrvFreeBSDIOCtlSlow: ulCmd=%lx pData=%p failed, rc=%d\n", ulCmd, pvData, rc)); rc = EINVAL; } return rc; }
/** * Worker for VBoxDrvDarwinIOCtl that takes the slow IOCtl functions. * * @returns Darwin errno. * * @param pSession The session. * @param iCmd The IOCtl command. * @param pData Pointer to the kernel copy of the SUPDRVIOCTLDATA buffer. * @param pProcess The calling process. */ static int VBoxDrvDarwinIOCtlSlow(PSUPDRVSESSION pSession, u_long iCmd, caddr_t pData, struct proc *pProcess) { LogFlow(("VBoxDrvDarwinIOCtlSlow: pSession=%p iCmd=%p pData=%p pProcess=%p\n", pSession, iCmd, pData, pProcess)); /* * Buffered or unbuffered? */ PSUPREQHDR pHdr; user_addr_t pUser = 0; void *pvPageBuf = NULL; uint32_t cbReq = IOCPARM_LEN(iCmd); if ((IOC_DIRMASK & iCmd) == IOC_INOUT) { pHdr = (PSUPREQHDR)pData; if (RT_UNLIKELY(cbReq < sizeof(*pHdr))) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: cbReq=%#x < %#x; iCmd=%#lx\n", cbReq, (int)sizeof(*pHdr), iCmd)); return EINVAL; } if (RT_UNLIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: bad magic fFlags=%#x; iCmd=%#lx\n", pHdr->fFlags, iCmd)); return EINVAL; } if (RT_UNLIKELY( RT_MAX(pHdr->cbIn, pHdr->cbOut) != cbReq || pHdr->cbIn < sizeof(*pHdr) || pHdr->cbOut < sizeof(*pHdr))) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: max(%#x,%#x) != %#x; iCmd=%#lx\n", pHdr->cbIn, pHdr->cbOut, cbReq, iCmd)); return EINVAL; } } else if ((IOC_DIRMASK & iCmd) == IOC_VOID && !cbReq) { /* * Get the header and figure out how much we're gonna have to read. */ SUPREQHDR Hdr; pUser = (user_addr_t)*(void **)pData; int rc = copyin(pUser, &Hdr, sizeof(Hdr)); if (RT_UNLIKELY(rc)) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyin(%llx,Hdr,) -> %#x; iCmd=%#lx\n", (unsigned long long)pUser, rc, iCmd)); return rc; } if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC)) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: bad magic fFlags=%#x; iCmd=%#lx\n", Hdr.fFlags, iCmd)); return EINVAL; } cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut); if (RT_UNLIKELY( Hdr.cbIn < sizeof(Hdr) || Hdr.cbOut < sizeof(Hdr) || cbReq > _1M*16)) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: max(%#x,%#x); iCmd=%#lx\n", Hdr.cbIn, Hdr.cbOut, iCmd)); return EINVAL; } /* * Allocate buffer and copy in the data. */ pHdr = (PSUPREQHDR)RTMemTmpAlloc(cbReq); if (!pHdr) pvPageBuf = pHdr = (PSUPREQHDR)IOMallocAligned(RT_ALIGN_Z(cbReq, PAGE_SIZE), 8); if (RT_UNLIKELY(!pHdr)) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: failed to allocate buffer of %d bytes; iCmd=%#lx\n", cbReq, iCmd)); return ENOMEM; } rc = copyin(pUser, pHdr, Hdr.cbIn); if (RT_UNLIKELY(rc)) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyin(%llx,%p,%#x) -> %#x; iCmd=%#lx\n", (unsigned long long)pUser, pHdr, Hdr.cbIn, rc, iCmd)); if (pvPageBuf) IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); else RTMemTmpFree(pHdr); return rc; } } else { Log(("VBoxDrvDarwinIOCtlSlow: huh? cbReq=%#x iCmd=%#lx\n", cbReq, iCmd)); return EINVAL; } /* * Process the IOCtl. */ int rc = supdrvIOCtl(iCmd, &g_DevExt, pSession, pHdr); if (RT_LIKELY(!rc)) { /* * If not buffered, copy back the buffer before returning. */ if (pUser) { uint32_t cbOut = pHdr->cbOut; if (cbOut > cbReq) { OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbOut, cbReq, iCmd)); cbOut = cbReq; } rc = copyout(pHdr, pUser, cbOut); if (RT_UNLIKELY(rc)) OSDBGPRINT(("VBoxDrvDarwinIOCtlSlow: copyout(%p,%llx,%#x) -> %d; uCmd=%#lx!\n", pHdr, (unsigned long long)pUser, cbOut, rc, iCmd)); /* cleanup */ if (pvPageBuf) IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); else RTMemTmpFree(pHdr); } } else { /* * The request failed, just clean up. */ if (pUser) { if (pvPageBuf) IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); else RTMemTmpFree(pHdr); } Log(("VBoxDrvDarwinIOCtlSlow: pid=%d iCmd=%lx pData=%p failed, rc=%d\n", proc_pid(pProcess), iCmd, (void *)pData, rc)); rc = EINVAL; } Log2(("VBoxDrvDarwinIOCtlSlow: returns %d\n", rc)); return rc; }
DECLASM(int) VBoxDrvIOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData, uint16_t *pcbParm, uint16_t *pcbData) { /* * Find the session. */ const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(sfn); PSUPDRVSESSION pSession; RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; if (pSession && pSession->Process != Process) { do pSession = pSession->pNextHash; while ( pSession && ( pSession->sfn != sfn || pSession->Process != Process)); if (RT_LIKELY(pSession)) supdrvSessionRetain(pSession); } RTSpinlockReleaseNoInts(g_Spinlock); if (!pSession) { OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process)); return VERR_INVALID_PARAMETER; } /* * Verify the category and dispatch the IOCtl. */ if (RT_LIKELY(iCat == SUP_CTL_CATEGORY)) { Log(("VBoxDrvIOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData)); Assert(pvParm); Assert(!pvData); /* * Lock the header. */ PSUPREQHDR pHdr = (PSUPREQHDR)pvParm; AssertReturn(*pcbParm == sizeof(*pHdr), VERR_INVALID_PARAMETER); KernVMLock_t Lock; int rc = KernVMLock(VMDHL_WRITE, pHdr, *pcbParm, &Lock, (KernPageList_t *)-1, NULL); AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, *pcbParm, &Lock, rc), VERR_LOCK_FAILED); /* * Validate the header. */ if (RT_LIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) == SUPREQHDR_FLAGS_MAGIC)) { uint32_t cbReq = RT_MAX(pHdr->cbIn, pHdr->cbOut); if (RT_LIKELY( pHdr->cbIn >= sizeof(*pHdr) && pHdr->cbOut >= sizeof(*pHdr) && cbReq <= _1M*16)) { /* * Lock the rest of the buffer if necessary. */ if (((uintptr_t)pHdr & PAGE_OFFSET_MASK) + cbReq > PAGE_SIZE) { rc = KernVMUnlock(&Lock); AssertMsgReturn(!rc, ("KernVMUnlock(Lock) -> %#x\n", rc), VERR_LOCK_FAILED); rc = KernVMLock(VMDHL_WRITE, pHdr, cbReq, &Lock, (KernPageList_t *)-1, NULL); AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, cbReq, &Lock, rc), VERR_LOCK_FAILED); } /* * Process the IOCtl. */ rc = supdrvIOCtl(iFunction, &g_DevExt, pSession, pHdr); } else { OSDBGPRINT(("VBoxDrvIOCtl: max(%#x,%#x); iCmd=%#x\n", pHdr->cbIn, pHdr->cbOut, iFunction)); rc = VERR_INVALID_PARAMETER; } } else { OSDBGPRINT(("VBoxDrvIOCtl: bad magic fFlags=%#x; iCmd=%#x\n", pHdr->fFlags, iFunction)); rc = VERR_INVALID_PARAMETER; } /* * Unlock and return. */ int rc2 = KernVMUnlock(&Lock); AssertMsg(!rc2, ("rc2=%d\n", rc2)); NOREF(rc2);s }