mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-05 00:48:08 +02:00
Protect drm_mmap against disappearing maps.
The map lists and hash tables are protected using dev->struct_mutex, but drm_mmap strangely never locked this mutex.
This commit is contained in:
parent
3024f23c65
commit
333c6af47a
1 changed files with 39 additions and 26 deletions
|
|
@ -42,8 +42,7 @@
|
|||
static void drm_vm_open(struct vm_area_struct *vma);
|
||||
static void drm_vm_close(struct vm_area_struct *vma);
|
||||
static void drm_vm_ttm_close(struct vm_area_struct *vma);
|
||||
static int drm_vm_ttm_open(struct vm_area_struct *vma);
|
||||
static void drm_vm_ttm_open_wrapper(struct vm_area_struct *vma);
|
||||
static void drm_vm_ttm_open(struct vm_area_struct *vma);
|
||||
|
||||
|
||||
pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
|
||||
|
|
@ -511,13 +510,13 @@ static struct vm_operations_struct drm_vm_sg_ops = {
|
|||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21))
|
||||
static struct vm_operations_struct drm_vm_ttm_ops = {
|
||||
.nopage = drm_vm_ttm_nopage,
|
||||
.open = drm_vm_ttm_open_wrapper,
|
||||
.open = drm_vm_ttm_open,
|
||||
.close = drm_vm_ttm_close,
|
||||
};
|
||||
#else
|
||||
static struct vm_operations_struct drm_vm_ttm_ops = {
|
||||
.fault = drm_vm_ttm_fault,
|
||||
.open = drm_vm_ttm_open_wrapper,
|
||||
.open = drm_vm_ttm_open,
|
||||
.close = drm_vm_ttm_close,
|
||||
};
|
||||
#endif
|
||||
|
|
@ -530,7 +529,7 @@ static struct vm_operations_struct drm_vm_ttm_ops = {
|
|||
* Create a new drm_vma_entry structure as the \p vma private data entry and
|
||||
* add it to drm_device::vmalist.
|
||||
*/
|
||||
static void drm_vm_open(struct vm_area_struct *vma)
|
||||
static void drm_vm_open_locked(struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
|
@ -542,36 +541,43 @@ static void drm_vm_open(struct vm_area_struct *vma)
|
|||
|
||||
vma_entry = drm_ctl_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
|
||||
if (vma_entry) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
vma_entry->vma = vma;
|
||||
vma_entry->next = dev->vmalist;
|
||||
vma_entry->pid = current->pid;
|
||||
dev->vmalist = vma_entry;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int drm_vm_ttm_open(struct vm_area_struct *vma) {
|
||||
|
||||
drm_local_map_t *map = (drm_local_map_t *)vma->vm_private_data;
|
||||
drm_ttm_t *ttm;
|
||||
static void drm_vm_open(struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
||||
drm_vm_open(vma);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_vm_open_locked(vma);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
static void drm_vm_ttm_open_locked(struct vm_area_struct *vma) {
|
||||
|
||||
drm_local_map_t *map = (drm_local_map_t *)vma->vm_private_data;
|
||||
drm_ttm_t *ttm;
|
||||
|
||||
drm_vm_open_locked(vma);
|
||||
ttm = (drm_ttm_t *) map->offset;
|
||||
atomic_inc(&ttm->vma_count);
|
||||
#ifdef DRM_ODD_MM_COMPAT
|
||||
drm_ttm_add_vma(ttm, vma);
|
||||
#endif
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_vm_ttm_open_wrapper(struct vm_area_struct *vma)
|
||||
{
|
||||
drm_vm_ttm_open(vma);
|
||||
static void drm_vm_ttm_open(struct vm_area_struct *vma) {
|
||||
drm_file_t *priv = vma->vm_file->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_vm_ttm_open_locked(vma);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -653,7 +659,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
|
|||
drm_device_dma_t *dma;
|
||||
unsigned long length = vma->vm_end - vma->vm_start;
|
||||
|
||||
lock_kernel();
|
||||
dev = priv->head->dev;
|
||||
dma = dev->dma;
|
||||
DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
|
||||
|
|
@ -664,7 +669,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
|
|||
unlock_kernel();
|
||||
return -EINVAL;
|
||||
}
|
||||
unlock_kernel();
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN) &&
|
||||
(dma->flags & _DRM_DMA_USE_PCI_RO)) {
|
||||
|
|
@ -686,7 +690,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
|
|||
vma->vm_flags |= VM_RESERVED; /* Don't swap */
|
||||
|
||||
vma->vm_file = filp; /* Needed for drm_vm_open() */
|
||||
drm_vm_open(vma);
|
||||
drm_vm_open_locked(vma);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -719,7 +723,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
|
|||
* according to the mapping type and remaps the pages. Finally sets the file
|
||||
* pointer and calls vm_open().
|
||||
*/
|
||||
int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
|
|
@ -839,12 +843,8 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
vma->vm_file = filp;
|
||||
vma->vm_flags |= VM_RESERVED | VM_IO;
|
||||
#ifdef DRM_ODD_MM_COMPAT
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
drm_ttm_map_bound(vma);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
#endif
|
||||
if (drm_vm_ttm_open(vma))
|
||||
return -EAGAIN;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
|
|
@ -853,7 +853,20 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
vma->vm_flags |= VM_RESERVED; /* Don't swap */
|
||||
|
||||
vma->vm_file = filp; /* Needed for drm_vm_open() */
|
||||
drm_vm_open(vma);
|
||||
drm_vm_open_locked(vma);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->head->dev;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = drm_mmap_locked(filp, vma);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mmap);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue