/** * Adds an entry for a file with the specified set of attributes. * * @returns IPRT status code. * * @param hManifest The manifest handle. * @param hVfsIos The I/O stream handle of the entry. This will * be processed to its end on successful return. * (Must be positioned at the start to get * the expected results.) * @param pszEntry The entry name. * @param fAttrs The attributes to create for this stream. */ RTDECL(int) RTManifestEntryAddIoStream(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, const char *pszEntry, uint32_t fAttrs) { /* * Note! This is a convenicence function, so just use the available public * methods to get the job done. */ AssertReturn(fAttrs < RTMANIFEST_ATTR_END, VERR_INVALID_PARAMETER); AssertPtr(pszEntry); /* * Allocate and initialize the hash contexts, hash digests and I/O buffer. */ PRTMANIFESTHASHES pHashes = rtManifestHashesCreate(fAttrs); if (!pHashes) return VERR_NO_TMP_MEMORY; int rc; size_t cbBuf = _1M; void *pvBuf = RTMemTmpAlloc(cbBuf); if (RT_UNLIKELY(!pvBuf)) { cbBuf = _4K; pvBuf = RTMemTmpAlloc(cbBuf); } if (RT_LIKELY(pvBuf)) { /* * Process the stream data. */ for (;;) { size_t cbRead; rc = RTVfsIoStrmRead(hVfsIos, pvBuf, cbBuf, true /*fBlocking*/, &cbRead); if ( (rc == VINF_EOF && cbRead == 0) || RT_FAILURE(rc)) break; rtManifestHashesUpdate(pHashes, pvBuf, cbRead); } RTMemTmpFree(pvBuf); if (RT_SUCCESS(rc)) { /* * Add the entry with the finalized hashes. */ rtManifestHashesFinal(pHashes); rc = RTManifestEntryAdd(hManifest, pszEntry); if (RT_SUCCESS(rc)) rc = rtManifestHashesSetAttrs(pHashes, hManifest, pszEntry); } } else { rtManifestHashesDestroy(pHashes); rc = VERR_NO_TMP_MEMORY; } return rc; }
DECLINLINE(void *) rtTarMemTmpAlloc(size_t *pcbSize) { *pcbSize = 0; /* Allocate a reasonably large buffer, fall back on a tiny one. * Note: has to be 512 byte aligned and >= 512 byte. */ size_t cbTmp = _1M; void *pvTmp = RTMemTmpAlloc(cbTmp); if (!pvTmp) { cbTmp = sizeof(RTTARRECORD); pvTmp = RTMemTmpAlloc(cbTmp); } *pcbSize = cbTmp; return pvTmp; }
RTDECL(int) RTEnvUnsetUtf8(const char *pszVar) { AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME); size_t cwcVar; int rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcVar); if (RT_SUCCESS(rc)) { PRTUTF16 pwszTmp = (PRTUTF16)RTMemTmpAlloc((cwcVar + 1 + 1) * sizeof(RTUTF16)); if (pwszTmp) { rc = RTStrToUtf16Ex(pszVar, RTSTR_MAX, &pwszTmp, cwcVar + 1, NULL); if (RT_SUCCESS(rc)) { pwszTmp[cwcVar] = '='; pwszTmp[cwcVar + 1] = '\0'; if (!_wputenv(pwszTmp)) rc = VINF_SUCCESS; else rc = RTErrConvertFromErrno(errno); } RTMemTmpFree(pwszTmp); } } return rc; }
RTDECL(int) RTSymlinkReadA(const char *pszSymlink, char **ppszTarget) { AssertPtr(ppszTarget); char const *pszNativeSymlink; int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL); if (RT_SUCCESS(rc)) { /* Guess the initial buffer size. */ ssize_t cbBuf; struct stat s; if (!lstat(pszNativeSymlink, &s)) cbBuf = RT_MIN(RT_ALIGN_Z(s.st_size, 64), 64); else cbBuf = 1024; /* Read loop that grows the buffer. */ char *pszBuf = NULL; for (;;) { RTMemTmpFree(pszBuf); pszBuf = (char *)RTMemTmpAlloc(cbBuf); if (pszBuf) { ssize_t cbReturned = readlink(pszNativeSymlink, pszBuf, cbBuf); if (cbReturned >= cbBuf) { /* Increase the buffer size and try again */ cbBuf *= 2; continue; } if (cbReturned > 0) { pszBuf[cbReturned] = '\0'; rc = rtPathFromNativeDup(ppszTarget, pszBuf, pszSymlink); } else if (errno == EINVAL) rc = VERR_NOT_SYMLINK; else rc = RTErrConvertFromErrno(errno); } else rc = VERR_NO_TMP_MEMORY; break; } /* for loop */ RTMemTmpFree(pszBuf); rtPathFreeNative(pszNativeSymlink, pszSymlink); } if (RT_SUCCESS(rc)) LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc *ppszTarget=%p:{%s}\n", pszSymlink, pszSymlink, ppszTarget, rc, *ppszTarget, *ppszTarget)); else LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc\n", pszSymlink, pszSymlink, ppszTarget, rc)); return rc; }
HRESULT MachineDebugger::logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr, const char *pszLogGetStr, BSTR *a_pbstrSettings) { /* Make sure the VM is powered up. */ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (FAILED(hrc)) return hrc; /* Make sure we've got a logger. */ if (!pLogger) { Bstr bstrEmpty; bstrEmpty.cloneTo(a_pbstrSettings); return S_OK; } /* Do the job. */ size_t cbBuf = _1K; for (;;) { char *pszBuf = (char *)RTMemTmpAlloc(cbBuf); AssertReturn(pszBuf, E_OUTOFMEMORY); int rc = pfnLogGetStr(pLogger, pszBuf, cbBuf); if (RT_SUCCESS(rc)) { try { Bstr bstrRet(pszBuf); bstrRet.detachTo(a_pbstrSettings); hrc = S_OK; } catch (std::bad_alloc) { hrc = E_OUTOFMEMORY; } RTMemTmpFree(pszBuf); return hrc; } RTMemTmpFree(pszBuf); AssertReturn(rc == VERR_BUFFER_OVERFLOW, setError(VBOX_E_IPRT_ERROR, tr("%s returned %Rrc"), pszLogGetStr, rc)); /* try again with a bigger buffer. */ cbBuf *= 2; AssertReturn(cbBuf <= _256K, setError(E_FAIL, tr("%s returns too much data"), pszLogGetStr)); } }
RTDECL(int) RTErrInfoAllocEx(size_t cbMsg, PRTERRINFO *ppErrInfo) { if (cbMsg == 0) cbMsg = _4K; else cbMsg = RT_ALIGN_Z(cbMsg, 256); PRTERRINFO pErrInfo; *ppErrInfo = pErrInfo = (PRTERRINFO)RTMemTmpAlloc(sizeof(*pErrInfo) + cbMsg); if (RT_UNLIKELY(!pErrInfo)) return VERR_NO_TMP_MEMORY; RTErrInfoInit(pErrInfo, (char *)(pErrInfo + 1), cbMsg); pErrInfo->fFlags = RTERRINFO_FLAGS_T_ALLOC | RTERRINFO_FLAGS_MAGIC; return VINF_SUCCESS; }
HRESULT MachineDebugger::i_logStringProps(PRTLOGGER pLogger, PFNLOGGETSTR pfnLogGetStr, const char *pszLogGetStr, Utf8Str *pstrSettings) { /* Make sure the VM is powered up. */ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtr ptrVM(mParent); HRESULT hrc = ptrVM.rc(); if (FAILED(hrc)) return hrc; /* Make sure we've got a logger. */ if (!pLogger) { *pstrSettings = ""; return S_OK; } /* Do the job. */ size_t cbBuf = _1K; for (;;) { char *pszBuf = (char *)RTMemTmpAlloc(cbBuf); AssertReturn(pszBuf, E_OUTOFMEMORY); int vrc = pstrSettings->reserveNoThrow(cbBuf); if (RT_SUCCESS(vrc)) { vrc = pfnLogGetStr(pLogger, pstrSettings->mutableRaw(), cbBuf); if (RT_SUCCESS(vrc)) { pstrSettings->jolt(); return S_OK; } *pstrSettings = ""; AssertReturn(vrc == VERR_BUFFER_OVERFLOW, setError(VBOX_E_IPRT_ERROR, tr("%s returned %Rrc"), pszLogGetStr, vrc)); } else return E_OUTOFMEMORY; /* try again with a bigger buffer. */ cbBuf *= 2; AssertReturn(cbBuf <= _256K, setError(E_FAIL, tr("%s returns too much data"), pszLogGetStr)); } }
/** * Output processing task, handles outgoing frames */ static void vboxNetFltFreeBSDoutput(void *arg, int pending) { PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg; struct mbuf *m, *m0; struct ifnet *ifp = pThis->u.s.ifp; unsigned int cSegs = 0; bool fDropIt = false, fActive; PINTNETSG pSG; VBOXCURVNET_SET(ifp->if_vnet); vboxNetFltRetain(pThis, true /* fBusy */); for (;;) { mtx_lock_spin(&pThis->u.s.outq.ifq_mtx); _IF_DEQUEUE(&pThis->u.s.outq, m); mtx_unlock_spin(&pThis->u.s.outq.ifq_mtx); if (m == NULL) break; for (m0 = m; m0 != NULL; m0 = m0->m_next) if (m0->m_len > 0) cSegs++; #ifdef PADD_RUNT_FRAMES_FROM_HOST if (m_length(m, NULL) < 60) cSegs++; #endif /* Create a copy and deliver to the virtual switch */ pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs])); vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0); fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, NULL /* pvIf */, pSG, INTNETTRUNKDIR_HOST); RTMemTmpFree(pSG); if (fDropIt) m_freem(m); else ether_output_frame(ifp, m); } vboxNetFltRelease(pThis, true /* fBusy */); VBOXCURVNET_RESTORE(); }
/** * Gets an entry. * * @returns IPRT status code. * @param pThis The manifest to work with. * @param pszEntry The entry name. * @param fNeedNormalization Whether rtManifestValidateNameEntry said it * needed normalization. * @param cchEntry The length of the name. * @param ppEntry Where to return the entry pointer on success. */ static int rtManifestGetEntry(RTMANIFESTINT *pThis, const char *pszEntry, bool fNeedNormalization, size_t cchEntry, PRTMANIFESTENTRY *ppEntry) { PRTMANIFESTENTRY pEntry; AssertCompileMemberOffset(RTMANIFESTATTR, StrCore, 0); if (!fNeedNormalization) pEntry = (PRTMANIFESTENTRY)RTStrSpaceGet(&pThis->Entries, pszEntry); else { char *pszCopy = (char *)RTMemTmpAlloc(cchEntry + 1); if (RT_UNLIKELY(!pszCopy)) return VERR_NO_TMP_MEMORY; memcpy(pszCopy, pszEntry, cchEntry + 1); rtManifestNormalizeEntry(pszCopy); pEntry = (PRTMANIFESTENTRY)RTStrSpaceGet(&pThis->Entries, pszCopy); RTMemTmpFree(pszCopy); } *ppEntry = pEntry; return pEntry ? VINF_SUCCESS : VERR_NOT_FOUND; }
int vbglR3GRAlloc(VMMDevRequestHeader **ppReq, uint32_t cb, VMMDevRequestType enmReqType) { VMMDevRequestHeader *pReq; AssertPtrReturn(ppReq, VERR_INVALID_PARAMETER); AssertMsgReturn(cb >= sizeof(VMMDevRequestHeader), ("%#x vs %#zx\n", cb, sizeof(VMMDevRequestHeader)), VERR_INVALID_PARAMETER); pReq = (VMMDevRequestHeader *)RTMemTmpAlloc(cb); if (RT_UNLIKELY(!pReq)) return VERR_NO_MEMORY; pReq->size = cb; pReq->version = VMMDEV_REQUEST_HEADER_VERSION; pReq->requestType = enmReqType; pReq->rc = VERR_GENERAL_FAILURE; pReq->reserved1 = 0; pReq->reserved2 = 0; *ppReq = pReq; return VINF_SUCCESS; }
RTDECL(int) RTEnvSetUtf8(const char *pszVar, const char *pszValue) { AssertReturn(strchr(pszVar, '=') == NULL, VERR_ENV_INVALID_VAR_NAME); size_t cwcVar; int rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcVar); if (RT_SUCCESS(rc)) { size_t cwcValue; rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcValue); if (RT_SUCCESS(rc)) { PRTUTF16 pwszTmp = (PRTUTF16)RTMemTmpAlloc((cwcVar + 1 + cwcValue + 1) * sizeof(RTUTF16)); if (pwszTmp) { rc = RTStrToUtf16Ex(pszVar, RTSTR_MAX, &pwszTmp, cwcVar + 1, NULL); if (RT_SUCCESS(rc)) { PRTUTF16 pwszTmpValue = &pwszTmp[cwcVar]; *pwszTmpValue++ = '='; rc = RTStrToUtf16Ex(pszValue, RTSTR_MAX, &pwszTmpValue, cwcValue + 1, NULL); if (RT_SUCCESS(rc)) { if (!_wputenv(pwszTmp)) rc = VINF_SUCCESS; else rc = RTErrConvertFromErrno(errno); } } RTMemTmpFree(pwszTmp); } else rc = VERR_NO_TMP_MEMORY; } } return rc; }
RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser) { /* * Validate input. */ AssertMsgReturn(RTFileIsValid(FileSrc), ("FileSrc=%RTfile\n", FileSrc), VERR_INVALID_PARAMETER); AssertMsgReturn(RTFileIsValid(FileDst), ("FileDst=%RTfile\n", FileDst), VERR_INVALID_PARAMETER); AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER); /* * Save file offset. */ RTFOFF offSrcSaved; int rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_CURRENT, (uint64_t *)&offSrcSaved); if (RT_FAILURE(rc)) return rc; /* * Get the file size. */ RTFOFF cbSrc; rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_END, (uint64_t *)&cbSrc); if (RT_FAILURE(rc)) return rc; /* * Allocate buffer. */ size_t cbBuf; uint8_t *pbBufFree = NULL; uint8_t *pbBuf; if (cbSrc < _512K) { cbBuf = 8*_1K; pbBuf = (uint8_t *)alloca(cbBuf); } else { cbBuf = _128K; pbBuf = pbBufFree = (uint8_t *)RTMemTmpAlloc(cbBuf); } if (pbBuf) { /* * Seek to the start of each file * and set the size of the destination file. */ rc = RTFileSeek(FileSrc, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) { rc = RTFileSeek(FileDst, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) rc = RTFileSetSize(FileDst, cbSrc); if (RT_SUCCESS(rc) && pfnProgress) rc = pfnProgress(0, pvUser); if (RT_SUCCESS(rc)) { /* * Copy loop. */ unsigned uPercentage = 0; RTFOFF off = 0; RTFOFF cbPercent = cbSrc / 100; RTFOFF offNextPercent = cbPercent; while (off < cbSrc) { /* copy block */ RTFOFF cbLeft = cbSrc - off; size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft; rc = RTFileRead(FileSrc, pbBuf, cbBlock, NULL); if (RT_FAILURE(rc)) break; rc = RTFileWrite(FileDst, pbBuf, cbBlock, NULL); if (RT_FAILURE(rc)) break; /* advance */ off += cbBlock; if (pfnProgress && offNextPercent < off) { while (offNextPercent < off) { uPercentage++; offNextPercent += cbPercent; } rc = pfnProgress(uPercentage, pvUser); if (RT_FAILURE(rc)) break; } } #if 0 /* * Copy OS specific data (EAs and stuff). */ rtFileCopyOSStuff(FileSrc, FileDst); #endif /* 100% */ if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc)) rc = pfnProgress(100, pvUser); } } RTMemTmpFree(pbBufFree); } else rc = VERR_NO_MEMORY; /* * Restore source position. */ RTFileSeek(FileSrc, offSrcSaved, RTFILE_SEEK_BEGIN, NULL); return rc; }
static int vboxguestLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg) #endif { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pFilp->private_data; uint32_t cbData = _IOC_SIZE(uCmd); void *pvBufFree; void *pvBuf; int rc; uint64_t au64Buf[32/sizeof(uint64_t)]; Log6(("vboxguestLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p pid=%d/%d\n", pFilp, uCmd, (void *)ulArg, RTProcSelf(), current->pid)); /* * Buffer the request. */ if (cbData <= sizeof(au64Buf)) { pvBufFree = NULL; pvBuf = &au64Buf[0]; } else { pvBufFree = pvBuf = RTMemTmpAlloc(cbData); if (RT_UNLIKELY(!pvBuf)) { LogRel((DEVICE_NAME "::IOCtl: RTMemTmpAlloc failed to alloc %u bytes.\n", cbData)); return -ENOMEM; } } if (RT_LIKELY(copy_from_user(pvBuf, (void *)ulArg, cbData) == 0)) { /* * Process the IOCtl. */ size_t cbDataReturned; rc = VbgdCommonIoCtl(uCmd, &g_DevExt, pSession, pvBuf, cbData, &cbDataReturned); /* * Copy ioctl data and output buffer back to user space. */ if (RT_SUCCESS(rc)) { rc = 0; if (RT_UNLIKELY(cbDataReturned > cbData)) { LogRel((DEVICE_NAME "::IOCtl: too much output data %u expected %u\n", cbDataReturned, cbData)); cbDataReturned = cbData; } if (cbDataReturned > 0) { if (RT_UNLIKELY(copy_to_user((void *)ulArg, pvBuf, cbDataReturned) != 0)) { LogRel((DEVICE_NAME "::IOCtl: copy_to_user failed; pvBuf=%p ulArg=%p cbDataReturned=%u uCmd=%d\n", pvBuf, (void *)ulArg, cbDataReturned, uCmd, rc)); rc = -EFAULT; } } } else { Log(("vboxguestLinuxIOCtl: pFilp=%p uCmd=%#x ulArg=%p failed, rc=%d\n", pFilp, uCmd, (void *)ulArg, rc)); rc = -rc; Assert(rc > 0); /* Positive returns == negated VBox error status codes. */ } } else { Log((DEVICE_NAME "::IOCtl: copy_from_user(,%#lx, %#x) failed; uCmd=%#x.\n", ulArg, cbData, uCmd)); rc = -EFAULT; } if (pvBufFree) RTMemFree(pvBufFree); Log6(("vboxguestLinuxIOCtl: returns %d (pid=%d/%d)\n", rc, RTProcSelf(), current->pid)); return rc; }
/** * Reads the extension pack descriptor. * * @returns NULL on success, pointer to an error message on failure (caller * deletes it). * @param a_pszDir The directory containing the description file. * @param a_pExtPackDesc Where to store the extension pack descriptor. * @param a_pObjInfo Where to store the object info for the file (unix * attribs). Optional. */ RTCString *VBoxExtPackLoadDescFromVfsFile(RTVFSFILE hVfsFile, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo) { vboxExtPackClearDesc(a_pExtPackDesc); /* * Query the object info. */ RTFSOBJINFO ObjInfo; int rc = RTVfsFileQueryInfo(hVfsFile, &ObjInfo, RTFSOBJATTRADD_UNIX); if (RT_FAILURE(rc)) return &(new RTCString)->printf("RTVfsFileQueryInfo failed: %Rrc", rc); if (a_pObjInfo) *a_pObjInfo = ObjInfo; /* * The simple approach, read the whole thing into memory and pass this to * the XML parser. */ /* Check the file size. */ if (ObjInfo.cbObject > _1M || ObjInfo.cbObject < 0) return &(new RTCString)->printf("The XML file is too large (%'RU64 bytes)", ObjInfo.cbObject); size_t const cbFile = (size_t)ObjInfo.cbObject; /* Rewind to the start of the file. */ rc = RTVfsFileSeek(hVfsFile, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) return &(new RTCString)->printf("RTVfsFileSeek(,0,BEGIN) failed: %Rrc", rc); /* Allocate memory and read the file content into it. */ void *pvFile = RTMemTmpAlloc(cbFile); if (!pvFile) return &(new RTCString)->printf("RTMemTmpAlloc(%zu) failed", cbFile); RTCString *pstrErr = NULL; rc = RTVfsFileRead(hVfsFile, pvFile, cbFile, NULL); if (RT_FAILURE(rc)) pstrErr = &(new RTCString)->printf("RTVfsFileRead failed: %Rrc", rc); /* * Parse the file. */ xml::Document Doc; if (RT_SUCCESS(rc)) { xml::XmlMemParser Parser; RTCString strFileName = VBOX_EXTPACK_DESCRIPTION_NAME; try { Parser.read(pvFile, cbFile, strFileName, Doc); } catch (xml::XmlError Err) { pstrErr = new RTCString(Err.what()); rc = VERR_PARSE_ERROR; } } RTMemTmpFree(pvFile); /* * Hand the xml doc over to the common code. */ if (RT_SUCCESS(rc)) pstrErr = vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc); return pstrErr; }
RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t cbBuf) { AssertPtrReturn(pszBuf, VERR_INVALID_POINTER); AssertReturn(cbBuf > 0, VERR_INVALID_PARAMETER); *pszBuf = '\0'; AssertReturn(enmString > RTSYSDMISTR_INVALID && enmString < RTSYSDMISTR_END, VERR_INVALID_PARAMETER); CFStringRef PropStringRef = NULL; switch (enmString) { case RTSYSDMISTR_PRODUCT_NAME: PropStringRef = CFSTR(PROP_PRODUCT_NAME); break; case RTSYSDMISTR_PRODUCT_VERSION: PropStringRef = CFSTR(PROP_PRODUCT_VERSION); break; case RTSYSDMISTR_PRODUCT_SERIAL: PropStringRef = CFSTR(PROP_PRODUCT_SERIAL); break; case RTSYSDMISTR_PRODUCT_UUID: PropStringRef = CFSTR(PROP_PRODUCT_UUID); break; case RTSYSDMISTR_MANUFACTURER: PropStringRef = CFSTR(PROP_MANUFACTURER); break; default: return VERR_NOT_SUPPORTED; } mach_port_t MasterPort; kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort); if (kr != kIOReturnSuccess) { if (kr == KERN_NO_ACCESS) return VERR_ACCESS_DENIED; return RTErrConvertFromDarwinIO(kr); } CFDictionaryRef ClassToMatch = IOServiceMatching(IOCLASS_PLATFORMEXPERTDEVICE); if (!ClassToMatch) return VERR_NOT_SUPPORTED; /* IOServiceGetMatchingServices will always consume ClassToMatch. */ io_iterator_t Iterator; kr = IOServiceGetMatchingServices(MasterPort, ClassToMatch, &Iterator); if (kr != kIOReturnSuccess) return RTErrConvertFromDarwinIO(kr); int rc = VERR_NOT_SUPPORTED; io_service_t ServiceObject; while ((ServiceObject = IOIteratorNext(Iterator))) { if ( enmString == RTSYSDMISTR_PRODUCT_NAME || enmString == RTSYSDMISTR_PRODUCT_VERSION || enmString == RTSYSDMISTR_MANUFACTURER ) { CFDataRef DataRef = (CFDataRef)IORegistryEntryCreateCFProperty(ServiceObject, PropStringRef, kCFAllocatorDefault, kNilOptions); if (DataRef) { size_t cbData = CFDataGetLength(DataRef); const char *pchData = (const char *)CFDataGetBytePtr(DataRef); rc = RTStrCopyEx(pszBuf, cbBuf, pchData, cbData); CFRelease(DataRef); break; } } else { CFStringRef StringRef = (CFStringRef)IORegistryEntryCreateCFProperty(ServiceObject, PropStringRef, kCFAllocatorDefault, kNilOptions); if (StringRef) { Boolean fRc = CFStringGetCString(StringRef, pszBuf, cbBuf, kCFStringEncodingUTF8); if (fRc) rc = VINF_SUCCESS; else { CFIndex cwc = CFStringGetLength(StringRef); size_t cbTmp = cwc + 1; char *pszTmp = (char *)RTMemTmpAlloc(cbTmp); int cTries = 1; while ( pszTmp && (fRc = CFStringGetCString(StringRef, pszTmp, cbTmp, kCFStringEncodingUTF8)) == FALSE && cTries++ < 4) { RTMemTmpFree(pszTmp); cbTmp *= 2; pszTmp = (char *)RTMemTmpAlloc(cbTmp); } if (fRc) rc = RTStrCopy(pszBuf, cbBuf, pszTmp); else if (!pszTmp) rc = VERR_NO_TMP_MEMORY; else rc = VERR_ACCESS_DENIED; RTMemFree(pszTmp); } CFRelease(StringRef); break; } } } IOObjectRelease(ServiceObject); IOObjectRelease(Iterator); return rc; }
/** * VMMR3Init worker that initiates the switcher code (aka core code). * * This is core per VM code which might need fixups and/or for ease of use are * put on linear contiguous backing. * * @returns VBox status code. * @param pVM Pointer to the VM. */ int vmmR3SwitcherInit(PVM pVM) { #ifndef VBOX_WITH_RAW_MODE return VINF_SUCCESS; #else /* * Calc the size. */ unsigned cbCoreCode = 0; for (unsigned iSwitcher = 0; iSwitcher < RT_ELEMENTS(s_apSwitchers); iSwitcher++) { pVM->vmm.s.aoffSwitchers[iSwitcher] = cbCoreCode; PVMMSWITCHERDEF pSwitcher = s_apSwitchers[iSwitcher]; if (pSwitcher) { AssertRelease((unsigned)pSwitcher->enmType == iSwitcher); cbCoreCode += RT_ALIGN_32(pSwitcher->cbCode + 1, 32); } } /* * Allocate contiguous pages for switchers and deal with * conflicts in the intermediate mapping of the code. */ pVM->vmm.s.cbCoreCode = RT_ALIGN_32(cbCoreCode, PAGE_SIZE); pVM->vmm.s.pvCoreCodeR3 = SUPR3ContAlloc(pVM->vmm.s.cbCoreCode >> PAGE_SHIFT, &pVM->vmm.s.pvCoreCodeR0, &pVM->vmm.s.HCPhysCoreCode); int rc = VERR_NO_MEMORY; if (pVM->vmm.s.pvCoreCodeR3) { rc = PGMR3MapIntermediate(pVM, pVM->vmm.s.pvCoreCodeR0, pVM->vmm.s.HCPhysCoreCode, cbCoreCode); if (rc == VERR_PGM_INTERMEDIATE_PAGING_CONFLICT) { /* try more allocations - Solaris, Linux. */ const unsigned cTries = 8234; struct VMMInitBadTry { RTR0PTR pvR0; void *pvR3; RTHCPHYS HCPhys; RTUINT cb; } *paBadTries = (struct VMMInitBadTry *)RTMemTmpAlloc(sizeof(*paBadTries) * cTries); AssertReturn(paBadTries, VERR_NO_TMP_MEMORY); unsigned i = 0; do { paBadTries[i].pvR3 = pVM->vmm.s.pvCoreCodeR3; paBadTries[i].pvR0 = pVM->vmm.s.pvCoreCodeR0; paBadTries[i].HCPhys = pVM->vmm.s.HCPhysCoreCode; i++; pVM->vmm.s.pvCoreCodeR0 = NIL_RTR0PTR; pVM->vmm.s.HCPhysCoreCode = NIL_RTHCPHYS; pVM->vmm.s.pvCoreCodeR3 = SUPR3ContAlloc(pVM->vmm.s.cbCoreCode >> PAGE_SHIFT, &pVM->vmm.s.pvCoreCodeR0, &pVM->vmm.s.HCPhysCoreCode); if (!pVM->vmm.s.pvCoreCodeR3) break; rc = PGMR3MapIntermediate(pVM, pVM->vmm.s.pvCoreCodeR0, pVM->vmm.s.HCPhysCoreCode, cbCoreCode); } while ( rc == VERR_PGM_INTERMEDIATE_PAGING_CONFLICT && i < cTries - 1); /* cleanup */ if (RT_FAILURE(rc)) { paBadTries[i].pvR3 = pVM->vmm.s.pvCoreCodeR3; paBadTries[i].pvR0 = pVM->vmm.s.pvCoreCodeR0; paBadTries[i].HCPhys = pVM->vmm.s.HCPhysCoreCode; paBadTries[i].cb = pVM->vmm.s.cbCoreCode; i++; LogRel(("Failed to allocated and map core code: rc=%Rrc\n", rc)); } while (i-- > 0) { LogRel(("Core code alloc attempt #%d: pvR3=%p pvR0=%p HCPhys=%RHp\n", i, paBadTries[i].pvR3, paBadTries[i].pvR0, paBadTries[i].HCPhys)); SUPR3ContFree(paBadTries[i].pvR3, paBadTries[i].cb >> PAGE_SHIFT); } RTMemTmpFree(paBadTries); } }
/** * Driver ioctl, an alternate entry point for this character driver. * * @param Dev Device number * @param Cmd Operation identifier * @param pArg Arguments from user to driver * @param Mode Information bitfield (read/write, address space etc.) * @param pCred User credentials * @param pVal Return value for calling process. * * @return corresponding solaris error code. */ static int VBoxGuestSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArg, int Mode, cred_t *pCred, int *pVal) { LogFlow((DEVICE_NAME ":VBoxGuestSolarisIOCtl\n")); /* * Get the session from the soft state item. */ vboxguest_state_t *pState = ddi_get_soft_state(g_pVBoxGuestSolarisState, getminor(Dev)); if (!pState) { LogRel((DEVICE_NAME "::IOCtl: no state data for %d\n", getminor(Dev))); return EINVAL; } PVBOXGUESTSESSION pSession = pState->pSession; if (!pSession) { LogRel((DEVICE_NAME "::IOCtl: no session data for %d\n", getminor(Dev))); return EINVAL; } /* * Read and validate the request wrapper. */ VBGLBIGREQ ReqWrap; if (IOCPARM_LEN(Cmd) != sizeof(ReqWrap)) { LogRel((DEVICE_NAME "::IOCtl: bad request %#x size=%d expected=%d\n", Cmd, IOCPARM_LEN(Cmd), sizeof(ReqWrap))); return ENOTTY; } int rc = ddi_copyin((void *)pArg, &ReqWrap, sizeof(ReqWrap), Mode); if (RT_UNLIKELY(rc)) { LogRel((DEVICE_NAME "::IOCtl: ddi_copyin failed to read header pArg=%p Cmd=%d. rc=%#x.\n", pArg, Cmd, rc)); return EINVAL; } if (ReqWrap.u32Magic != VBGLBIGREQ_MAGIC) { LogRel((DEVICE_NAME "::IOCtl: bad magic %#x; pArg=%p Cmd=%#x.\n", ReqWrap.u32Magic, pArg, Cmd)); return EINVAL; } if (RT_UNLIKELY(ReqWrap.cbData > _1M*16)) { LogRel((DEVICE_NAME "::IOCtl: bad size %#x; pArg=%p Cmd=%#x.\n", ReqWrap.cbData, pArg, Cmd)); return EINVAL; } /* * Read the request payload if any; requests like VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS have no data payload. */ void *pvBuf = NULL; if (RT_LIKELY(ReqWrap.cbData > 0)) { pvBuf = RTMemTmpAlloc(ReqWrap.cbData); if (RT_UNLIKELY(!pvBuf)) { LogRel((DEVICE_NAME "::IOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap.cbData)); return ENOMEM; } rc = ddi_copyin((void *)(uintptr_t)ReqWrap.pvDataR3, pvBuf, ReqWrap.cbData, Mode); if (RT_UNLIKELY(rc)) { RTMemTmpFree(pvBuf); LogRel((DEVICE_NAME "::IOCtl: ddi_copyin failed; pvBuf=%p pArg=%p Cmd=%d. rc=%d\n", pvBuf, pArg, Cmd, rc)); return EFAULT; } if (RT_UNLIKELY(!VALID_PTR(pvBuf))) { RTMemTmpFree(pvBuf); LogRel((DEVICE_NAME "::IOCtl: pvBuf invalid pointer %p\n", pvBuf)); return EINVAL; } } Log((DEVICE_NAME "::IOCtl: pSession=%p pid=%d.\n", pSession, (int)RTProcSelf())); /* * Process the IOCtl. */ size_t cbDataReturned = 0; rc = VBoxGuestCommonIOCtl(Cmd, &g_DevExt, pSession, pvBuf, ReqWrap.cbData, &cbDataReturned); if (RT_SUCCESS(rc)) { rc = 0; if (RT_UNLIKELY(cbDataReturned > ReqWrap.cbData)) { LogRel((DEVICE_NAME "::IOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap.cbData)); cbDataReturned = ReqWrap.cbData; } if (cbDataReturned > 0) { rc = ddi_copyout(pvBuf, (void *)(uintptr_t)ReqWrap.pvDataR3, cbDataReturned, Mode); if (RT_UNLIKELY(rc)) { LogRel((DEVICE_NAME "::IOCtl: ddi_copyout failed; pvBuf=%p pArg=%p cbDataReturned=%u Cmd=%d. rc=%d\n", pvBuf, pArg, cbDataReturned, Cmd, rc)); rc = EFAULT; } } } else { /* * We Log() instead of LogRel() here because VBOXGUEST_IOCTL_WAITEVENT can return VERR_TIMEOUT, * VBOXGUEST_IOCTL_CANCEL_ALL_EVENTS can return VERR_INTERRUPTED and possibly more in the future; * which are not really failures that require logging. */ Log((DEVICE_NAME "::IOCtl: VBoxGuestCommonIOCtl failed. Cmd=%#x rc=%d\n", Cmd, rc)); rc = RTErrConvertToErrno(rc); } *pVal = rc; if (pvBuf) RTMemTmpFree(pvBuf); return rc; }
/** * Parses any string and tests if it is an IPv6 Address * * This function should NOT be used directly. If you do, note * that no security checks are done at the moment. This can change. * * @returns iprt sstatus code. * @param pszAddress The strin that holds the IPv6 address * @param addressLength The length of pszAddress * @param pszAddressOut Returns a plain, full blown IPv6 address * as a char array * @param addressOutSize The size of pszAddressOut (length) * @param pPortOut 32 bit unsigned integer, holding the port * If pszAddress doesn't contain a port, it's 0 * @param pszScopeOut Returns the scope of the address, if none it's 0 * @param scopeOutSize sizeof(pszScopeOut) * @param pBrackets returns true if the address was enclosed in brackets * @param pEmbeddedV4 returns true if the address is an embedded IPv4 address * @param followRfc if set to true, the function follows RFC (default) */ static int rtStrParseAddrStr6(const char *pszAddress, size_t addressLength, char *pszAddressOut, size_t addressOutSize, uint32_t *pPortOut, char *pszIfIdOut, size_t ifIdOutSize, bool *pBrackets, bool *pEmbeddedV4, bool followRfc) { /************************\ * Pointer Hell Ahead * \************************/ const char szIpV6AddressChars[] = "ABCDEF01234567890abcdef.:[]%"; // order IMPORTANT const char szIpV4AddressChars[] = "01234567890.:[]"; // order IMPORTANT const char szLinkLocalPrefix[] = "FfEe8800"; // const char *pszIpV6AddressChars = NULL, *pszIpV4AddressChars = NULL, *pszLinkLocalPrefix = NULL; char *pszSourceAddress = NULL, *pszSourceAddressStart = NULL; char *pszResultAddress = NULL, *pszResultAddressStart = NULL; char *pszResultAddress4 = NULL, *pszResultAddress4Start = NULL; char *pszResultPort = NULL, *pszResultPortStart = NULL; char *pszInternalAddress = NULL, *pszInternalAddressStart = NULL; char *pszInternalPort = NULL, *pszInternalPortStart = NULL; char *pStart = NULL, *pNow = NULL, *pNext = NULL, *pNowChar = NULL, *pIfId = NULL, *pIfIdEnd = NULL; char *pNowDigit = NULL, *pFrom = NULL, *pTo = NULL, *pLast = NULL; char *pGap = NULL, *pMisc = NULL, *pDotStart = NULL, *pFieldStart = NULL, *pFieldEnd = NULL; char *pFieldStartLongest = NULL, *pBracketOpen = NULL, *pBracketClose = NULL; char *pszRc = NULL; bool isLinkLocal = false; char szDummy[4]; uint8_t *pByte = NULL; uint32_t byteOut = 0; uint16_t returnValue = 0; uint32_t colons = 0; uint32_t colonsOverAll = 0; uint32_t fieldLength = 0; uint32_t dots = 0; size_t gapSize = 0; uint32_t intPortOut = 0; pszIpV4AddressChars = &szIpV4AddressChars[0]; pszIpV6AddressChars = &szIpV6AddressChars[6]; pszLinkLocalPrefix = &szLinkLocalPrefix[6]; if (!followRfc) pszIpV6AddressChars = &szIpV6AddressChars[0]; if (addressLength<2) returnValue = 711; pszResultAddressStart = (char *)RTMemTmpAlloc(34); pszInternalAddressStart = (char *)RTMemTmpAlloc(34); pszInternalPortStart = (char * )RTMemTmpAlloc(10); if (! (pszResultAddressStart && pszInternalAddressStart && pszInternalPortStart)) { if (pszResultAddressStart) RTMemTmpFree(pszResultAddressStart); if (pszInternalAddressStart) RTMemTmpFree(pszInternalAddressStart); if (pszInternalPortStart) RTMemTmpFree(pszInternalPortStart); return -701; } memset(szDummy, '\0', 4); pszResultAddress = pszResultAddressStart; memset(pszResultAddressStart, '\0', 34); pszInternalAddress = pszInternalAddressStart; memset(pszInternalAddressStart, '\0' , 34); pszInternalPort = pszInternalPortStart; memset(pszInternalPortStart, '\0', 10); pszSourceAddress = pszSourceAddressStart = (char *)pszAddress; pFrom = pTo = pStart = pLast = pszSourceAddressStart; while (*pszSourceAddress != '\0' && !returnValue) { pNow = NULL; pNext = NULL; pNowChar = NULL; pNowDigit = NULL; pNow = pszSourceAddress; pNext = pszSourceAddress + 1; if (!pFrom) pFrom = pTo = pNow; pNowChar = (char *)memchr(pszIpV6AddressChars, *pNow, strlen(pszIpV6AddressChars)); pNowDigit = (char *)memchr(pszIpV6AddressChars, *pNow, strlen(pszIpV6AddressChars) - 5); if (pszResultPort) { if (pLast && (pszResultPort == pszSourceAddressStart)) { if (*pLast == '\0') returnValue = 721; pszResultPortStart = (char *)RTMemTmpAlloc(10); if (!pszResultPortStart) returnValue = 702; memset(pszResultPortStart, '\0', 10); pszResultPort = pszResultPortStart; pszSourceAddress = pLast; pMisc = pLast; pLast = NULL; continue; } pNowDigit = NULL; pNowDigit = (char *)memchr(pszIpV4AddressChars, *pNow, strlen(pszIpV4AddressChars) - 4); if (strlen(pszResultPortStart) == 5) returnValue = 11; if (*pNow == '0' && pszResultPort == pszResultPortStart && *pNext != '\0' && (pNow - pMisc) < 5 ) { pszSourceAddress++; continue; } if (pNowDigit) { *pszResultPort = *pNowDigit; pszResultPort++; pszSourceAddress++; continue; } else returnValue = 12; } if (pszResultAddress4) { if (pszResultAddress4 == pszSourceAddressStart && pLast) { dots = 0; pszResultAddress4 = NULL; pszResultAddress4Start = NULL; pszResultAddress4Start = (char *)RTMemTmpAlloc(20); if (!pszResultAddress4Start) { returnValue = 401; break; } memset(pszResultAddress4Start, '\0', 20); pszResultAddress4 = pszResultAddress4Start; pszSourceAddress = pLast; pFrom = pLast; pTo = pLast; pLast = NULL; continue; } pTo = pNow; pNowDigit = NULL; pNowDigit = (char *)memchr(pszIpV4AddressChars, *pNow, strlen(pszIpV4AddressChars) - 4); if (!pNowDigit && *pNow != '.' && *pNow != ']' && *pNow != ':' && *pNow != '%') returnValue = 412; if ((pNow - pFrom) > 3) { returnValue = 402; break; } if (pNowDigit && *pNext != '\0') { pszSourceAddress++; continue; } if (!pNowDigit && !pBracketOpen && (*pNext == '.' || *pNext == ']' || *pNext == ':')) returnValue = 411; memset(pszResultAddress4, '0', 3); pMisc = pszResultAddress4 + 2; pszResultAddress4 = pszResultAddress4 + 3; if (*pNow != '.' && !pNowDigit && strlen(pszResultAddress4Start) < 9) returnValue = 403; if ((pTo - pFrom) > 0) pTo--; dots++; while (pTo >= pFrom) { *pMisc = *pTo; pMisc--; pTo--; } if (dots == 4 && *pNow == '.') { if (!pBracketOpen) { pszResultPort = pszSourceAddressStart; pLast = pNext; } else { returnValue = 409; } } dots = 0; pFrom = pNext; pTo = pNext; if (strlen(pszResultAddress4Start) > 11) pszResultAddress4 = NULL; if ((*pNow == ':' || *pNow == '.') && strlen(pszResultAddress4Start) == 12) { pLast = pNext; pszResultPort = pszSourceAddressStart; } if (*pNow == '%') { pIfId = pNow; pLast = pNow; continue; } pszSourceAddress = pNext; if (*pNow != ']') continue; pFrom = pNow; pTo = pNow; } if (pIfId && (!pIfIdEnd)) { if (*pIfId == '%' && pIfId == pLast && *pNext != '\0') { pFrom = pNext; pIfId = pNext; pLast = NULL; pszSourceAddress++; continue; } if (*pNow == '%' && pIfId <= pNow) { returnValue = 442; break; } if (*pNow != ']' && *pNext != '\0') { pTo = pNow; pszSourceAddress++; continue; } if (*pNow == ']') { pIfIdEnd = pNow - 1; pFrom = pNow; pTo = pNow; continue; } else { pIfIdEnd = pNow; pFrom = NULL; pTo = NULL; pszSourceAddress++; continue; } } if (!pNowChar) { returnValue = 254; if (followRfc) { pMisc = (char *)memchr(&szIpV6AddressChars[0], *pNow, strlen(&szIpV6AddressChars[0])); if (pMisc) returnValue = 253; } } if (strlen(pszResultAddressStart) > 32 && !pszResultAddress4Start) returnValue = 255; if (pNowDigit && *pNext != '\0' && colons == 0) { pTo = pNow; pszSourceAddress++; continue; } if (*pNow == ':' && *pNext != '\0') { colonsOverAll++; colons++; pszSourceAddress++; continue; } if (*pNow == ':' ) { colons++; colonsOverAll++; } if (*pNow == '.') { pMisc = pNow; while (*pMisc != '\0' && *pMisc != ']') { if (*pMisc == '.') dots++; pMisc++; } } if (*pNow == ']') { if (pBracketClose) returnValue = 77; if (!pBracketOpen) returnValue = 22; if (*pNext == ':' || *pNext == '.') { pszResultPort = pszSourceAddressStart; pLast = pNext + 1; } if (pFrom == pNow) pFrom = NULL; pBracketClose = pNow; } if (*pNow == '[') { if (pBracketOpen) returnValue = 23; if (pStart != pNow) returnValue = 24; pBracketOpen = pNow; pStart++; pFrom++; pszSourceAddress++; continue; } if (*pNow == '%') { if (pIfId) returnValue = 441; pLast = pNext; pIfId = pNext; } if (colons > 0) { if (colons == 1) { if (pStart + 1 == pNow ) returnValue = 31; if (*pNext == '\0' && !pNowDigit) returnValue = 32; pLast = pNow; } if (colons == 2) { if (pGap) returnValue = 33; pGap = pszResultAddress + 4; if (pStart + 1 == pNow || pStart + 2 == pNow) { pGap = pszResultAddressStart; pFrom = pNow; } if (*pNext == '\0' && !pNowDigit) pszSourceAddress++; if (*pNext != ':' && *pNext != '.') pLast = pNow; } if (colons == 3) { pFrom = pLast; pLast = pNow; if (*pNext == '\0' && !pNowDigit) returnValue = 34; if (pBracketOpen) returnValue = 35; if (pGap && followRfc) returnValue = 36; if (!pGap) pGap = pszResultAddress + 4; if (pStart + 3 == pNow) { pszResultPort = pszSourceAddressStart; pGap = pszResultAddress; pFrom = NULL; } if (pNowDigit) { pszResultPort = pszSourceAddressStart; } } } if (*pNext == '\0' && colons == 0 && !pIfIdEnd) { pFrom = pLast; if (pNowDigit) pTo = pNow; pLast = NULL; } if (dots > 0) { if (dots == 1) { pszResultPort = pszSourceAddressStart; pLast = pNext; } if (dots == 4 && pBracketOpen) returnValue = 601; if (dots == 3 || dots == 4) { pszResultAddress4 = pszSourceAddressStart; pLast = pFrom; pFrom = NULL; } if (dots > 4) returnValue = 603; dots = 0; } if (pFrom && pTo) { if (pTo - pFrom > 3) { returnValue = 51; break; } if (followRfc) { if ((pTo - pFrom > 0) && *pFrom == '0') returnValue = 101; if ((pTo - pFrom) == 0 && *pFrom == '0' && colons == 2) returnValue = 102; if ((pTo - pFrom) == 0 && *pFrom == '0' && pszResultAddress == pGap) returnValue = 103; if ((pTo - pFrom) == 0 && *pFrom == '0') { if (!pFieldStart) { pFieldStart = pszResultAddress; pFieldEnd = pszResultAddress + 4; } else { pFieldEnd = pFieldEnd + 4; } } else { if ((size_t)(pFieldEnd - pFieldStart) > fieldLength) { fieldLength = pFieldEnd - pFieldStart; pFieldStartLongest = pFieldStart; } pFieldStart = NULL; pFieldEnd = NULL; } } if (!(pGap == pszResultAddressStart && (size_t)(pNow - pStart) == colons)) { memset(pszResultAddress, '0', 4); pMisc = pszResultAddress + 3; pszResultAddress = pszResultAddress + 4; if (pFrom == pStart && (pTo - pFrom) == 3) { isLinkLocal = true; while (pTo >= pFrom) { *pMisc = *pTo; if (*pTo != *pszLinkLocalPrefix && *pTo != *(pszLinkLocalPrefix + 1)) isLinkLocal = false; pTo--; pMisc--; pszLinkLocalPrefix = pszLinkLocalPrefix - 2; } } else { while (pTo >= pFrom) { *pMisc = *pTo; pMisc--; pTo--; } } } pFrom = pNow; pTo = pNow; } if (*pNext == '\0' && colons == 0) pszSourceAddress++; if (*pNext == '\0' && !pBracketClose && !pszResultPort) pTo = pNext; colons = 0; } // end of loop if (!returnValue && colonsOverAll < 2) returnValue = 252; if (!returnValue && (pBracketOpen && !pBracketClose)) returnValue = 25; if (!returnValue && pGap) { gapSize = 32 - strlen(pszResultAddressStart); if (followRfc) { if (gapSize < 5) returnValue = 104; if (fieldLength > gapSize) returnValue = 105; if (fieldLength == gapSize && pFieldStartLongest < pGap) returnValue = 106; } pszResultAddress = pszResultAddressStart; pszInternalAddress = pszInternalAddressStart; if (!returnValue && pszResultAddress4Start) { if (strlen(pszResultAddressStart) > 4) returnValue = 405; pszResultAddress = pszResultAddressStart; if (pGap != pszResultAddressStart) returnValue = 407; memset(pszInternalAddressStart, '0', 20); pszInternalAddress = pszInternalAddressStart + 20; for (int i = 0; i < 4; i++) { if (*pszResultAddress != 'f' && *pszResultAddress != 'F') { returnValue = 406; break; } *pszInternalAddress = *pszResultAddress; pszResultAddress++; pszInternalAddress++; } pszResultAddress4 = pszResultAddress4Start; for (int i = 0; i<4; i++) { memcpy(szDummy, pszResultAddress4, 3); int rc = RTStrToUInt32Ex((const char *)&szDummy[0], NULL, 16, &byteOut); if (rc == 0 && byteOut < 256) { RTStrPrintf(szDummy, 3, "%02x", byteOut); memcpy(pszInternalAddress, szDummy, 2); pszInternalAddress = pszInternalAddress + 2; pszResultAddress4 = pszResultAddress4 + 3; memset(szDummy, '\0', 4); } else { returnValue = 499; } } } else { while (!returnValue && pszResultAddress != pGap) { *pszInternalAddress = *pszResultAddress; pszResultAddress++; pszInternalAddress++; } memset(pszInternalAddress, '0', gapSize); pszInternalAddress = pszInternalAddress + gapSize; while (!returnValue && *pszResultAddress != '\0') { *pszInternalAddress = *pszResultAddress; pszResultAddress++; pszInternalAddress++; } } } else { if (!returnValue) { if (strlen(pszResultAddressStart) != 32) returnValue = 111; if (followRfc) { if (fieldLength > 4) returnValue = 112; } memcpy(pszInternalAddressStart, pszResultAddressStart, strlen(pszResultAddressStart)); } } if (pszResultPortStart) { if (strlen(pszResultPortStart) > 0 && strlen(pszResultPortStart) < 6) { memcpy(pszInternalPortStart, pszResultPortStart, strlen(pszResultPortStart)); intPortOut = 0; int rc = RTStrToUInt32Ex(pszInternalPortStart, NULL, 10, &intPortOut); if (rc == 0) { if (!(intPortOut > 0 && intPortOut < 65536)) intPortOut = 0; } else { returnValue = 888; } } else { returnValue = 889; } } /* full blown address 32 bytes, no colons -> pszInternalAddressStart port as string -> pszResultPortStart port as binary integer -> intPortOut interface id in pIfId and pIfIdEnd Now fill the out parameters. */ if (!returnValue && pszAddressOut) { if (strlen(pszInternalAddressStart) < addressOutSize) { pszRc = NULL; pszRc = (char *)memset(pszAddressOut, '\0', addressOutSize); if (!pszRc) returnValue = 910; pszRc = NULL; pszRc = (char *)memcpy(pszAddressOut, pszInternalAddressStart, strlen(pszInternalAddressStart)); if (!pszRc) returnValue = 911; } else { returnValue = 912; } } if (!returnValue && pPortOut) { *pPortOut = intPortOut; } if (!returnValue && pszIfIdOut) { if (pIfIdEnd && pIfId) { if ((size_t)(pIfIdEnd - pIfId) + 1 < ifIdOutSize) { pszRc = NULL; pszRc = (char *)memset(pszIfIdOut, '\0', ifIdOutSize); if (!pszRc) returnValue = 913; pszRc = NULL; pszRc = (char *)memcpy(pszIfIdOut, pIfId, (pIfIdEnd - pIfId) + 1); if (!pszRc) returnValue = 914; } else { returnValue = 915; } } else { pszRc = NULL; pszRc = (char *)memset(pszIfIdOut, '\0', ifIdOutSize); if (!pszRc) returnValue = 916; } // temporary hack if (isLinkLocal && (strlen(pszIfIdOut) < 1)) { memset(pszIfIdOut, '\0', ifIdOutSize); *pszIfIdOut = '%'; pszIfIdOut++; *pszIfIdOut = '0'; pszIfIdOut++; } } if (pBracketOpen && pBracketClose && pBrackets) *pBrackets = true; if (pEmbeddedV4 && pszResultAddress4Start) *pEmbeddedV4 = true; if (pszResultAddressStart) RTMemTmpFree(pszResultAddressStart); if (pszResultPortStart) RTMemTmpFree(pszResultPortStart); if (pszResultAddress4Start) RTMemTmpFree(pszResultAddress4Start); if (pszInternalAddressStart) RTMemTmpFree(pszInternalAddressStart); if (pszInternalPortStart) RTMemTmpFree(pszInternalPortStart); return (uint32_t)(returnValue - (returnValue * 2)); // make it negative... }
RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser) { /* * Validate input. */ AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE); AssertReturn(RTFileIsValid(hFile1), VERR_INVALID_HANDLE); AssertMsgReturn(!pfnProgress || VALID_PTR(pfnProgress), ("pfnProgress=%p\n", pfnProgress), VERR_INVALID_PARAMETER); AssertMsgReturn(!(fFlags & ~RTFILECOMP_FLAGS_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER); /* * Compare the file sizes first. */ uint64_t cbFile1; int rc = RTFileGetSize(hFile1, &cbFile1); if (RT_FAILURE(rc)) return rc; uint64_t cbFile2; rc = RTFileGetSize(hFile1, &cbFile2); if (RT_FAILURE(rc)) return rc; if (cbFile1 != cbFile2) return VERR_NOT_EQUAL; /* * Allocate buffer. */ size_t cbBuf; uint8_t *pbBuf1Free = NULL; uint8_t *pbBuf1; uint8_t *pbBuf2Free = NULL; uint8_t *pbBuf2; if (cbFile1 < _512K) { cbBuf = 8*_1K; pbBuf1 = (uint8_t *)alloca(cbBuf); pbBuf2 = (uint8_t *)alloca(cbBuf); } else { cbBuf = _128K; pbBuf1 = pbBuf1Free = (uint8_t *)RTMemTmpAlloc(cbBuf); pbBuf2 = pbBuf2Free = (uint8_t *)RTMemTmpAlloc(cbBuf); } if (pbBuf1 && pbBuf2) { /* * Seek to the start of each file * and set the size of the destination file. */ rc = RTFileSeek(hFile1, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) { rc = RTFileSeek(hFile2, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc) && pfnProgress) rc = pfnProgress(0, pvUser); if (RT_SUCCESS(rc)) { /* * Compare loop. */ unsigned uPercentage = 0; RTFOFF off = 0; RTFOFF cbPercent = cbFile1 / 100; RTFOFF offNextPercent = cbPercent; while (off < (RTFOFF)cbFile1) { /* read the blocks */ RTFOFF cbLeft = cbFile1 - off; size_t cbBlock = cbLeft >= (RTFOFF)cbBuf ? cbBuf : (size_t)cbLeft; rc = RTFileRead(hFile1, pbBuf1, cbBlock, NULL); if (RT_FAILURE(rc)) break; rc = RTFileRead(hFile2, pbBuf2, cbBlock, NULL); if (RT_FAILURE(rc)) break; /* compare */ if (memcmp(pbBuf1, pbBuf2, cbBlock)) { rc = VERR_NOT_EQUAL; break; } /* advance */ off += cbBlock; if (pfnProgress && offNextPercent < off) { while (offNextPercent < off) { uPercentage++; offNextPercent += cbPercent; } rc = pfnProgress(uPercentage, pvUser); if (RT_FAILURE(rc)) break; } } #if 0 /* * Compare OS specific data (EAs and stuff). */ if (RT_SUCCESS(rc)) rc = rtFileCompareOSStuff(hFile1, hFile2); #endif /* 100% */ if (pfnProgress && uPercentage < 100 && RT_SUCCESS(rc)) rc = pfnProgress(100, pvUser); } } } else rc = VERR_NO_MEMORY; RTMemTmpFree(pbBuf2Free); RTMemTmpFree(pbBuf1Free); return rc; }
int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename) { pImage->pvNtSectionObj = NULL; pImage->hMemLock = NIL_RTR0MEMOBJ; #ifdef VBOX_WITHOUT_NATIVE_R0_LOADER # ifndef RT_ARCH_X86 # error "VBOX_WITHOUT_NATIVE_R0_LOADER is only safe on x86." # endif NOREF(pDevExt); NOREF(pszFilename); NOREF(pImage); return VERR_NOT_SUPPORTED; #else /* * Convert the filename from DOS UTF-8 to NT UTF-16. */ size_t cwcFilename; int rc = RTStrCalcUtf16LenEx(pszFilename, RTSTR_MAX, &cwcFilename); if (RT_FAILURE(rc)) return rc; PRTUTF16 pwcsFilename = (PRTUTF16)RTMemTmpAlloc((4 + cwcFilename + 1) * sizeof(RTUTF16)); if (!pwcsFilename) return VERR_NO_TMP_MEMORY; pwcsFilename[0] = '\\'; pwcsFilename[1] = '?'; pwcsFilename[2] = '?'; pwcsFilename[3] = '\\'; PRTUTF16 pwcsTmp = &pwcsFilename[4]; rc = RTStrToUtf16Ex(pszFilename, RTSTR_MAX, &pwcsTmp, cwcFilename + 1, NULL); if (RT_SUCCESS(rc)) { /* * Try load it. */ MYSYSTEMGDIDRIVERINFO Info; RtlInitUnicodeString(&Info.Name, pwcsFilename); Info.ImageAddress = NULL; Info.SectionPointer = NULL; Info.EntryPointer = NULL; Info.ExportSectionPointer = NULL; Info.ImageLength = 0; NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemLoadGdiDriverInSystemSpaceInformation, &Info, sizeof(Info)); if (NT_SUCCESS(rcNt)) { pImage->pvImage = Info.ImageAddress; pImage->pvNtSectionObj = Info.SectionPointer; Log(("ImageAddress=%p SectionPointer=%p ImageLength=%#x cbImageBits=%#x rcNt=%#x '%ls'\n", Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer)); # ifdef DEBUG_bird SUPR0Printf("ImageAddress=%p SectionPointer=%p ImageLength=%#x cbImageBits=%#x rcNt=%#x '%ws'\n", Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer); # endif if (pImage->cbImageBits == Info.ImageLength) { /* * Lock down the entire image, just to be on the safe side. */ rc = RTR0MemObjLockKernel(&pImage->hMemLock, pImage->pvImage, pImage->cbImageBits, RTMEM_PROT_READ); if (RT_FAILURE(rc)) { pImage->hMemLock = NIL_RTR0MEMOBJ; supdrvOSLdrUnload(pDevExt, pImage); } } else { supdrvOSLdrUnload(pDevExt, pImage); rc = VERR_LDR_MISMATCH_NATIVE; } } else { Log(("rcNt=%#x '%ls'\n", rcNt, pwcsFilename)); SUPR0Printf("VBoxDrv: rcNt=%x '%ws'\n", rcNt, pwcsFilename); switch (rcNt) { case /* 0xc0000003 */ STATUS_INVALID_INFO_CLASS: # ifdef RT_ARCH_AMD64 /* Unwind will crash and BSOD, so no fallback here! */ rc = VERR_NOT_IMPLEMENTED; # else /* * Use the old way of loading the modules. * * Note! We do *NOT* try class 26 because it will probably * not work correctly on terminal servers and such. */ rc = VERR_NOT_SUPPORTED; # endif break; case /* 0xc0000034 */ STATUS_OBJECT_NAME_NOT_FOUND: rc = VERR_MODULE_NOT_FOUND; break; case /* 0xC0000263 */ STATUS_DRIVER_ENTRYPOINT_NOT_FOUND: rc = VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND; break; case 0xC0000428 /* STATUS_INVALID_IMAGE_HASH */ : rc = VERR_LDR_IMAGE_HASH; break; case 0xC000010E /* STATUS_IMAGE_ALREADY_LOADED */ : Log(("WARNING: see @bugref{4853} for cause of this failure on Windows 7 x64\n")); rc = VERR_ALREADY_LOADED; break; default: rc = VERR_LDR_GENERAL_FAILURE; break; } pImage->pvNtSectionObj = NULL; } } RTMemTmpFree(pwcsFilename); NOREF(pDevExt); return rc; #endif }
/** * Converts a string from one charset to another without using the handle cache. * * @returns IPRT status code. * * @param pvInput Pointer to intput string. * @param cbInput Size (in bytes) of input string. Excludes any terminators. * @param pszInputCS Codeset of the input string. * @param ppvOutput Pointer to pointer to output buffer if cbOutput > 0. * If cbOutput is 0 this is where the pointer to the allocated * buffer is stored. * @param cbOutput Size of the passed in buffer. * @param pszOutputCS Codeset of the input string. * @param cFactor Input vs. output size factor. */ static int rtStrConvertUncached(const void *pvInput, size_t cbInput, const char *pszInputCS, void **ppvOutput, size_t cbOutput, const char *pszOutputCS, unsigned cFactor) { /* * Allocate buffer */ bool fUcs2Term; void *pvOutput; size_t cbOutput2; if (!cbOutput) { cbOutput2 = cbInput * cFactor; pvOutput = RTMemTmpAlloc(cbOutput2 + sizeof(RTUTF16)); if (!pvOutput) return VERR_NO_TMP_MEMORY; fUcs2Term = true; } else { pvOutput = *ppvOutput; fUcs2Term = !strcmp(pszOutputCS, "UCS-2"); cbOutput2 = cbOutput - (fUcs2Term ? sizeof(RTUTF16) : 1); if (cbOutput2 > cbOutput) return VERR_BUFFER_OVERFLOW; } /* * Use a loop here to retry with bigger buffers. */ for (unsigned cTries = 10; cTries > 0; cTries--) { /* * Create conversion object. */ #if defined(RT_OS_SOLARIS) || defined(RT_OS_NETBSD) /* Some systems don't grok empty codeset strings, so help them find the current codeset. */ if (!*pszInputCS) pszInputCS = rtStrGetLocaleCodeset(); if (!*pszOutputCS) pszOutputCS = rtStrGetLocaleCodeset(); #endif IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc causes trouble */ iconv_t icHandle = iconv_open(pszOutputCS, pszInputCS); IPRT_ALIGNMENT_CHECKS_ENABLE(); if (icHandle != (iconv_t)-1) { /* * Do the conversion. */ size_t cbInLeft = cbInput; size_t cbOutLeft = cbOutput2; const void *pvInputLeft = pvInput; void *pvOutputLeft = pvOutput; size_t cchNonRev; #if defined(RT_OS_LINUX) || defined(RT_OS_HAIKU) || defined(RT_OS_SOLARIS) || (defined(RT_OS_DARWIN) && defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) /* there are different opinions about the constness of the input buffer. */ cchNonRev = iconv(icHandle, (char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft); #else cchNonRev = iconv(icHandle, (const char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft); #endif if (cchNonRev != (size_t)-1) { if (!cbInLeft) { /* * We're done, just add the terminator and return. * (Two terminators to support UCS-2 output, too.) */ iconv_close(icHandle); ((char *)pvOutputLeft)[0] = '\0'; if (fUcs2Term) ((char *)pvOutputLeft)[1] = '\0'; *ppvOutput = pvOutput; if (cchNonRev == 0) return VINF_SUCCESS; return VWRN_NO_TRANSLATION; } errno = E2BIG; } iconv_close(icHandle); /* * If we failed because of output buffer space we'll * increase the output buffer size and retry. */ if (errno == E2BIG) { if (!cbOutput) { RTMemTmpFree(pvOutput); cbOutput2 *= 2; pvOutput = RTMemTmpAlloc(cbOutput2 + sizeof(RTUTF16)); if (!pvOutput) return VERR_NO_TMP_MEMORY; continue; } return VERR_BUFFER_OVERFLOW; } } break; } /* failure */ if (!cbOutput) RTMemTmpFree(pvOutput); return VERR_NO_TRANSLATION; }
/* Used by PutEventMultiTouch and PutEventMultiTouchString. */ HRESULT Mouse::putEventMultiTouch(LONG aCount, LONG64 *paContacts, ULONG aScanTime) { if (aCount >= 256) { return E_INVALIDARG; } DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface(); ComAssertRet(pDisplay, E_FAIL); /* Touch events are mapped to the primary monitor, because the emulated USB * touchscreen device is associated with one (normally the primary) screen in the guest. */ ULONG uScreenId = 0; ULONG cWidth = 0; ULONG cHeight = 0; LONG xOrigin = 0; LONG yOrigin = 0; HRESULT rc = pDisplay->getScreenResolution(uScreenId, &cWidth, &cHeight, NULL, &xOrigin, &yOrigin); ComAssertComRCRetRC(rc); uint64_t* pau64Contacts = NULL; uint8_t cContacts = 0; /* Deliver 0 contacts too, touch device may use this to reset the state. */ if (aCount > 0) { /* Create a copy with converted coords. */ pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t)); if (pau64Contacts) { int32_t x1 = xOrigin; int32_t y1 = yOrigin; int32_t x2 = x1 + cWidth; int32_t y2 = y1 + cHeight; LogRel3(("%s: screen [%d] %d,%d %d,%d\n", __FUNCTION__, uScreenId, x1, y1, x2, y2)); LONG i; for (i = 0; i < aCount; i++) { uint32_t u32Lo = RT_LO_U32(paContacts[i]); uint32_t u32Hi = RT_HI_U32(paContacts[i]); int32_t x = (int16_t)u32Lo; int32_t y = (int16_t)(u32Lo >> 16); uint8_t contactId = RT_BYTE1(u32Hi); bool fInContact = (RT_BYTE2(u32Hi) & 0x1) != 0; bool fInRange = (RT_BYTE2(u32Hi) & 0x2) != 0; LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n", __FUNCTION__, i, x, y, contactId, fInContact, fInRange)); /* x1,y1 are inclusive and x2,y2 are exclusive, * while x,y start from 1 and are inclusive. */ if (x <= x1 || x > x2 || y <= y1 || y > y2) { /* Out of range. Skip the contact. */ continue; } int32_t xAdj = x1 < x2? ((x - 1 - x1) * VMMDEV_MOUSE_RANGE) / (x2 - x1) : 0; int32_t yAdj = y1 < y2? ((y - 1 - y1) * VMMDEV_MOUSE_RANGE) / (y2 - y1) : 0; bool fValid = ( xAdj >= VMMDEV_MOUSE_RANGE_MIN && xAdj <= VMMDEV_MOUSE_RANGE_MAX && yAdj >= VMMDEV_MOUSE_RANGE_MIN && yAdj <= VMMDEV_MOUSE_RANGE_MAX); if (fValid) { uint8_t fu8 = (fInContact? 0x01: 0x00) | (fInRange? 0x02: 0x00); pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj, (uint16_t)yAdj, RT_MAKE_U16(contactId, fu8), 0); cContacts++; } } } else {
RTR3DECL(int) RTSha256DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser) { /* Validate input */ AssertPtrReturn(pszFile, VERR_INVALID_POINTER); AssertPtrReturn(ppszDigest, VERR_INVALID_POINTER); AssertPtrNullReturn(pfnProgressCallback, VERR_INVALID_PARAMETER); *ppszDigest = NULL; /* Initialize the hash context. */ RTSHA256CONTEXT Ctx; RTSha256Init(&Ctx); /* Open the file to calculate a SHA256 sum of */ RTFILE hFile; int rc = RTFileOpen(&hFile, pszFile, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) return rc; /* Fetch the file size. Only needed if there is a progress callback. */ double rdMulti = 0; if (pfnProgressCallback) { uint64_t cbFile; rc = RTFileGetSize(hFile, &cbFile); if (RT_FAILURE(rc)) { RTFileClose(hFile); return rc; } rdMulti = 100.0 / (cbFile ? cbFile : 1); } /* Allocate a reasonably large buffer, fall back on a tiny one. */ void *pvBufFree; size_t cbBuf = _1M; void *pvBuf = pvBufFree = RTMemTmpAlloc(cbBuf); if (!pvBuf) { cbBuf = 0x1000; pvBuf = alloca(cbBuf); } /* Read that file in blocks */ size_t cbReadTotal = 0; for (;;) { size_t cbRead; rc = RTFileRead(hFile, pvBuf, cbBuf, &cbRead); if (RT_FAILURE(rc) || !cbRead) break; RTSha256Update(&Ctx, pvBuf, cbRead); cbReadTotal += cbRead; /* Call the progress callback if one is defined */ if (pfnProgressCallback) { rc = pfnProgressCallback((unsigned)(cbReadTotal * rdMulti), pvUser); if (RT_FAILURE(rc)) break; /* canceled */ } } RTMemTmpFree(pvBufFree); RTFileClose(hFile); if (RT_FAILURE(rc)) return rc; /* Finally calculate & format the SHA256 sum */ uint8_t abHash[RTSHA256_HASH_SIZE]; RTSha256Final(&Ctx, abHash); char *pszDigest; rc = RTStrAllocEx(&pszDigest, RTSHA256_DIGEST_LEN + 1); if (RT_SUCCESS(rc)) { rc = RTSha256ToString(abHash, pszDigest, RTSHA256_DIGEST_LEN + 1); if (RT_SUCCESS(rc)) *ppszDigest = pszDigest; else RTStrFree(pszDigest); } 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 vgdrvFreeBSDIOCtlSlow(PVBOXGUESTSESSION pSession, u_long ulCmd, caddr_t pvData, struct thread *pTd) { PVBGLREQHDR pHdr; uint32_t cbReq = IOCPARM_LEN(ulCmd); void *pvUser = NULL; /* * Buffered request? */ if ((IOC_DIRMASK & ulCmd) == IOC_INOUT) { pHdr = (PVBGLREQHDR)pvData; if (RT_UNLIKELY(cbReq < sizeof(*pHdr))) { LogRel(("vgdrvFreeBSDIOCtlSlow: cbReq=%#x < %#x; ulCmd=%#lx\n", cbReq, (int)sizeof(*pHdr), ulCmd)); return EINVAL; } if (RT_UNLIKELY(pHdr->uVersion != VBGLREQHDR_VERSION)) { LogRel(("vgdrvFreeBSDIOCtlSlow: bad uVersion=%#x; ulCmd=%#lx\n", pHdr->uVersion, ulCmd)); return EINVAL; } if (RT_UNLIKELY( RT_MAX(pHdr->cbIn, pHdr->cbOut) != cbReq || pHdr->cbIn < sizeof(*pHdr) || (pHdr->cbOut < sizeof(*pHdr) && pHdr->cbOut != 0))) { LogRel(("vgdrvFreeBSDIOCtlSlow: 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. */ VBGLREQHDR Hdr; pvUser = *(void **)pvData; int rc = copyin(pvUser, &Hdr, sizeof(Hdr)); if (RT_UNLIKELY(rc)) { LogRel(("vgdrvFreeBSDIOCtlSlow: copyin(%p,Hdr,) -> %#x; ulCmd=%#lx\n", pvUser, rc, ulCmd)); return rc; } if (RT_UNLIKELY(Hdr.uVersion != VBGLREQHDR_VERSION)) { LogRel(("vgdrvFreeBSDIOCtlSlow: bad uVersion=%#x; ulCmd=%#lx\n", Hdr.uVersion, ulCmd)); return EINVAL; } cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut); if (RT_UNLIKELY( Hdr.cbIn < sizeof(Hdr) || (Hdr.cbOut < sizeof(Hdr) && Hdr.cbOut != 0) || cbReq > _1M*16)) { LogRel(("vgdrvFreeBSDIOCtlSlow: max(%#x,%#x); ulCmd=%#lx\n", Hdr.cbIn, Hdr.cbOut, ulCmd)); return EINVAL; } /* * Allocate buffer and copy in the data. */ pHdr = (PVBGLREQHDR)RTMemTmpAlloc(cbReq); if (RT_UNLIKELY(!pHdr)) { LogRel(("vgdrvFreeBSDIOCtlSlow: failed to allocate buffer of %d bytes; ulCmd=%#lx\n", cbReq, ulCmd)); return ENOMEM; } rc = copyin(pvUser, pHdr, Hdr.cbIn); if (RT_UNLIKELY(rc)) { LogRel(("vgdrvFreeBSDIOCtlSlow: copyin(%p,%p,%#x) -> %#x; ulCmd=%#lx\n", pvUser, pHdr, Hdr.cbIn, rc, ulCmd)); RTMemTmpFree(pHdr); return rc; } if (Hdr.cbIn < cbReq) RT_BZERO((uint8_t *)pHdr + Hdr.cbIn, cbReq - Hdr.cbIn); } else { Log(("vgdrvFreeBSDIOCtlSlow: huh? cbReq=%#x ulCmd=%#lx\n", cbReq, ulCmd)); return EINVAL; } /* * Process the IOCtl. */ int rc = VGDrvCommonIoCtl(ulCmd, &g_DevExt, pSession, pHdr, cbReq); if (RT_LIKELY(!rc)) { /* * If unbuffered, copy back the result before returning. */ if (pvUser) { uint32_t cbOut = pHdr->cbOut; if (cbOut > cbReq) { LogRel(("vgdrvFreeBSDIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbOut, cbReq, ulCmd)); cbOut = cbReq; } rc = copyout(pHdr, pvUser, cbOut); if (RT_UNLIKELY(rc)) LogRel(("vgdrvFreeBSDIOCtlSlow: copyout(%p,%p,%#x) -> %d; uCmd=%#lx!\n", pHdr, pvUser, cbOut, rc, ulCmd)); Log(("vgdrvFreeBSDIOCtlSlow: 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(("vgdrvFreeBSDIOCtlSlow: ulCmd=%lx pData=%p failed, rc=%d\n", ulCmd, pvData, rc)); rc = EINVAL; } return rc; }
/* Used by PutEventMultiTouch and PutEventMultiTouchString. */ HRESULT Mouse::putEventMultiTouch(LONG aCount, LONG64 *paContacts, ULONG aScanTime) { if (aCount >= 256) { return E_INVALIDARG; } DisplayMouseInterface *pDisplay = mParent->getDisplayMouseInterface(); ComAssertRet(pDisplay, E_FAIL); HRESULT rc = S_OK; uint64_t* pau64Contacts = NULL; uint8_t cContacts = 0; /* Deliver 0 contacts too, touch device may use this to reset the state. */ if (aCount > 0) { /* Create a copy with converted coords. */ pau64Contacts = (uint64_t *)RTMemTmpAlloc(aCount * sizeof(uint64_t)); if (pau64Contacts) { int32_t x1, y1, x2, y2; /* Takes the display lock */ pDisplay->getFramebufferDimensions(&x1, &y1, &x2, &y2); LONG i; for (i = 0; i < aCount; i++) { uint32_t u32Lo = RT_LO_U32(paContacts[i]); uint32_t u32Hi = RT_HI_U32(paContacts[i]); int32_t x = (int16_t)u32Lo; int32_t y = (int16_t)(u32Lo >> 16); uint8_t contactId = RT_BYTE1(u32Hi); bool fInContact = (RT_BYTE2(u32Hi) & 0x1) != 0; bool fInRange = (RT_BYTE2(u32Hi) & 0x2) != 0; LogRel3(("%s: [%d] %d,%d id %d, inContact %d, inRange %d\n", __FUNCTION__, i, x, y, contactId, fInContact, fInRange)); /* Framebuffer dimensions are 0,0 width, height, that is x2,y2 are exclusive, * while coords are inclusive. */ int32_t xAdj = x1 < x2 ? ((x - 1 - x1) * VMMDEV_MOUSE_RANGE) / (x2 - x1) : 0; int32_t yAdj = y1 < y2 ? ((y - 1 - y1) * VMMDEV_MOUSE_RANGE) / (y2 - y1) : 0; bool fValid = ( xAdj >= VMMDEV_MOUSE_RANGE_MIN && xAdj <= VMMDEV_MOUSE_RANGE_MAX && yAdj >= VMMDEV_MOUSE_RANGE_MIN && yAdj <= VMMDEV_MOUSE_RANGE_MAX); if (fValid) { uint8_t fu8 = (fInContact? 0x01: 0x00) | (fInRange? 0x02: 0x00); pau64Contacts[cContacts] = RT_MAKE_U64_FROM_U16((uint16_t)xAdj, (uint16_t)yAdj, RT_MAKE_U16(contactId, fu8), 0); cContacts++; } } } else {
/** * IOCTL handler * */ static int VBoxGuestFreeBSDIOCtl(struct cdev *pDev, u_long ulCmd, caddr_t pvData, int fFile, struct thread *pTd) { LogFlow((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl\n")); int rc = 0; /* * Validate the input. */ PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1; if (RT_UNLIKELY(!VALID_PTR(pSession))) return EINVAL; /* * Validate the request wrapper. */ if (IOCPARM_LEN(ulCmd) != sizeof(VBGLBIGREQ)) { Log((DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad request %lu size=%lu expected=%d\n", ulCmd, IOCPARM_LEN(ulCmd), sizeof(VBGLBIGREQ))); return ENOTTY; } PVBGLBIGREQ ReqWrap = (PVBGLBIGREQ)pvData; if (ReqWrap->u32Magic != VBGLBIGREQ_MAGIC) { Log((DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad magic %#x; pArg=%p Cmd=%lu.\n", ReqWrap->u32Magic, pvData, ulCmd)); return EINVAL; } if (RT_UNLIKELY( ReqWrap->cbData == 0 || ReqWrap->cbData > _1M*16)) { printf(DEVICE_NAME ": VBoxGuestFreeBSDIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", ReqWrap->cbData, pvData, ulCmd); return EINVAL; } /* * Read the request. */ void *pvBuf = RTMemTmpAlloc(ReqWrap->cbData); if (RT_UNLIKELY(!pvBuf)) { Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap->cbData)); return ENOMEM; } rc = copyin((void *)(uintptr_t)ReqWrap->pvDataR3, pvBuf, ReqWrap->cbData); if (RT_UNLIKELY(rc)) { RTMemTmpFree(pvBuf); Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: copyin failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, pvData, ulCmd, rc)); return EFAULT; } if (RT_UNLIKELY( ReqWrap->cbData != 0 && !VALID_PTR(pvBuf))) { RTMemTmpFree(pvBuf); Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: pvBuf invalid pointer %p\n", pvBuf)); return EINVAL; } Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: pSession=%p pid=%d.\n", pSession, (int)RTProcSelf())); /* * Process the IOCtl. */ size_t cbDataReturned; rc = VbgdCommonIoCtl(ulCmd, &g_DevExt, pSession, pvBuf, ReqWrap->cbData, &cbDataReturned); if (RT_SUCCESS(rc)) { rc = 0; if (RT_UNLIKELY(cbDataReturned > ReqWrap->cbData)) { Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap->cbData)); cbDataReturned = ReqWrap->cbData; } if (cbDataReturned > 0) { rc = copyout(pvBuf, (void *)(uintptr_t)ReqWrap->pvDataR3, cbDataReturned); if (RT_UNLIKELY(rc)) { Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: copyout failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, pvData, ulCmd, rc)); rc = EFAULT; } } } else { Log((DEVICE_NAME ":VBoxGuestFreeBSDIOCtl: VbgdCommonIoCtl failed. rc=%d\n", rc)); rc = EFAULT; } RTMemTmpFree(pvBuf); return rc; }
/** * Tests if the given string is a valid IPv6 address. * * @returns 0 if valid, some random number if not. THIS IS NOT AN IPRT STATUS! * @param psz The string to test * @param pszResultAddress plain address, optional read "valid addresses * and strings" above. * @param resultAddressSize size of pszResultAddress * @param addressOnly return only the plain address (no scope) * Ignored, and will always return the if id */ static int rtNetIpv6CheckAddrStr(const char *psz, char *pszResultAddress, size_t resultAddressSize, bool addressOnly, bool followRfc) { int rc; int rc2; int returnValue; char *p = NULL, *pl = NULL; size_t memAllocMaxSize = RT_MAX(strlen(psz), resultAddressSize) + 40; char *pszAddressOutLocal = (char *)RTMemTmpAlloc(memAllocMaxSize); char *pszIfIdOutLocal = (char *)RTMemTmpAlloc(memAllocMaxSize); char *pszAddressRfcOutLocal = (char *)RTMemTmpAlloc(memAllocMaxSize); if (!pszAddressOutLocal || !pszIfIdOutLocal || !pszAddressRfcOutLocal) return VERR_NO_TMP_MEMORY; memset(pszAddressOutLocal, '\0', memAllocMaxSize); memset(pszIfIdOutLocal, '\0', memAllocMaxSize); memset(pszAddressRfcOutLocal, '\0', memAllocMaxSize); rc = rtStrParseAddrStr6(psz, strlen(psz), pszAddressOutLocal, memAllocMaxSize, NULL, pszIfIdOutLocal, memAllocMaxSize, NULL, NULL, followRfc); if (rc == 0) returnValue = VINF_SUCCESS; if (rc == 0 && pszResultAddress) { // convert the 32 characters to a valid, shortened ipv6 address rc2 = rtStrToIpAddr6Str((const char *)pszAddressOutLocal, pszAddressRfcOutLocal, memAllocMaxSize, NULL, 0, followRfc); if (rc2 != 0) returnValue = 951; // this is a temporary solution if (!returnValue && strlen(pszIfIdOutLocal) > 0) // the if identifier is copied over _ALWAYS_ && !addressOnly) { p = pszAddressRfcOutLocal + strlen(pszAddressRfcOutLocal); *p = '%'; p++; pl = (char *)memcpy(p, pszIfIdOutLocal, strlen(pszIfIdOutLocal)); if (!pl) returnValue = VERR_NOT_SUPPORTED; } pl = NULL; pl = (char *)memcpy(pszResultAddress, pszAddressRfcOutLocal, strlen(pszAddressRfcOutLocal)); if (!pl) returnValue = VERR_NOT_SUPPORTED; } if (rc != 0) returnValue = VERR_NOT_SUPPORTED; if (pszAddressOutLocal) RTMemTmpFree(pszAddressOutLocal); if (pszAddressRfcOutLocal) RTMemTmpFree(pszAddressRfcOutLocal); if (pszIfIdOutLocal) RTMemTmpFree(pszIfIdOutLocal); return returnValue; }
/** * Worker for VbgdDarwinIOCtl 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 data buffer. * @param pProcess The calling process. */ static int VbgdDarwinIOCtlSlow(PVBOXGUESTSESSION pSession, u_long iCmd, caddr_t pData, struct proc *pProcess) { LogFlow(("VbgdDarwinIOCtlSlow: pSession=%p iCmd=%p pData=%p pProcess=%p\n", pSession, iCmd, pData, pProcess)); /* * Buffered or unbuffered? */ void *pvReqData; user_addr_t pUser = 0; void *pvPageBuf = NULL; uint32_t cbReq = IOCPARM_LEN(iCmd); if ((IOC_DIRMASK & iCmd) == IOC_INOUT) { /* * Raw buffered request data, common code validates it. */ pvReqData = pData; } else if ((IOC_DIRMASK & iCmd) == IOC_VOID && !cbReq) { /* * Get the header and figure out how much we're gonna have to read. */ VBGLBIGREQ Hdr; pUser = (user_addr_t)*(void **)pData; int rc = copyin(pUser, &Hdr, sizeof(Hdr)); if (RT_UNLIKELY(rc)) { Log(("VbgdDarwinIOCtlSlow: copyin(%llx,Hdr,) -> %#x; iCmd=%#lx\n", (unsigned long long)pUser, rc, iCmd)); return rc; } if (RT_UNLIKELY(Hdr.u32Magic != VBGLBIGREQ_MAGIC)) { Log(("VbgdDarwinIOCtlSlow: bad magic u32Magic=%#x; iCmd=%#lx\n", Hdr.u32Magic, iCmd)); return EINVAL; } cbReq = Hdr.cbData; if (RT_UNLIKELY(cbReq > _1M*16)) { Log(("VbgdDarwinIOCtlSlow: %#x; iCmd=%#lx\n", Hdr.cbData, iCmd)); return EINVAL; } pUser = Hdr.pvDataR3; /* * Allocate buffer and copy in the data. */ pvReqData = RTMemTmpAlloc(cbReq); if (!pvReqData) pvPageBuf = pvReqData = IOMallocAligned(RT_ALIGN_Z(cbReq, PAGE_SIZE), 8); if (RT_UNLIKELY(!pvReqData)) { Log(("VbgdDarwinIOCtlSlow: failed to allocate buffer of %d bytes; iCmd=%#lx\n", cbReq, iCmd)); return ENOMEM; } rc = copyin(pUser, pvReqData, Hdr.cbData); if (RT_UNLIKELY(rc)) { Log(("VbgdDarwinIOCtlSlow: copyin(%llx,%p,%#x) -> %#x; iCmd=%#lx\n", (unsigned long long)pUser, pvReqData, Hdr.cbData, rc, iCmd)); if (pvPageBuf) IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); else RTMemTmpFree(pvReqData); return rc; } } else { Log(("VbgdDarwinIOCtlSlow: huh? cbReq=%#x iCmd=%#lx\n", cbReq, iCmd)); return EINVAL; } /* * Process the IOCtl. */ size_t cbReqRet = 0; int rc = VBoxGuestCommonIOCtl(iCmd, &g_DevExt, pSession, pvReqData, cbReq, &cbReqRet); if (RT_SUCCESS(rc)) { /* * If not buffered, copy back the buffer before returning. */ if (pUser) { if (cbReqRet > cbReq) { Log(("VbgdDarwinIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbReqRet, cbReq, iCmd)); cbReqRet = cbReq; } rc = copyout(pvReqData, pUser, cbReqRet); if (RT_UNLIKELY(rc)) Log(("VbgdDarwinIOCtlSlow: copyout(%p,%llx,%#x) -> %d; uCmd=%#lx!\n", pvReqData, (unsigned long long)pUser, cbReqRet, rc, iCmd)); /* cleanup */ if (pvPageBuf) IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); else RTMemTmpFree(pvReqData); } else rc = 0; } else { /* * The request failed, just clean up. */ if (pUser) { if (pvPageBuf) IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); else RTMemTmpFree(pvReqData); } Log(("VbgdDarwinIOCtlSlow: pid=%d iCmd=%lx pData=%p failed, rc=%d\n", proc_pid(pProcess), iCmd, (void *)pData, rc)); rc = EINVAL; } Log2(("VbgdDarwinIOCtlSlow: returns %d\n", rc)); return rc; }
static int VBoxUSBMonSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArg, int Mode, cred_t *pCred, int *pVal) { LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl Dev=%d Cmd=%d pArg=%p Mode=%d\n", Dev, Cmd, pArg)); /* * Get the session from the soft state item. */ vboxusbmon_state_t *pState = ddi_get_soft_state(g_pVBoxUSBMonSolarisState, getminor(Dev)); if (!pState) { LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: no state data for %d\n", getminor(Dev))); return EINVAL; } /* * Read the request wrapper. Though We don't really need wrapper struct. now * it's room for the future as Solaris isn't generous regarding the size. */ VBOXUSBREQ ReqWrap; if (IOCPARM_LEN(Cmd) != sizeof(ReqWrap)) { LogRel((DEVICE_NAME ": VBoxUSBMonSolarisIOCtl: bad request %#x size=%d expected=%d\n", Cmd, IOCPARM_LEN(Cmd), sizeof(ReqWrap))); return ENOTTY; } int rc = ddi_copyin((void *)pArg, &ReqWrap, sizeof(ReqWrap), Mode); if (RT_UNLIKELY(rc)) { LogRel((DEVICE_NAME ": VBoxUSBMonSolarisIOCtl: ddi_copyin failed to read header pArg=%p Cmd=%d. rc=%d.\n", pArg, Cmd, rc)); return EINVAL; } if (ReqWrap.u32Magic != VBOXUSBMON_MAGIC) { LogRel((DEVICE_NAME ": VBoxUSBMonSolarisIOCtl: bad magic %#x; pArg=%p Cmd=%d.\n", ReqWrap.u32Magic, pArg, Cmd)); return EINVAL; } if (RT_UNLIKELY( ReqWrap.cbData == 0 || ReqWrap.cbData > _1M*16)) { LogRel((DEVICE_NAME ": VBoxUSBMonSolarisIOCtl: bad size %#x; pArg=%p Cmd=%d.\n", ReqWrap.cbData, pArg, Cmd)); return EINVAL; } /* * Read the request. */ void *pvBuf = RTMemTmpAlloc(ReqWrap.cbData); if (RT_UNLIKELY(!pvBuf)) { LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap.cbData)); return ENOMEM; } rc = ddi_copyin((void *)(uintptr_t)ReqWrap.pvDataR3, pvBuf, ReqWrap.cbData, Mode); if (RT_UNLIKELY(rc)) { RTMemTmpFree(pvBuf); LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: ddi_copyin failed; pvBuf=%p pArg=%p Cmd=%d. rc=%d\n", pvBuf, pArg, Cmd, rc)); return EFAULT; } if (RT_UNLIKELY( ReqWrap.cbData != 0 && !VALID_PTR(pvBuf))) { RTMemTmpFree(pvBuf); LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: pvBuf invalid pointer %p\n", pvBuf)); return EINVAL; } Log((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: pid=%d.\n", (int)RTProcSelf())); /* * Process the IOCtl. */ size_t cbDataReturned; rc = vboxUSBMonSolarisProcessIOCtl(Cmd, pState, pvBuf, ReqWrap.cbData, &cbDataReturned); ReqWrap.rc = rc; rc = 0; if (RT_UNLIKELY(cbDataReturned > ReqWrap.cbData)) { LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap.cbData)); cbDataReturned = ReqWrap.cbData; } ReqWrap.cbData = cbDataReturned; /* * Copy the request back to user space. */ rc = ddi_copyout(&ReqWrap, (void *)pArg, sizeof(ReqWrap), Mode); if (RT_LIKELY(!rc)) { /* * Copy the payload (if any) back to user space. */ if (cbDataReturned > 0) { rc = ddi_copyout(pvBuf, (void *)(uintptr_t)ReqWrap.pvDataR3, cbDataReturned, Mode); if (RT_UNLIKELY(rc)) { LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: ddi_copyout failed; pvBuf=%p pArg=%p Cmd=%d. rc=%d\n", pvBuf, pArg, Cmd, rc)); rc = EFAULT; } } } else { LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: ddi_copyout(1) failed pArg=%p Cmd=%d\n", pArg, Cmd)); rc = EFAULT; } *pVal = rc; RTMemTmpFree(pvBuf); return rc; }
/** * 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; }