/** * Common open code. * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. * @param fUnrestricted Indicates which device node which was opened. */ static int vboxdrvLinuxCreateCommon(struct inode *pInode, struct file *pFilp, bool fUnrestricted) { int rc; PSUPDRVSESSION pSession; Log(("VBoxDrvLinuxCreate: pFilp=%p pid=%d/%d %s\n", pFilp, RTProcSelf(), current->pid, current->comm)); #ifdef VBOX_WITH_HARDENING /* * Only root is allowed to access the unrestricted device, enforce it! */ if ( fUnrestricted && vboxdrvLinuxEuid() != 0 /* root */ ) { Log(("VBoxDrvLinuxCreate: euid=%d, expected 0 (root)\n", vboxdrvLinuxEuid())); return -EPERM; } #endif /* VBOX_WITH_HARDENING */ /* * Call common code for the rest. */ rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession); if (!rc) { pSession->Uid = vboxdrvLinuxUid(); pSession->Gid = vboxdrvLinuxGid(); } pFilp->private_data = pSession; Log(("VBoxDrvLinuxCreate: g_DevExt=%p pSession=%p rc=%d/%d (pid=%d/%d %s)\n", &g_DevExt, pSession, rc, VBoxDrvLinuxErr2LinuxErr(rc), RTProcSelf(), current->pid, current->comm)); return VBoxDrvLinuxErr2LinuxErr(rc); }
DECLASM(int) VBoxDrvClose(uint16_t sfn) { Log(("VBoxDrvClose: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn)); /* * Remove from the hash table. */ PSUPDRVSESSION pSession; const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(sfn); RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; if (pSession) { if ( pSession->sfn == sfn && pSession->Process == Process) { g_apSessionHashTab[iHash] = pSession->pNextHash; pSession->pNextHash = NULL; } else { PSUPDRVSESSION pPrev = pSession; pSession = pSession->pNextHash; while (pSession) { if ( pSession->sfn == sfn && pSession->Process == Process) { pPrev->pNextHash = pSession->pNextHash; pSession->pNextHash = NULL; break; } /* next */ pPrev = pSession; pSession = pSession->pNextHash; } } } RTSpinlockReleaseNoInts(g_Spinlock); if (!pSession) { OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn)); return VERR_INVALID_PARAMETER; } /* * Close the session. */ supdrvSessionRelease(pSession); return 0; }
/** * Close device. */ static int VbgdDarwinClose(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess) { Log(("VbgdDarwinClose: pid=%d\n", (int)RTProcSelf())); Assert(proc_pid(pProcess) == (int)RTProcSelf()); /* * Hand the session closing to org_virtualbox_VBoxGuestClient. */ org_virtualbox_VBoxGuestClient::sessionClose(RTProcSelf()); return 0; }
static void tstRTProcQueryUsername(void) { RTTestISub("Basics"); size_t cbUser; char szUser[1024]; memset(szUser, '-', sizeof(szUser)); /* negative stuff that may assert: */ bool fMayPanic = RTAssertSetMayPanic(false); bool fQuiet = RTAssertSetQuiet(true); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), NULL, 8, &cbUser), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), szUser, 0, &cbUser), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), NULL, 0, NULL), VERR_INVALID_PARAMETER); RTTESTI_CHECK_RC(RTProcQueryUsernameA(RTProcSelf(), NULL), VERR_INVALID_POINTER); RTAssertSetMayPanic(fMayPanic); RTAssertSetQuiet(fQuiet); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), NULL, 0, &cbUser), VERR_BUFFER_OVERFLOW); memset(szUser, '-', sizeof(szUser)); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), szUser, cbUser - 1, &cbUser), VERR_BUFFER_OVERFLOW); memset(szUser, '-', sizeof(szUser)); RTTESTI_CHECK_RC(RTProcQueryUsername(RTProcSelf(), szUser, sizeof(szUser), &cbUser), VINF_SUCCESS); RTTestPrintf(NULL, RTTESTLVL_ALWAYS, "Username: %s\n", szUser); /* */ char *pszUser = NULL; RTTESTI_CHECK_RC(RTProcQueryUsernameA(RTProcSelf(), &pszUser), VINF_SUCCESS); RTTestPrintf(NULL, RTTESTLVL_ALWAYS, "Username: %s\n", pszUser); RTTESTI_CHECK(strcmp(pszUser, szUser) == 0); RTStrFree(pszUser); }
DECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction) { /* * 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 (RT_UNLIKELY(!pSession)) { OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process)); return VERR_INVALID_PARAMETER; } /* * Dispatch the fast IOCtl. */ supdrvIOCtlFast(iFunction, 0, &g_DevExt, pSession); supdrvSessionRelease(pSession); return 0; }
/** * Creates a PID File and returns the open file descriptor. * * On DOS based system, file sharing (deny write) is used for locking the PID * file. * * On Unix-y systems, an exclusive advisory lock is used for locking the PID * file since the file sharing support is usually missing there. * * This API will overwrite any existing PID Files without a lock on them, on the * assumption that they are stale files which an old process did not properly * clean up. * * @returns IPRT status code. * @param pszPath The path and filename to create the PID File under * @param phFile Where to store the file descriptor of the open (and locked * on Unix-y systems) PID File. On failure, or if another * process owns the PID File, this will be set to NIL_RTFILE. */ VBGLR3DECL(int) VbglR3PidFile(const char *pszPath, PRTFILE phFile) { AssertPtrReturn(pszPath, VERR_INVALID_PARAMETER); AssertPtrReturn(phFile, VERR_INVALID_PARAMETER); *phFile = NIL_RTFILE; RTFILE hPidFile; int rc = RTFileOpen(&hPidFile, pszPath, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE | (0644 << RTFILE_O_CREATE_MODE_SHIFT)); if (RT_SUCCESS(rc)) { #if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2) /** @todo using size 0 for locking means lock all on Posix. * We should adopt this as our convention too, or something * similar. */ rc = RTFileLock(hPidFile, RTFILE_LOCK_WRITE, 0, 0); if (RT_FAILURE(rc)) RTFileClose(hPidFile); else #endif { char szBuf[256]; size_t cbPid = RTStrPrintf(szBuf, sizeof(szBuf), "%d\n", RTProcSelf()); RTFileWrite(hPidFile, szBuf, cbPid, NULL); *phFile = hPidFile; } } return rc; }
/** * Close device. * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. */ static int VBoxNetAdpLinuxClose(struct inode *pInode, struct file *pFilp) { Log(("VBoxNetAdpLinuxClose: pid=%d/%d %s\n", RTProcSelf(), current->pid, current->comm)); pFilp->private_data = NULL; return 0; }
static int VBoxGuestSolarisClose(dev_t Dev, int flag, int fType, cred_t *pCred) { LogFlow((DEVICE_NAME "::Close pid=%d\n", (int)RTProcSelf())); PVBOXGUESTSESSION pSession = NULL; vboxguest_state_t *pState = ddi_get_soft_state(g_pVBoxGuestSolarisState, getminor(Dev)); if (!pState) { Log((DEVICE_NAME "::Close: failed to get pState.\n")); return EFAULT; } proc_unref(pState->pvProcRef); pSession = pState->pSession; pState->pSession = NULL; Log((DEVICE_NAME "::Close: pSession=%p pState=%p\n", pSession, pState)); ddi_soft_state_free(g_pVBoxGuestSolarisState, getminor(Dev)); if (!pSession) { Log((DEVICE_NAME "::Close: failed to get pSession.\n")); return EFAULT; } /* * Close the session. */ VBoxGuestCloseSession(&g_DevExt, pSession); return 0; }
static int vgdrvSolarisClose(dev_t Dev, int flag, int fType, cred_t *pCred) { LogFlow(("vgdrvSolarisClose: pid=%d\n", (int)RTProcSelf())); PVBOXGUESTSESSION pSession = NULL; vboxguest_state_t *pState = ddi_get_soft_state(g_pvgdrvSolarisState, getminor(Dev)); if (!pState) { Log(("vgdrvSolarisClose: failed to get pState.\n")); return EFAULT; } if (pState->pvProcRef != NULL) { proc_unref(pState->pvProcRef); pState->pvProcRef = NULL; } pSession = pState->pSession; pState->pSession = NULL; Log(("vgdrvSolarisClose: pSession=%p pState=%p\n", pSession, pState)); ddi_soft_state_free(g_pvgdrvSolarisState, getminor(Dev)); if (!pSession) { Log(("vgdrvSolarisClose: failed to get pSession.\n")); return EFAULT; } /* * Close the session. */ if (pSession) VGDrvCommonCloseSession(&g_DevExt, pSession); return 0; }
/** * Close device. * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. */ static int VBoxDrvLinuxClose(struct inode *pInode, struct file *pFilp) { Log(("VBoxDrvLinuxClose: pFilp=%p pSession=%p pid=%d/%d %s\n", pFilp, pFilp->private_data, RTProcSelf(), current->pid, current->comm)); supdrvSessionRelease((PSUPDRVSESSION)pFilp->private_data); pFilp->private_data = NULL; return 0; }
/** * The client exits abnormally / forgets to do cleanups. (logging) */ IOReturn org_virtualbox_SupDrvClient::clientDied(void) { LogFlow(("org_virtualbox_SupDrvClient::clientDied([%p]) m_Task=%p R0Process=%p Process=%d\n", this, m_Task, RTR0ProcHandleSelf(), RTProcSelf())); /* IOUserClient::clientDied() calls clientClose, so we'll just do the work there. */ return IOUserClient::clientDied(); }
/** * 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 VBoxDrvSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArgs, int Mode, cred_t *pCred, int *pVal) { #ifndef USE_SESSION_HASH /* * Get the session from the soft state item. */ vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev)); if (!pState) { LogRel((DEVICE_NAME ":VBoxDrvSolarisIOCtl: no state data for %#x (%d)\n", Dev, getminor(Dev))); return EINVAL; } PSUPDRVSESSION pSession = pState->pSession; if (!pSession) { LogRel((DEVICE_NAME ":VBoxDrvSolarisIOCtl: no session in state data for %#x (%d)\n", Dev, getminor(Dev))); return DDI_SUCCESS; } #else const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(Process); PSUPDRVSESSION pSession; /* * Find the session. */ RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; if (pSession && pSession->Process != Process) { do pSession = pSession->pNextHash; while (pSession && pSession->Process != Process); } RTSpinlockReleaseNoInts(g_Spinlock); if (!pSession) { LogRel((DEVICE_NAME ":VBoxSupDrvIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#x\n", (int)Process, Cmd)); return EINVAL; } #endif /* * Deal with the two high-speed IOCtl that takes it's arguments from * the session and iCmd, and only returns a VBox status code. */ if ( Cmd == SUP_IOCTL_FAST_DO_RAW_RUN || Cmd == SUP_IOCTL_FAST_DO_HWACC_RUN || Cmd == SUP_IOCTL_FAST_DO_NOP) { *pVal = supdrvIOCtlFast(Cmd, pArgs, &g_DevExt, pSession); return 0; } return VBoxDrvSolarisIOCtlSlow(pSession, Cmd, Mode, pArgs); }
/** * Close device. * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. */ static int vboxguestLinuxRelease(struct inode *pInode, struct file *pFilp) { Log(("vboxguestLinuxRelease: pFilp=%p pSession=%p pid=%d/%d %s\n", pFilp, pFilp->private_data, RTProcSelf(), current->pid, current->comm)); VBoxGuestCloseSession(&g_DevExt, (PVBOXGUESTSESSION)pFilp->private_data); pFilp->private_data = NULL; return 0; }
RTR3DECL(int) RTProcQueryParent(RTPROCESS hProcess, PRTPROCESS phParent) { if (hProcess == RTProcSelf()) { *phParent = getppid(); return VINF_SUCCESS; } return VERR_NOT_SUPPORTED; }
/** * Device open. Called on open /dev/vboxdrv * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. */ static int vboxguestLinuxOpen(struct inode *pInode, struct file *pFilp) { int rc; PVBOXGUESTSESSION pSession; Log((DEVICE_NAME ": pFilp=%p pid=%d/%d %s\n", pFilp, RTProcSelf(), current->pid, current->comm)); /* * Call common code to create the user session. Associate it with * the file so we can access it in the other methods. */ rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession); if (RT_SUCCESS(rc)) pFilp->private_data = pSession; Log(("vboxguestLinuxOpen: g_DevExt=%p pSession=%p rc=%d/%d (pid=%d/%d %s)\n", &g_DevExt, pSession, rc, vboxguestLinuxConvertToNegErrno(rc), RTProcSelf(), current->pid, current->comm)); return vboxguestLinuxConvertToNegErrno(rc); }
/** * Device open. Called on open /dev/vboxguest and (later) /dev/vboxguestu. * * @param Dev The device number. * @param fFlags ???. * @param fDevType ???. * @param pProcess The process issuing this request. */ static int VbgdDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess) { /* * Only two minor devices numbers are allowed. */ if (minor(Dev) != 0 && minor(Dev) != 1) return EACCES; /* * Find the session created by org_virtualbox_VBoxGuestClient, fail * if no such session, and mark it as opened. We set the uid & gid * here too, since that is more straight forward at this point. */ //const bool fUnrestricted = minor(Dev) == 0; int rc = VINF_SUCCESS; PVBOXGUESTSESSION pSession = NULL; kauth_cred_t pCred = kauth_cred_proc_ref(pProcess); if (pCred) { RTPROCESS Process = RTProcSelf(); unsigned iHash = SESSION_HASH(Process); RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; while (pSession && pSession->Process != Process) pSession = pSession->pNextHash; if (pSession) { if (!pSession->fOpened) { pSession->fOpened = true; /*pSession->fUnrestricted = fUnrestricted; - later */ } else rc = VERR_ALREADY_LOADED; } else rc = VERR_GENERAL_FAILURE; RTSpinlockRelease(g_Spinlock); #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 kauth_cred_unref(&pCred); #else /* 10.4 */ /* The 10.4u SDK headers and 10.4.11 kernel source have inconsistent definitions of kauth_cred_unref(), so use the other (now deprecated) API for releasing it. */ kauth_cred_rele(pCred); #endif /* 10.4 */ } else rc = VERR_INVALID_PARAMETER; Log(("VbgdDarwinOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, proc_pid(pProcess))); return VbgdDarwinErr2DarwinErr(rc); }
/** * Device open. Called on open /dev/vboxdrv * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. */ static int vgdrvLinuxOpen(struct inode *pInode, struct file *pFilp) { int rc; PVBOXGUESTSESSION pSession; Log((DEVICE_NAME ": pFilp=%p pid=%d/%d %s\n", pFilp, RTProcSelf(), current->pid, current->comm)); /* * Call common code to create the user session. Associate it with * the file so we can access it in the other methods. */ rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession); if (RT_SUCCESS(rc)) { pFilp->private_data = pSession; if (MINOR(pInode->i_rdev) == g_MiscDeviceUser.minor) pSession->fUserSession = true; } Log(("vgdrvLinuxOpen: g_DevExt=%p pSession=%p rc=%d/%d (pid=%d/%d %s)\n", &g_DevExt, pSession, rc, vgdrvLinuxConvertToNegErrno(rc), RTProcSelf(), current->pid, current->comm)); return vgdrvLinuxConvertToNegErrno(rc); }
STDMETHODIMP Session::GetPID(ULONG *aPid) { AssertReturn(aPid, E_POINTER); AutoCaller autoCaller(this); AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); *aPid = (ULONG)RTProcSelf(); AssertCompile(sizeof(*aPid) == sizeof(RTPROCESS)); return S_OK; }
/** * Close device. * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. */ static int vboxguestLinuxRelease(struct inode *pInode, struct file *pFilp) { Log(("vboxguestLinuxRelease: pFilp=%p pSession=%p pid=%d/%d %s\n", pFilp, pFilp->private_data, RTProcSelf(), current->pid, current->comm)); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) /* This housekeeping was needed in older kernel versions to ensure that * the file pointer didn't get left on the polling queue. */ vboxguestFAsync(-1, pFilp, 0); #endif VbgdCommonCloseSession(&g_DevExt, (PVBOXGUESTSESSION)pFilp->private_data); pFilp->private_data = NULL; return 0; }
/** * Initializer called when the client opens the service. */ bool org_virtualbox_SupDrvClient::initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type) { LogFlow(("org_virtualbox_SupDrvClient::initWithTask([%p], %#x, %p, %#x) (cur pid=%d proc=%p)\n", this, OwningTask, pvSecurityId, u32Type, RTProcSelf(), RTR0ProcHandleSelf())); AssertMsg((RTR0PROCESS)OwningTask == RTR0ProcHandleSelf(), ("%p %p\n", OwningTask, RTR0ProcHandleSelf())); if (!OwningTask) return false; if (IOUserClient::initWithTask(OwningTask, pvSecurityId , u32Type)) { m_Task = OwningTask; m_pSession = NULL; m_pProvider = NULL; return true; } return false; }
/** * Device open. Called on open /dev/vboxnetctl * * @param pInode Pointer to inode info structure. * @param pFilp Associated file pointer. */ static int VBoxNetAdpLinuxOpen(struct inode *pInode, struct file *pFilp) { Log(("VBoxNetAdpLinuxOpen: pid=%d/%d %s\n", RTProcSelf(), current->pid, current->comm)); #ifdef VBOX_WITH_HARDENING /* * Only root is allowed to access the device, enforce it! */ if (!capable(CAP_SYS_ADMIN)) { Log(("VBoxNetAdpLinuxOpen: admin privileges required!\n")); return -EPERM; } #endif return 0; }
static int VBoxUSBMonSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred) { vboxusbmon_state_t *pState = NULL; unsigned iOpenInstance; LogFunc((DEVICE_NAME ": VBoxUSBMonSolarisOpen\n")); /* * Verify we are being opened as a character device. */ if (fType != OTYP_CHR) return EINVAL; /* * Verify that we're called after attach. */ if (!g_pDip) { LogRel((DEVICE_NAME ": VBoxUSBMonSolarisOpen: Invalid state for opening\n")); return ENXIO; } for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++) { if ( !ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance) /* faster */ && ddi_soft_state_zalloc(g_pVBoxUSBMonSolarisState, iOpenInstance) == DDI_SUCCESS) { pState = ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance); break; } } if (!pState) { LogRel((DEVICE_NAME ": VBoxUSBMonSolarisOpen: Too many open instances")); return ENXIO; } pState->Process = RTProcSelf(); *pDev = makedevice(getmajor(*pDev), iOpenInstance); NOREF(fFlag); NOREF(pCred); return 0; }
RTR3DECL(int) RTProcQueryUsernameA(RTPROCESS hProcess, char **ppszUser) { AssertPtrReturn(ppszUser, VERR_INVALID_POINTER); int rc; if ( hProcess == NIL_RTPROCESS || hProcess == RTProcSelf()) { /* * Figure a good buffer estimate. */ int32_t cbPwdMax = sysconf(_SC_GETPW_R_SIZE_MAX); if (cbPwdMax <= _1K) cbPwdMax = _1K; else AssertStmt(cbPwdMax <= 32*_1M, cbPwdMax = 32*_1M); char *pchBuf = (char *)RTMemTmpAllocZ(cbPwdMax); if (pchBuf) { /* * Get the password file entry. */ struct passwd Pwd; struct passwd *pPwd = NULL; rc = getpwuid_r(geteuid(), &Pwd, pchBuf, cbPwdMax, &pPwd); if (!rc) { /* * Convert the name to UTF-8, assuming that we're getting it in the local codeset. */ rc = RTStrCurrentCPToUtf8(ppszUser, pPwd->pw_name); } else rc = RTErrConvertFromErrno(rc); RTMemFree(pchBuf); } else rc = VERR_NO_TMP_MEMORY; } else rc = VERR_NOT_SUPPORTED; return rc; }
RTR3DECL(int) RTProcQueryUsername(RTPROCESS hProcess, char *pszUser, size_t cbUser, size_t *pcbUser) { AssertReturn( (pszUser && cbUser > 0) || (!pszUser && !cbUser), VERR_INVALID_PARAMETER); if (hProcess != RTProcSelf()) return VERR_NOT_SUPPORTED; int32_t cbPwdMax = sysconf(_SC_GETPW_R_SIZE_MAX); if (cbPwdMax == -1) return RTErrConvertFromErrno(errno); char *pbBuf = (char *)RTMemAllocZ(cbPwdMax); if (!pbBuf) return VERR_NO_MEMORY; struct passwd Pwd, *pPwd; int rc = getpwuid_r(geteuid(), &Pwd, pbBuf, cbPwdMax, &pPwd); if (!rc) { size_t cbPwdUser = strlen(pPwd->pw_name) + 1; if (pcbUser) *pcbUser = cbPwdUser; if (cbPwdUser > cbUser) rc = VERR_BUFFER_OVERFLOW; else { memcpy(pszUser, pPwd->pw_name, cbPwdUser); rc = VINF_SUCCESS; } } else rc = RTErrConvertFromErrno(rc); RTMemFree(pbBuf); return rc; }
/** * Client exits normally. */ IOReturn org_virtualbox_SupDrvClient::clientClose(void) { LogFlow(("org_virtualbox_SupDrvClient::clientClose([%p]) (cur pid=%d proc=%p)\n", this, RTProcSelf(), RTR0ProcHandleSelf())); AssertMsg((RTR0PROCESS)m_Task == RTR0ProcHandleSelf(), ("%p %p\n", m_Task, RTR0ProcHandleSelf())); /* * Clean up the session if it's still around. * * We cannot rely 100% on close, and in the case of a dead client * we'll end up hanging inside vm_map_remove() if we postpone it. */ if (m_pSession) { sessionClose(RTProcSelf()); Assert(!m_pSession); } m_pProvider = NULL; terminate(); return kIOReturnSuccess; }
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; }
static int VBoxUSBMonSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred) { vboxusbmon_state_t *pState = NULL; unsigned iOpenInstance; LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisOpen\n")); /* * Verify we are being opened as a character device. */ if (fType != OTYP_CHR) return EINVAL; /* * Verify that we're called after attach. */ if (!g_pDip) { LogRel((DEVICE_NAME ":VBoxUSBMonSolarisOpen invalid state for opening.\n")); return ENXIO; } mutex_enter(&g_VBoxUSBMonSolarisMtx); if (!g_cVBoxUSBMonSolarisClient) { mutex_exit(&g_VBoxUSBMonSolarisMtx); int rc = usb_register_dev_driver(g_pDip, VBoxUSBMonSolarisElectDriver); if (RT_UNLIKELY(rc != DDI_SUCCESS)) { LogRel((DEVICE_NAME ":Failed to register driver election callback with USBA rc=%d\n", rc)); return EINVAL; } Log((DEVICE_NAME ":Successfully registered election callback with USBA\n")); mutex_enter(&g_VBoxUSBMonSolarisMtx); } g_cVBoxUSBMonSolarisClient++; mutex_exit(&g_VBoxUSBMonSolarisMtx); for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++) { if ( !ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance) /* faster */ && ddi_soft_state_zalloc(g_pVBoxUSBMonSolarisState, iOpenInstance) == DDI_SUCCESS) { pState = ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance); break; } } if (!pState) { LogRel((DEVICE_NAME ":VBoxUSBMonSolarisOpen: too many open instances.")); mutex_enter(&g_VBoxUSBMonSolarisMtx); g_cVBoxUSBMonSolarisClient--; mutex_exit(&g_VBoxUSBMonSolarisMtx); return ENXIO; } pState->Process = RTProcSelf(); *pDev = makedevice(getmajor(*pDev), iOpenInstance); NOREF(fFlag); NOREF(pCred); return 0; }
/** * Worker that we can wrap with error variable saving and restoring. */ static bool rtAssertShouldPanicWorker(void) { /* * Check for the VBOX_ASSERT variable. */ const char *psz = RTEnvGet("VBOX_ASSERT"); /* not defined => default behaviour. */ if (!psz) return true; /* 'breakpoint' or 'panic' means default behaviour. */ if (!strcmp(psz, "breakpoint") || !strcmp(psz, "panic")) return true; #ifdef VBOX_RTASSERT_WITH_GDB /* 'gdb' - means try launch a gdb session in xterm. */ if (!strcmp(psz, "gdb")) { /* Did we already fire up gdb? If so, just hit the breakpoint. */ static bool volatile s_fAlreadyLaunchedGdb = false; if (ASMAtomicUoReadBool(&s_fAlreadyLaunchedGdb)) return true; /* Try find a suitable terminal program. */ const char *pszTerm = RTEnvGet("VBOX_ASSERT_TERM"); if ( !pszTerm || !RTPathExists(pszTerm)) { pszTerm = "/usr/bin/gnome-terminal"; if (!RTPathExists(pszTerm)) { pszTerm = "/usr/X11R6/bin/xterm"; if (!RTPathExists(pszTerm)) { pszTerm ="/usr/bin/xterm"; if (!RTPathExists(pszTerm)) return true; } } } /* And find gdb. */ const char *pszGdb = RTEnvGet("VBOX_ASSERT_GDB"); if ( !pszGdb || !RTPathExists(pszGdb)) { pszGdb = "/usr/bin/gdb"; if (!RTPathExists(pszGdb)) pszGdb = "gdb"; } /* Try spawn the process. */ char szCmd[512]; size_t cch = RTStrPrintf(szCmd, sizeof(szCmd), "%s -p %d ", pszGdb, RTProcSelf()); if (cch < sizeof(szCmd)) { char *pszExecName = &szCmd[cch]; if (!RTProcGetExecutablePath(pszExecName, sizeof(szCmd) - cch)) *pszExecName = '\0'; } const char *apszArgs[] = { pszTerm, "-e", szCmd, NULL }; RTPROCESS Process; int rc = RTProcCreate(apszArgs[0], &apszArgs[0], RTENV_DEFAULT, 0, &Process); if (RT_FAILURE(rc)) return false; ASMAtomicWriteBool(&s_fAlreadyLaunchedGdb, true); /* Wait for gdb to attach. */ RTThreadSleep(15000); return true; } #endif /* '*' - don't hit the breakpoint. */ return false; }
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; }
int main() { /* * Init the runtime and stuff. */ RTTEST hTest; int rc = RTTestInitAndCreate("tstFork", &hTest); if (rc) return rc; RTTestBanner(hTest); #ifdef RT_OS_WINDOWS RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Skipped\n"); #else /* * Get values that are supposed to or change across the fork. */ RTPROCESS const ProcBefore = RTProcSelf(); /* * Fork. */ pid_t pid = fork(); if (pid == 0) { /* * Check that the values has changed. */ rc = 0; if (ProcBefore == RTProcSelf()) { RTTestFailed(hTest, "%RTproc == %RTproc [child]", ProcBefore, RTProcSelf()); rc = 1; } return rc; } if (pid != -1) { /* * Check that the values didn't change. */ RTTEST_CHECK(hTest, ProcBefore == RTProcSelf()); /* * Wait for the child. */ rc = 1; while ( waitpid(pid, &rc, 0) && errno == EINTR) rc = 1; if (!WIFEXITED(rc) || WEXITSTATUS(rc) != 0) RTTestFailed(hTest, "rc=%#x", rc); } else RTTestFailed(hTest, "fork() failed: %d - %s", errno, strerror(errno)); #endif /* * Summary */ return RTTestSummaryAndDestroy(hTest); }