Logo Search packages:      
Sourcecode: virtualbox-ose version File versions

int VBOXCALL supdrvIOCtl ( unsigned int  uIOCtl,
PSUPDRVDEVEXT  pDevExt,
PSUPDRVSESSION  pSession,
void *  pvIn,
unsigned  cbIn,
void *  pvOut,
unsigned  cbOut,
unsigned *  pcbReturned 
)

I/O Control worker.

Returns:
0 on success.

One of the SUPDRV_ERR_* on failure.

Parameters:
uIOCtl Function number.
pDevExt Device extention.
pSession Session data.
pvIn Input data.
cbIn Size of input data.
pvOut Output data. IMPORTANT! This buffer may be shared with the input data, thus no writing before done reading input data!!!
cbOut Size of output data.
pcbReturned Size of the returned data.

Todo:
A more secure cookie negotiation?

Todo:
this interface needs re-doing, we're accessing Ring-3 buffers directly here!

Todo:
address the pvArg problem!

Definition at line 627 of file SUPDRVShared.c.

References SUPLDRLOAD_IN::achImage, SUPQUERYFUNCS_OUT::aFunctions, SUPLOWALLOC_OUT::aPages, SUPPINPAGES_OUT::aPages, AssertMsg, SUPLDRLOAD_IN::cbImage, SUPLDROPEN_IN::cbImage, SUPLDRLOAD_IN::cbStrTab, SUPQUERYFUNCS_OUT::cFunctions, SUPCOOKIE_OUT::cFunctions, SUPLOWALLOC_IN::cPages, SUPCONTALLOC_IN::cPages, SUPPINPAGES_IN::cPages, SUPLDRLOAD_IN::cSymbols, dprintf, ELEMENTS, SUPCONTALLOC_OUT::HCPhys, SUPGIPMAP_OUT::HCPhysGip, NULL, SUPLDRSYM::offName, SUPLDRLOAD_IN::offStrTab, SUPLDRLOAD_IN::offSymbols, PAGE_SIZE, SUPDRVDEVEXT::pGip, SUPCALLVMMR0_IN::pvArg, SUPSETVMFORFAST_IN::pVMR0, SUPCALLVMMR0_IN::pVMR0, SUPLOWALLOC_OUT::pvR0, SUPCONTALLOC_OUT::pvR0, SUPLOWFREE_IN::pvR3, SUPLOWALLOC_OUT::pvR3, SUPCONTFREE_IN::pvR3, SUPCONTALLOC_OUT::pvR3, SUPUNPINPAGES_IN::pvR3, SUPPINPAGES_IN::pvR3, SUPLDRGETSYMBOL_OUT::pvSymbol, SUPCALLVMMR0_OUT::rc, RT_MIN, RT_OFFSETOF, strncmp(), SUP_IOCTL_CALL_VMMR0, SUP_IOCTL_CONT_ALLOC, SUP_IOCTL_CONT_FREE, SUP_IOCTL_COOKIE, SUP_IOCTL_GET_PAGING_MODE, SUP_IOCTL_GIP_MAP, SUP_IOCTL_GIP_UNMAP, SUP_IOCTL_IDT_INSTALL, SUP_IOCTL_IDT_REMOVE, SUP_IOCTL_LDR_FREE, SUP_IOCTL_LDR_GET_SYMBOL, SUP_IOCTL_LDR_LOAD, SUP_IOCTL_LDR_OPEN, SUP_IOCTL_LOW_ALLOC, SUP_IOCTL_LOW_FREE, SUP_IOCTL_PINPAGES, SUP_IOCTL_QUERY_FUNCS, SUP_IOCTL_SET_VM_FOR_FAST, SUP_IOCTL_UNPINPAGES, SUPCOOKIE_MAGIC, SUPDRV_ERR_GENERAL_FAILURE, SUPDRV_ERR_INVALID_MAGIC, SUPDRV_ERR_INVALID_PARAM, SUPDRV_ERR_INVALID_POINTER, SUPDRV_ERR_VERSION_MISMATCH, SUPDRVIOC_VERSION, supdrvIOCtl_GetPagingMode(), supdrvIOCtl_IdtInstall(), supdrvIOCtl_IdtRemoveAll(), supdrvIOCtl_LdrFree(), supdrvIOCtl_LdrGetSymbol(), supdrvIOCtl_LdrLoad(), supdrvIOCtl_LdrOpen(), SUPCOOKIE_IN::szMagic, SUPLDROPEN_IN::szName, SUPLDRGETSYMBOL_IN::szSymbol, SUPSETVMFORFAST_IN::u32Cookie, SUPGIPUNMAP_IN::u32Cookie, SUPGIPMAP_IN::u32Cookie, SUPLOWFREE_IN::u32Cookie, SUPLOWALLOC_IN::u32Cookie, SUPGETPAGINGMODE_IN::u32Cookie, SUPCALLVMMR0_IN::u32Cookie, SUPLDRGETSYMBOL_IN::u32Cookie, SUPLDRFREE_IN::u32Cookie, SUPLDRLOAD_IN::u32Cookie, SUPLDROPEN_IN::u32Cookie, SUPCONTFREE_IN::u32Cookie, SUPCONTALLOC_IN::u32Cookie, SUPUNPINPAGES_IN::u32Cookie, SUPPINPAGES_IN::u32Cookie, SUPIDTREMOVE_IN::u32Cookie, SUPIDTINSTALL_IN::u32Cookie, SUPQUERYFUNCS_IN::u32Cookie, SUPDRVDEVEXT::u32Cookie, SUPCOOKIE_OUT::u32Cookie, SUPCOOKIE_OUT::u32DriverVersion, SUPCOOKIE_IN::u32MinVersion, SUPCOOKIE_IN::u32ReqVersion, SUPSETVMFORFAST_IN::u32SessionCookie, SUPGIPUNMAP_IN::u32SessionCookie, SUPGIPMAP_IN::u32SessionCookie, SUPLOWFREE_IN::u32SessionCookie, SUPLOWALLOC_IN::u32SessionCookie, SUPGETPAGINGMODE_IN::u32SessionCookie, SUPCALLVMMR0_IN::u32SessionCookie, SUPLDRGETSYMBOL_IN::u32SessionCookie, SUPLDRFREE_IN::u32SessionCookie, SUPLDRLOAD_IN::u32SessionCookie, SUPLDROPEN_IN::u32SessionCookie, SUPCONTFREE_IN::u32SessionCookie, SUPCONTALLOC_IN::u32SessionCookie, SUPUNPINPAGES_IN::u32SessionCookie, SUPPINPAGES_IN::u32SessionCookie, SUPIDTREMOVE_IN::u32SessionCookie, SUPIDTINSTALL_IN::u32SessionCookie, SUPQUERYFUNCS_IN::u32SessionCookie, SUPCOOKIE_OUT::u32SessionCookie, SUPCOOKIE_OUT::u32SessionVersion, SUPIDTINSTALL_OUT::u8Idt, and SUPCALLVMMR0_IN::uOperation.

Referenced by VBoxDrvSolarisIOCtlSlow(), VBoxSupDrvDeviceControl(), VBoxSupDrvDeviceControlSlow(), and VBoxSupDrvIOCtlSlow().

{
    *pcbReturned = 0;
    switch (uIOCtl)
    {
        case SUP_IOCTL_COOKIE:
        {
            PSUPCOOKIE_IN  pIn = (PSUPCOOKIE_IN)pvIn;
            PSUPCOOKIE_OUT pOut = (PSUPCOOKIE_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != sizeof(*pOut))
            {
                OSDBGPRINT(("SUP_IOCTL_COOKIE: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                            (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (strncmp(pIn->szMagic, SUPCOOKIE_MAGIC, sizeof(pIn->szMagic)))
            {
                OSDBGPRINT(("SUP_IOCTL_COOKIE: invalid magic %.16s\n", pIn->szMagic));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Match the version.
             * The current logic is very simple, match the major interface version.
             */
            if (    pIn->u32MinVersion > SUPDRVIOC_VERSION
                ||  (pIn->u32MinVersion & 0xffff0000) != (SUPDRVIOC_VERSION & 0xffff0000))
            {
                OSDBGPRINT(("SUP_IOCTL_COOKIE: Version mismatch. Requested: %#x  Min: %#x  Current: %#x\n",
                            pIn->u32ReqVersion, pIn->u32MinVersion, SUPDRVIOC_VERSION));
                pOut->u32Cookie         = 0xffffffff;
                pOut->u32SessionCookie  = 0xffffffff;
                pOut->u32SessionVersion = 0xffffffff;
                pOut->u32DriverVersion  = SUPDRVIOC_VERSION;
                pOut->pSession          = NULL;
                pOut->cFunctions        = 0;
                *pcbReturned = sizeof(*pOut);
                return SUPDRV_ERR_VERSION_MISMATCH;
            }

            /*
             * Fill in return data and be gone.
             * N.B. The first one to change SUPDRVIOC_VERSION shall makes sure that
             *      u32SessionVersion <= u32ReqVersion!
             */
            /** @todo A more secure cookie negotiation? */
            pOut->u32Cookie         = pDevExt->u32Cookie;
            pOut->u32SessionCookie  = pSession->u32Cookie;
            pOut->u32SessionVersion = SUPDRVIOC_VERSION;
            pOut->u32DriverVersion  = SUPDRVIOC_VERSION;
            pOut->pSession          = pSession;
            pOut->cFunctions        = sizeof(g_aFunctions) / sizeof(g_aFunctions[0]);
            *pcbReturned = sizeof(*pOut);
            return 0;
        }


        case SUP_IOCTL_QUERY_FUNCS:
        {
            unsigned            cFunctions;
            PSUPQUERYFUNCS_IN   pIn = (PSUPQUERYFUNCS_IN)pvIn;
            PSUPQUERYFUNCS_OUT  pOut = (PSUPQUERYFUNCS_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut < sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_QUERY_FUNCS: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie )
            {
                dprintf(("SUP_IOCTL_QUERY_FUNCS: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Copy the functions.
             */
            cFunctions = (cbOut - RT_OFFSETOF(SUPQUERYFUNCS_OUT, aFunctions)) / sizeof(pOut->aFunctions[0]);
            cFunctions = RT_MIN(cFunctions, ELEMENTS(g_aFunctions));
            AssertMsg(cFunctions == ELEMENTS(g_aFunctions),
                      ("Why aren't R3 querying all the functions!?! cFunctions=%d while there are %d available\n",
                       cFunctions, ELEMENTS(g_aFunctions)));
            pOut->cFunctions = cFunctions;
            memcpy(&pOut->aFunctions[0], g_aFunctions, sizeof(pOut->aFunctions[0]) * cFunctions);
            *pcbReturned = RT_OFFSETOF(SUPQUERYFUNCS_OUT, aFunctions[cFunctions]);
            return 0;
        }


        case SUP_IOCTL_IDT_INSTALL:
        {
            PSUPIDTINSTALL_IN   pIn = (PSUPIDTINSTALL_IN)pvIn;
            PSUPIDTINSTALL_OUT  pOut = (PSUPIDTINSTALL_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_INSTALL: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie )
            {
                dprintf(("SUP_IOCTL_INSTALL: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie,  pDevExt->u32Cookie,
                         pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            *pcbReturned = sizeof(*pOut);
#ifndef VBOX_WITHOUT_IDT_PATCHING
            return supdrvIOCtl_IdtInstall(pDevExt, pSession, pIn, pOut);
#else
            pOut->u8Idt = 3;
            return 0;
#endif
        }


        case SUP_IOCTL_IDT_REMOVE:
        {
            PSUPIDTREMOVE_IN   pIn = (PSUPIDTREMOVE_IN)pvIn;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != 0)
            {
                dprintf(("SUP_IOCTL_REMOVE: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie )
            {
                dprintf(("SUP_IOCTL_REMOVE: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

#ifndef VBOX_WITHOUT_IDT_PATCHING
            return supdrvIOCtl_IdtRemoveAll(pDevExt, pSession);
#else
            return 0;
#endif
        }


        case SUP_IOCTL_PINPAGES:
        {
            int                 rc;
            PSUPPINPAGES_IN     pIn = (PSUPPINPAGES_IN)pvIn;
            PSUPPINPAGES_OUT    pOut = (PSUPPINPAGES_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut < sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_PINPAGES: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie )
            {
                dprintf(("SUP_IOCTL_PINPAGES: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie,  pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }
            if (pIn->cPages <= 0 || !pIn->pvR3)
            {
                dprintf(("SUP_IOCTL_PINPAGES: Illegal request %p %d\n", (void *)pIn->pvR3, pIn->cPages));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if ((unsigned)RT_OFFSETOF(SUPPINPAGES_OUT, aPages[pIn->cPages]) > cbOut)
            {
                dprintf(("SUP_IOCTL_PINPAGES: Output buffer is too small! %d required %d passed in.\n",
                         RT_OFFSETOF(SUPPINPAGES_OUT, aPages[pIn->cPages]), cbOut));
                return SUPDRV_ERR_INVALID_PARAM;
            }

            /*
             * Execute.
             */
            *pcbReturned = RT_OFFSETOF(SUPPINPAGES_OUT, aPages[pIn->cPages]);
            rc = SUPR0LockMem(pSession, pIn->pvR3, pIn->cPages, &pOut->aPages[0]);
            if (rc)
                *pcbReturned = 0;
            return rc;
        }


        case SUP_IOCTL_UNPINPAGES:
        {
            PSUPUNPINPAGES_IN   pIn = (PSUPUNPINPAGES_IN)pvIn;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != 0)
            {
                dprintf(("SUP_IOCTL_UNPINPAGES: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_UNPINPAGES: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Execute.
             */
            return SUPR0UnlockMem(pSession, pIn->pvR3);
        }

        case SUP_IOCTL_CONT_ALLOC:
        {
            int                 rc;
            PSUPCONTALLOC_IN    pIn = (PSUPCONTALLOC_IN)pvIn;
            PSUPCONTALLOC_OUT   pOut = (PSUPCONTALLOC_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut < sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_CONT_ALLOC: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie )
            {
                dprintf(("SUP_IOCTL_CONT_ALLOC: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Execute.
             */
            rc = SUPR0ContAlloc(pSession, pIn->cPages, &pOut->pvR0, &pOut->pvR3, &pOut->HCPhys);
            if (!rc)
                *pcbReturned = sizeof(*pOut);
            return rc;
        }


        case SUP_IOCTL_CONT_FREE:
        {
            PSUPCONTFREE_IN   pIn = (PSUPCONTFREE_IN)pvIn;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != 0)
            {
                dprintf(("SUP_IOCTL_CONT_FREE: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_CONT_FREE: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Execute.
             */
            return SUPR0ContFree(pSession, (RTHCUINTPTR)pIn->pvR3);
        }


        case SUP_IOCTL_LDR_OPEN:
        {
            PSUPLDROPEN_IN  pIn = (PSUPLDROPEN_IN)pvIn;
            PSUPLDROPEN_OUT pOut = (PSUPLDROPEN_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_LDR_OPEN: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_LDR_OPEN: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }
            if (    pIn->cbImage <= 0
                ||  pIn->cbImage >= 16*1024*1024 /*16MB*/)
            {
                dprintf(("SUP_IOCTL_LDR_OPEN: Invalid size %d. (max is 16MB)\n", pIn->cbImage));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (!memchr(pIn->szName, '\0', sizeof(pIn->szName)))
            {
                dprintf(("SUP_IOCTL_LDR_OPEN: The image name isn't terminated!\n"));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (!pIn->szName[0])
            {
                dprintf(("SUP_IOCTL_LDR_OPEN: The image name is too short\n"));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (strpbrk(pIn->szName, ";:()[]{}/\\|&*%#@!~`\"'"))
            {
                dprintf(("SUP_IOCTL_LDR_OPEN: The name is invalid '%s'\n", pIn->szName));
                return SUPDRV_ERR_INVALID_PARAM;
            }

            *pcbReturned = sizeof(*pOut);
            return supdrvIOCtl_LdrOpen(pDevExt, pSession, pIn, pOut);
        }


        case SUP_IOCTL_LDR_LOAD:
        {
            PSUPLDRLOAD_IN  pIn = (PSUPLDRLOAD_IN)pvIn;

            /*
             * Validate.
             */
            if (    cbIn <= sizeof(*pIn)
                ||  cbOut != 0)
            {
                dprintf(("SUP_IOCTL_LDR_LOAD: Invalid input/output sizes. cbIn=%ld expected greater than %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_LDR_LOAD: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }
            if ((unsigned)RT_OFFSETOF(SUPLDRLOAD_IN, achImage[pIn->cbImage]) > cbIn)
            {
                dprintf(("SUP_IOCTL_LDR_LOAD: Invalid size %d. InputBufferLength=%d\n",
                         pIn->cbImage, cbIn));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (pIn->cSymbols > 16384)
            {
                dprintf(("SUP_IOCTL_LDR_LOAD: Too many symbols. cSymbols=%u max=16384\n", pIn->cSymbols));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->cSymbols
                &&  (   pIn->offSymbols >= pIn->cbImage
                     || pIn->offSymbols + pIn->cSymbols * sizeof(SUPLDRSYM) > pIn->cbImage)
               )
            {
                dprintf(("SUP_IOCTL_LDR_LOAD: symbol table is outside the image bits! offSymbols=%u cSymbols=%d cbImage=%d\n",
                         pIn->offSymbols, pIn->cSymbols, pIn->cbImage));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->cbStrTab
                &&  (   pIn->offStrTab >= pIn->cbImage
                     || pIn->offStrTab + pIn->cbStrTab > pIn->cbImage
                     || pIn->offStrTab + pIn->cbStrTab < pIn->offStrTab)
               )
            {
                dprintf(("SUP_IOCTL_LDR_LOAD: string table is outside the image bits! offStrTab=%u cbStrTab=%d cbImage=%d\n",
                         pIn->offStrTab, pIn->cbStrTab, pIn->cbImage));
                return SUPDRV_ERR_INVALID_PARAM;
            }

            if (pIn->cSymbols)
            {
                uint32_t    i;
                PSUPLDRSYM  paSyms = (PSUPLDRSYM)&pIn->achImage[pIn->offSymbols];
                for (i = 0; i < pIn->cSymbols; i++)
                {
                    if (paSyms[i].offSymbol >= pIn->cbImage)
                    {
                        dprintf(("SUP_IOCTL_LDR_LOAD: symbol i=%d has an invalid symbol offset: %#x (max=%#x)\n",
                                 i, paSyms[i].offSymbol, pIn->cbImage));
                        return SUPDRV_ERR_INVALID_PARAM;
                    }
                    if (paSyms[i].offName >= pIn->cbStrTab)
                    {
                        dprintf(("SUP_IOCTL_LDR_LOAD: symbol i=%d has an invalid name offset: %#x (max=%#x)\n",
                                 i, paSyms[i].offName, pIn->cbStrTab));
                        return SUPDRV_ERR_INVALID_PARAM;
                    }
                    if (!memchr(&pIn->achImage[pIn->offStrTab + paSyms[i].offName], '\0', pIn->cbStrTab - paSyms[i].offName))
                    {
                        dprintf(("SUP_IOCTL_LDR_LOAD: symbol i=%d has an unterminated name! offName=%#x (max=%#x)\n",
                                 i, paSyms[i].offName, pIn->cbStrTab));
                        return SUPDRV_ERR_INVALID_PARAM;
                    }
                }
            }

            return supdrvIOCtl_LdrLoad(pDevExt, pSession, pIn);
        }


        case SUP_IOCTL_LDR_FREE:
        {
            PSUPLDRFREE_IN  pIn = (PSUPLDRFREE_IN)pvIn;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != 0)
            {
                dprintf(("SUP_IOCTL_LDR_FREE: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_LDR_FREE: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            return supdrvIOCtl_LdrFree(pDevExt, pSession, pIn);
        }


        case SUP_IOCTL_LDR_GET_SYMBOL:
        {
            PSUPLDRGETSYMBOL_IN  pIn  = (PSUPLDRGETSYMBOL_IN)pvIn;
            PSUPLDRGETSYMBOL_OUT pOut = (PSUPLDRGETSYMBOL_OUT)pvOut;
            char                *pszEnd;

            /*
             * Validate.
             */
            if (    cbIn < (unsigned)RT_OFFSETOF(SUPLDRGETSYMBOL_IN, szSymbol[2])
                ||  cbOut != sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_LDR_GET_SYMBOL: Invalid input/output sizes. cbIn=%d expected >=%d. cbOut=%d expected at%d.\n",
                         cbIn, RT_OFFSETOF(SUPLDRGETSYMBOL_IN, szSymbol[2]), cbOut, 0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_LDR_GET_SYMBOL: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }
            pszEnd = memchr(pIn->szSymbol, '\0', cbIn - RT_OFFSETOF(SUPLDRGETSYMBOL_IN, szSymbol));
            if (!pszEnd)
            {
                dprintf(("SUP_IOCTL_LDR_GET_SYMBOL: The symbol name isn't terminated!\n"));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (pszEnd - &pIn->szSymbol[0] >= 1024)
            {
                dprintf(("SUP_IOCTL_LDR_GET_SYMBOL: The symbol name too long (%ld chars, max is %d)!\n",
                         (long)(pszEnd - &pIn->szSymbol[0]), 1024));
                return SUPDRV_ERR_INVALID_PARAM;
            }

            pOut->pvSymbol = NULL;
            *pcbReturned = sizeof(*pOut);
            return supdrvIOCtl_LdrGetSymbol(pDevExt, pSession, pIn, pOut);
        }


        /** @todo this interface needs re-doing, we're accessing Ring-3 buffers directly here! */
        case SUP_IOCTL_CALL_VMMR0:
        {
            PSUPCALLVMMR0_IN    pIn = (PSUPCALLVMMR0_IN)pvIn;
            PSUPCALLVMMR0_OUT   pOut = (PSUPCALLVMMR0_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_CALL_VMMR0: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie )
            {
                dprintf(("SUP_IOCTL_CALL_VMMR0: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Do we have an entrypoint?
             */
            if (!pDevExt->pfnVMMR0Entry)
                return SUPDRV_ERR_GENERAL_FAILURE;

            /*
             * Execute.
             */
            pOut->rc = pDevExt->pfnVMMR0Entry(pIn->pVMR0, pIn->uOperation, (void *)pIn->pvArg); /** @todo address the pvArg problem! */
            *pcbReturned = sizeof(*pOut);
            return 0;
        }


        case SUP_IOCTL_GET_PAGING_MODE:
        {
            int                     rc;
            PSUPGETPAGINGMODE_IN    pIn = (PSUPGETPAGINGMODE_IN)pvIn;
            PSUPGETPAGINGMODE_OUT   pOut = (PSUPGETPAGINGMODE_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_GET_PAGING_MODE: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie )
            {
                dprintf(("SUP_IOCTL_GET_PAGING_MODE: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Execute.
             */
            *pcbReturned = sizeof(*pOut);
            rc = supdrvIOCtl_GetPagingMode(pOut);
            if (rc)
                *pcbReturned = 0;
            return rc;
        }


        case SUP_IOCTL_LOW_ALLOC:
        {
            int                 rc;
            PSUPLOWALLOC_IN     pIn = (PSUPLOWALLOC_IN)pvIn;
            PSUPLOWALLOC_OUT    pOut = (PSUPLOWALLOC_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut < sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_LOW_ALLOC: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)sizeof(*pOut)));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie )
            {
                dprintf(("SUP_IOCTL_LOW_ALLOC: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie,  pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }
            if ((unsigned)RT_OFFSETOF(SUPLOWALLOC_OUT, aPages[pIn->cPages]) > cbOut)
            {
                dprintf(("SUP_IOCTL_LOW_ALLOC: Output buffer is too small! %d required %d passed in.\n",
                         RT_OFFSETOF(SUPLOWALLOC_OUT, aPages[pIn->cPages]), cbOut));
                return SUPDRV_ERR_INVALID_PARAM;
            }

            /*
             * Execute.
             */
            *pcbReturned = RT_OFFSETOF(SUPLOWALLOC_OUT, aPages[pIn->cPages]);
            rc = SUPR0LowAlloc(pSession, pIn->cPages, &pOut->pvR0, &pOut->pvR3, &pOut->aPages[0]);
            if (rc)
                *pcbReturned = 0;
            return rc;
        }


        case SUP_IOCTL_LOW_FREE:
        {
            PSUPLOWFREE_IN  pIn = (PSUPLOWFREE_IN)pvIn;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != 0)
            {
                dprintf(("SUP_IOCTL_LOW_FREE: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_LOW_FREE: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Execute.
             */
            return SUPR0LowFree(pSession, (RTHCUINTPTR)pIn->pvR3);
        }


        case SUP_IOCTL_GIP_MAP:
        {
            int             rc;
            PSUPGIPMAP_IN   pIn = (PSUPGIPMAP_IN)pvIn;
            PSUPGIPMAP_OUT  pOut = (PSUPGIPMAP_OUT)pvOut;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != sizeof(*pOut))
            {
                dprintf(("SUP_IOCTL_GIP_MAP: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_GIP_MAP: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Execute.
             */
            rc = SUPR0GipMap(pSession, &pOut->pGipR3, &pOut->HCPhysGip);
            if (!rc)
            {
                pOut->pGipR0 = pDevExt->pGip;
                *pcbReturned = sizeof(*pOut);
            }
            return rc;
        }


        case SUP_IOCTL_GIP_UNMAP:
        {
            PSUPGIPUNMAP_IN pIn = (PSUPGIPUNMAP_IN)pvIn;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != 0)
            {
                dprintf(("SUP_IOCTL_GIP_UNMAP: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_GIP_UNMAP: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }

            /*
             * Execute.
             */
            return SUPR0GipUnmap(pSession);
        }


        case SUP_IOCTL_SET_VM_FOR_FAST:
        {
            PSUPSETVMFORFAST_IN pIn = (PSUPSETVMFORFAST_IN)pvIn;

            /*
             * Validate.
             */
            if (    cbIn != sizeof(*pIn)
                ||  cbOut != 0)
            {
                dprintf(("SUP_IOCTL_SET_VM_FOR_FAST: Invalid input/output sizes. cbIn=%ld expected %ld. cbOut=%ld expected %ld.\n",
                         (long)cbIn, (long)sizeof(*pIn), (long)cbOut, (long)0));
                return SUPDRV_ERR_INVALID_PARAM;
            }
            if (    pIn->u32Cookie != pDevExt->u32Cookie
                ||  pIn->u32SessionCookie != pSession->u32Cookie)
            {
                dprintf(("SUP_IOCTL_SET_VM_FOR_FAST: Cookie mismatch {%#x,%#x} != {%#x,%#x}!\n",
                         pIn->u32Cookie, pDevExt->u32Cookie, pIn->u32SessionCookie, pSession->u32Cookie));
                return SUPDRV_ERR_INVALID_MAGIC;
            }
            if (    pIn->pVMR0 != NULL
                && (    !VALID_PTR(pIn->pVMR0)
                    ||  ((uintptr_t)pIn->pVMR0 & (PAGE_SIZE - 1))
                   )
                )
            {
                dprintf(("SUP_IOCTL_SET_VM_FOR_FAST: pVMR0=%p! Must be a valid, page aligned, pointer.\n", pIn->pVMR0));
                return SUPDRV_ERR_INVALID_POINTER;
            }

            /*
             * Execute.
             */
#ifndef VBOX_WITHOUT_IDT_PATCHING
            OSDBGPRINT(("SUP_IOCTL_SET_VM_FOR_FAST: !VBOX_WITHOUT_IDT_PATCHING\n"));
            return SUPDRV_ERR_GENERAL_FAILURE;
#else
            pSession->pVM = pIn->pVMR0;
            return 0;
#endif
        }


        default:
            dprintf(("Unknown IOCTL %#x\n", uIOCtl));
            break;
    }
    return SUPDRV_ERR_GENERAL_FAILURE;
}


Generated by  Doxygen 1.6.0   Back to index