drm-shim: Better mmap offsets

Using the bo pointer address as the offset doesn't go over well when
someone is fuzzing you.  But we already have the mem_addr, we can simply
use that instead.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Reviewed-by: Emma Anholt <emma@anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16250>
This commit is contained in:
Rob Clark 2022-04-28 15:36:54 -07:00 committed by Marge Bot
parent 97f4e48717
commit c4b5ebe1fc
3 changed files with 22 additions and 10 deletions

View File

@ -82,6 +82,8 @@ drm_shim_device_init(void)
uint_key_hash,
uint_key_compare);
shim_device.offset_map = _mesa_hash_table_u64_create(NULL);
mtx_init(&shim_device.mem_lock, mtx_plain);
shim_device.mem_fd = memfd_create("shim mem", MFD_CLOEXEC);
@ -372,18 +374,16 @@ drm_shim_bo_get_handle(struct shim_fd *shim_fd, struct shim_bo *bo)
}
/* Creates an mmap offset for the BO in the DRM fd.
*
* XXX: We should be maintaining a u_mm allocator where the mmap offsets
* allocate the size of the BO and it can be used to look the BO back up.
* Instead, we just stuff the shim's pointer as the return value, and treat
* the incoming mmap offset on the DRM fd as a BO pointer. This doesn't work
* if someone tries to map a subset of the BO, but it's enough to get V3D
* working for now.
*/
uint64_t
drm_shim_bo_get_mmap_offset(struct shim_fd *shim_fd, struct shim_bo *bo)
{
return (uintptr_t)bo;
mtx_lock(&shim_device.mem_lock);
_mesa_hash_table_u64_insert(shim_device.offset_map, bo->mem_addr, bo);
mtx_unlock(&shim_device.mem_lock);
/* reuse the buffer address as the mmap offset: */
return bo->mem_addr;
}
/* For mmap() on the DRM fd, look up the BO from the "offset" and map the BO's
@ -393,7 +393,15 @@ void *
drm_shim_mmap(struct shim_fd *shim_fd, size_t length, int prot, int flags,
int fd, off64_t offset)
{
struct shim_bo *bo = (void *)(uintptr_t)offset;
mtx_lock(&shim_device.mem_lock);
struct shim_bo *bo = _mesa_hash_table_u64_search(shim_device.offset_map, offset);
mtx_unlock(&shim_device.mem_lock);
if (!bo)
return MAP_FAILED;
if (length > bo->size)
return MAP_FAILED;
/* The offset we pass to mmap must be aligned to the page size */
assert((bo->mem_addr & (shim_page_size - 1)) == 0);

View File

@ -41,6 +41,9 @@ struct shim_device {
/* Mapping from int fd to struct shim_fd *. */
struct hash_table *fd_map;
/* Mapping from mmap offset to shim_bo */
struct hash_table_u64 *offset_map;
mtx_t mem_lock;
/* Heap from which shim_bo are allocated */
struct util_vma_heap mem_heap;

View File

@ -120,7 +120,8 @@ i915_ioctl_gem_mmap(int fd, unsigned long request, void *arg)
return -1;
if (!bo->map)
bo->map = drm_shim_mmap(shim_fd, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, -1, (uintptr_t)bo);
bo->map = drm_shim_mmap(shim_fd, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, -1,
drm_shim_bo_get_mmap_offset(shim_fd, bo));
mmap_arg->addr_ptr = (uint64_t) (bo->map + mmap_arg->offset);