VirtualBox

Changeset 69936 in vbox


Ignore:
Timestamp:
Dec 5, 2017 1:32:16 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119425
Message:

VBoxGuest-netbsd.c: catch up with ioctl changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-netbsd.c

    r69812 r69936  
    126126static int VBoxGuestNetBSDClose(struct file *fp);
    127127static int VBoxGuestNetBSDIOCtl(struct file *fp, u_long cmd, void *addr);
     128static int VBoxGuestNetBSDIOCtlSlow(struct vboxguest_session *session, u_long command, void *data);
    128129static int VBoxGuestNetBSDPoll(struct file *fp, int events);
    129130static void VBoxGuestNetBSDAttach(device_t, device_t, void*);
     
    262263{
    263264    struct vboxguest_session *session = fp->f_data;
     265
     266    if (VBGL_IOCTL_IS_FAST(command))
     267        return VGDrvCommonIoCtlFast(command, &g_DevExt, session->session);
     268
     269    return VBoxGuestNetBSDIOCtlSlow(session, command, data);
     270}
     271
     272static int VBoxGuestNetBSDIOCtlSlow(struct vboxguest_session *session, u_long command, void *data)
     273{
    264274    vboxguest_softc *vboxguest = session->sc;
    265 
    266     int rc = 0;
    267 
    268     LogFlow((DEVICE_NAME ": %s: command=%#lx data=%p\n",
    269              __func__, command, data));
    270 
    271     /*
    272      * Validate the request wrapper.
    273      */
    274     if (IOCPARM_LEN(command) != sizeof(VBGLBIGREQ))
    275     {
    276         Log((DEVICE_NAME ": %s: bad request %#lx size=%lu expected=%zu\n",
    277              __func__, command, IOCPARM_LEN(command), sizeof(VBGLBIGREQ)));
    278         return ENOTTY;
    279     }
    280 
    281     PVBGLBIGREQ ReqWrap = (PVBGLBIGREQ)data;
    282     if (ReqWrap->u32Magic != VBGLBIGREQ_MAGIC)
    283     {
    284         Log((DEVICE_NAME ": %s: bad magic %#" PRIx32 "; pArg=%p Cmd=%#lx\n",
    285              __func__, ReqWrap->u32Magic, data, command));
    286         return EINVAL;
    287     }
    288     if (RT_UNLIKELY(   ReqWrap->cbData == 0
    289                     || ReqWrap->cbData > _1M*16))
    290     {
    291         Log((DEVICE_NAME ": %s: bad size %" PRIu32 "; pArg=%p Cmd=%#lx\n",
    292              __func__, ReqWrap->cbData, data, command));
    293         return EINVAL;
    294     }
    295 
    296     /*
    297      * Read the request.
    298      */
    299     void *pvBuf = RTMemTmpAlloc(ReqWrap->cbData);
    300     if (RT_UNLIKELY(!pvBuf))
    301     {
    302         Log((DEVICE_NAME ": %s: RTMemTmpAlloc failed to alloc %" PRIu32 " bytes.\n",
    303              __func__, ReqWrap->cbData));
    304         return ENOMEM;
    305     }
    306 
    307     rc = copyin((void *)(uintptr_t)ReqWrap->pvDataR3, pvBuf, ReqWrap->cbData);
    308     if (RT_UNLIKELY(rc))
    309     {
    310         RTMemTmpFree(pvBuf);
    311         Log((DEVICE_NAME ": %s: copyin failed; pvBuf=%p pArg=%p Cmd=%#lx. rc=%d\n",
    312              __func__, pvBuf, data, command, rc));
    313         aprint_error_dev(vboxguest->sc_dev, "copyin failed\n");
    314         return EFAULT;
    315     }
    316     if (RT_UNLIKELY(   ReqWrap->cbData != 0
    317                     && !VALID_PTR(pvBuf)))
    318     {
    319         RTMemTmpFree(pvBuf);
    320         Log((DEVICE_NAME ": %s: invalid pvBuf=%p\n",
    321              __func__, pvBuf));
    322         return EINVAL;
     275    size_t cbReq = IOCPARM_LEN(command);
     276    PVBGLREQHDR pHdr = NULL;
     277    void *pvUser = NULL;
     278    int err, rc;
     279
     280    LogFlow(("%s: command=%#lx data=%p\n", __func__, command, data));
     281
     282    /*
     283     * Buffered request?
     284     */
     285    if ((command & IOC_DIRMASK) == IOC_INOUT)
     286    {
     287        /* will be validated by VGDrvCommonIoCtl() */
     288        pHdr = (PVBGLREQHDR)data;
     289    }
     290
     291    /*
     292     * Big unbuffered request?  "data" is the userland pointer.
     293     */
     294    else if ((command & IOC_DIRMASK) == IOC_VOID && cbReq != 0)
     295    {
     296        /*
     297         * Read the header, validate it and figure out how much that
     298         * needs to be buffered.
     299         */
     300        VBGLREQHDR Hdr;
     301
     302        if (RT_UNLIKELY(cbReq < sizeof(Hdr)))
     303            return ENOTTY;
     304
     305        pvUser = data;
     306        err = copyin(pvUser, &Hdr, sizeof(Hdr));
     307        if (RT_UNLIKELY(err != 0))
     308            return err;
     309
     310        if (RT_UNLIKELY(Hdr.uVersion != VBGLREQHDR_VERSION))
     311            return ENOTTY;
     312
     313        if (cbReq > 16 * _1M)
     314            return EINVAL;
     315
     316        if (Hdr.cbOut == 0)
     317            Hdr.cbOut = Hdr.cbIn;
     318
     319        if (RT_UNLIKELY(   Hdr.cbIn  < sizeof(Hdr) || Hdr.cbIn  > cbReq
     320                        || Hdr.cbOut < sizeof(Hdr) || Hdr.cbOut > cbReq))
     321            return EINVAL;
     322
     323        /*
     324         * Allocate buffer and copy in the data.
     325         */
     326        cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut);
     327
     328        pHdr = (PVBGLREQHDR)RTMemTmpAlloc(cbReq);
     329        if (RT_UNLIKELY(pHdr == NULL))
     330        {
     331            LogRel(("%s: command=%#lx data=%p: unable to allocate %zu bytes\n",
     332                    __func__, command, data, cbReq));
     333            return ENOMEM;
     334        }
     335
     336        err = copyin(pvUser, pHdr, Hdr.cbIn);
     337        if (err != 0)
     338        {
     339            RTMemTmpFree(pHdr);
     340            return err;
     341        }
     342
     343        if (Hdr.cbIn < cbReq)
     344            memset((uint8_t *)pHdr + Hdr.cbIn, '\0', cbReq - Hdr.cbIn);
    323345    }
    324346
     
    326348     * Process the IOCtl.
    327349     */
    328     size_t cbDataReturned;
    329     rc = VGDrvCommonIoCtl(command, &g_DevExt, session->session, pvBuf, ReqWrap->cbData, &cbDataReturned);
     350    rc = VGDrvCommonIoCtl(command, &g_DevExt, session->session, pHdr, cbReq);
    330351    if (RT_SUCCESS(rc))
    331352    {
    332         rc = 0;
    333         if (RT_UNLIKELY(cbDataReturned > ReqWrap->cbData))
     353        err = 0;
     354
     355        /*
     356         * If unbuffered, copy back the result before returning.
     357         */
     358        if (pvUser != NULL)
    334359        {
    335             Log((DEVICE_NAME ": %s: too much output data %zu expected %" PRIu32 "\n",
    336                  __func__, cbDataReturned, ReqWrap->cbData));
    337             cbDataReturned = ReqWrap->cbData;
     360            size_t cbOut = pHdr->cbOut;
     361            if (cbOut > cbReq)
     362            {
     363                LogRel(("%s: command=%#lx data=%p: too much output: %zu > %zu\n",
     364                        __func__, command, data, cbOut, cbReq));
     365                cbOut = cbReq;
     366            }
     367
     368            err = copyout(pHdr, pvUser, cbOut);
     369            RTMemTmpFree(pHdr);
    338370        }
    339         if (cbDataReturned > 0)
    340         {
    341             rc = copyout(pvBuf, (void *)(uintptr_t)ReqWrap->pvDataR3, cbDataReturned);
    342             if (RT_UNLIKELY(rc))
    343             {
    344                 Log((DEVICE_NAME ": %s: copyout failed; pvBuf=%p pArg=%p. rc=%d\n",
    345                      __func__, pvBuf, data, rc));
    346             }
    347         }
    348     } else {
    349         Log((DEVICE_NAME ": %s: VGDrvCommonIoCtl failed. rc=%d\n",
    350              __func__, rc));
    351         rc = -rc;
    352     }
    353     RTMemTmpFree(pvBuf);
    354     return rc;
     371    }
     372    else
     373    {
     374        LogRel(("%s: command=%#lx data=%p: error %Rrc\n",
     375                __func__, command, data, rc));
     376
     377        if (pvUser != NULL)
     378            RTMemTmpFree(pHdr);
     379
     380        err = RTErrConvertToErrno(rc);
     381    }
     382
     383    return err;
    355384}
    356385
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette