Changeset 69936 in vbox
- Timestamp:
- Dec 5, 2017 1:32:16 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119425
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-netbsd.c
r69812 r69936 126 126 static int VBoxGuestNetBSDClose(struct file *fp); 127 127 static int VBoxGuestNetBSDIOCtl(struct file *fp, u_long cmd, void *addr); 128 static int VBoxGuestNetBSDIOCtlSlow(struct vboxguest_session *session, u_long command, void *data); 128 129 static int VBoxGuestNetBSDPoll(struct file *fp, int events); 129 130 static void VBoxGuestNetBSDAttach(device_t, device_t, void*); … … 262 263 { 263 264 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 272 static int VBoxGuestNetBSDIOCtlSlow(struct vboxguest_session *session, u_long command, void *data) 273 { 264 274 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); 323 345 } 324 346 … … 326 348 * Process the IOCtl. 327 349 */ 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); 330 351 if (RT_SUCCESS(rc)) 331 352 { 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) 334 359 { 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); 338 370 } 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; 355 384 } 356 385
Note:
See TracChangeset
for help on using the changeset viewer.