/**
 * 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;
}
Exemple #7
0
/**
 * 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;
}
Exemple #11
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;
}
Exemple #14
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);
}
Exemple #18
0
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;
}
Exemple #19
0
/**
 * 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;
}
Exemple #20
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;
}
Exemple #21
0
/**
 * 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;
}
Exemple #22
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;
}
Exemple #23
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;
}
Exemple #24
0
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;
}
Exemple #25
0
/**
 * 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;
}
Exemple #29
0
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;
}
Exemple #30
0
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);
}