Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vfio/platform: store mapped memory in region, instead of an on-stack copy

vfio_platform_{read,write}_mmio() call ioremap_nocache() to map
a region of io memory, which they store in struct vfio_platform_region to
be eventually re-used, or unmapped by vfio_platform_regions_cleanup().

These functions receive a copy of their struct vfio_platform_region
argument on the stack - so these mapped areas are always allocated, and
always leaked.

Pass this argument as a pointer instead.

Fixes: 6e3f26456009 "vfio/platform: read and write support for the device fd"
Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Tested-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>

authored by

James Morse and committed by
Alex Williamson
1b4bb2ea 4644321f

+18 -18
+18 -18
drivers/vfio/platform/vfio_platform_common.c
··· 307 307 return -ENOTTY; 308 308 } 309 309 310 - static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg, 310 + static ssize_t vfio_platform_read_mmio(struct vfio_platform_region *reg, 311 311 char __user *buf, size_t count, 312 312 loff_t off) 313 313 { 314 314 unsigned int done = 0; 315 315 316 - if (!reg.ioaddr) { 317 - reg.ioaddr = 318 - ioremap_nocache(reg.addr, reg.size); 316 + if (!reg->ioaddr) { 317 + reg->ioaddr = 318 + ioremap_nocache(reg->addr, reg->size); 319 319 320 - if (!reg.ioaddr) 320 + if (!reg->ioaddr) 321 321 return -ENOMEM; 322 322 } 323 323 ··· 327 327 if (count >= 4 && !(off % 4)) { 328 328 u32 val; 329 329 330 - val = ioread32(reg.ioaddr + off); 330 + val = ioread32(reg->ioaddr + off); 331 331 if (copy_to_user(buf, &val, 4)) 332 332 goto err; 333 333 ··· 335 335 } else if (count >= 2 && !(off % 2)) { 336 336 u16 val; 337 337 338 - val = ioread16(reg.ioaddr + off); 338 + val = ioread16(reg->ioaddr + off); 339 339 if (copy_to_user(buf, &val, 2)) 340 340 goto err; 341 341 ··· 343 343 } else { 344 344 u8 val; 345 345 346 - val = ioread8(reg.ioaddr + off); 346 + val = ioread8(reg->ioaddr + off); 347 347 if (copy_to_user(buf, &val, 1)) 348 348 goto err; 349 349 ··· 376 376 return -EINVAL; 377 377 378 378 if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO) 379 - return vfio_platform_read_mmio(vdev->regions[index], 379 + return vfio_platform_read_mmio(&vdev->regions[index], 380 380 buf, count, off); 381 381 else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO) 382 382 return -EINVAL; /* not implemented */ ··· 384 384 return -EINVAL; 385 385 } 386 386 387 - static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg, 387 + static ssize_t vfio_platform_write_mmio(struct vfio_platform_region *reg, 388 388 const char __user *buf, size_t count, 389 389 loff_t off) 390 390 { 391 391 unsigned int done = 0; 392 392 393 - if (!reg.ioaddr) { 394 - reg.ioaddr = 395 - ioremap_nocache(reg.addr, reg.size); 393 + if (!reg->ioaddr) { 394 + reg->ioaddr = 395 + ioremap_nocache(reg->addr, reg->size); 396 396 397 - if (!reg.ioaddr) 397 + if (!reg->ioaddr) 398 398 return -ENOMEM; 399 399 } 400 400 ··· 406 406 407 407 if (copy_from_user(&val, buf, 4)) 408 408 goto err; 409 - iowrite32(val, reg.ioaddr + off); 409 + iowrite32(val, reg->ioaddr + off); 410 410 411 411 filled = 4; 412 412 } else if (count >= 2 && !(off % 2)) { ··· 414 414 415 415 if (copy_from_user(&val, buf, 2)) 416 416 goto err; 417 - iowrite16(val, reg.ioaddr + off); 417 + iowrite16(val, reg->ioaddr + off); 418 418 419 419 filled = 2; 420 420 } else { ··· 422 422 423 423 if (copy_from_user(&val, buf, 1)) 424 424 goto err; 425 - iowrite8(val, reg.ioaddr + off); 425 + iowrite8(val, reg->ioaddr + off); 426 426 427 427 filled = 1; 428 428 } ··· 452 452 return -EINVAL; 453 453 454 454 if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO) 455 - return vfio_platform_write_mmio(vdev->regions[index], 455 + return vfio_platform_write_mmio(&vdev->regions[index], 456 456 buf, count, off); 457 457 else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO) 458 458 return -EINVAL; /* not implemented */