ttm: make sure userspace can't destroy kernel create memory managers
this adds something to say the kernel initialised the memory region not the userspace. and blocks userspace from deallocating kernel areasmain
parent
180c9188f4
commit
d5c0101252
|
@ -2180,7 +2180,7 @@ restart:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type)
|
int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type, int kern_clean)
|
||||||
{
|
{
|
||||||
struct drm_buffer_manager *bm = &dev->bm;
|
struct drm_buffer_manager *bm = &dev->bm;
|
||||||
struct drm_mem_type_manager *man = &bm->man[mem_type];
|
struct drm_mem_type_manager *man = &bm->man[mem_type];
|
||||||
|
@ -2196,6 +2196,13 @@ int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type)
|
||||||
"memory manager type %u\n", mem_type);
|
"memory manager type %u\n", mem_type);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((man->kern_init_type) && (kern_clean == 0)) {
|
||||||
|
DRM_ERROR("Trying to take down kernel initialized "
|
||||||
|
"memory manager type %u\n", mem_type);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
man->use_type = 0;
|
man->use_type = 0;
|
||||||
man->has_type = 0;
|
man->has_type = 0;
|
||||||
|
|
||||||
|
@ -2247,9 +2254,9 @@ static int drm_bo_lock_mm(struct drm_device *dev, unsigned mem_type)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int drm_bo_init_mm(struct drm_device *dev,
|
int drm_bo_init_mm(struct drm_device *dev, unsigned type,
|
||||||
unsigned type,
|
unsigned long p_offset, unsigned long p_size,
|
||||||
unsigned long p_offset, unsigned long p_size)
|
int kern_init)
|
||||||
{
|
{
|
||||||
struct drm_buffer_manager *bm = &dev->bm;
|
struct drm_buffer_manager *bm = &dev->bm;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
|
@ -2283,6 +2290,7 @@ int drm_bo_init_mm(struct drm_device *dev,
|
||||||
}
|
}
|
||||||
man->has_type = 1;
|
man->has_type = 1;
|
||||||
man->use_type = 1;
|
man->use_type = 1;
|
||||||
|
man->kern_init_type = kern_init;
|
||||||
man->size = p_size;
|
man->size = p_size;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&man->lru);
|
INIT_LIST_HEAD(&man->lru);
|
||||||
|
@ -2316,7 +2324,7 @@ int drm_bo_driver_finish(struct drm_device *dev)
|
||||||
man = &bm->man[i];
|
man = &bm->man[i];
|
||||||
if (man->has_type) {
|
if (man->has_type) {
|
||||||
man->use_type = 0;
|
man->use_type = 0;
|
||||||
if ((i != DRM_BO_MEM_LOCAL) && drm_bo_clean_mm(dev, i)) {
|
if ((i != DRM_BO_MEM_LOCAL) && drm_bo_clean_mm(dev, i, 1)) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
DRM_ERROR("DRM memory manager type %d "
|
DRM_ERROR("DRM memory manager type %d "
|
||||||
"is not clean.\n", i);
|
"is not clean.\n", i);
|
||||||
|
@ -2386,7 +2394,7 @@ int drm_bo_driver_init(struct drm_device *dev)
|
||||||
* Initialize the system memory buffer type.
|
* Initialize the system memory buffer type.
|
||||||
* Other types need to be driver / IOCTL initialized.
|
* Other types need to be driver / IOCTL initialized.
|
||||||
*/
|
*/
|
||||||
ret = drm_bo_init_mm(dev, DRM_BO_MEM_LOCAL, 0, 0);
|
ret = drm_bo_init_mm(dev, DRM_BO_MEM_LOCAL, 0, 0, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
|
@ -2446,7 +2454,7 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = drm_bo_init_mm(dev, arg->mem_type,
|
ret = drm_bo_init_mm(dev, arg->mem_type,
|
||||||
arg->p_offset, arg->p_size);
|
arg->p_offset, arg->p_size, 0);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
@ -2485,9 +2493,11 @@ int drm_mm_takedown_ioctl(struct drm_device *dev, void *data, struct drm_file *f
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (drm_bo_clean_mm(dev, arg->mem_type)) {
|
if ((ret = drm_bo_clean_mm(dev, arg->mem_type, 0))) {
|
||||||
DRM_ERROR("Memory manager type %d not clean. "
|
if (ret == -EINVAL)
|
||||||
"Delaying takedown\n", arg->mem_type);
|
DRM_ERROR("Memory manager type %d not clean. "
|
||||||
|
"Delaying takedown\n", arg->mem_type);
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
|
|
@ -516,6 +516,7 @@ struct drm_buffer_object {
|
||||||
struct drm_mem_type_manager {
|
struct drm_mem_type_manager {
|
||||||
int has_type;
|
int has_type;
|
||||||
int use_type;
|
int use_type;
|
||||||
|
int kern_init_type;
|
||||||
struct drm_mm manager;
|
struct drm_mm manager;
|
||||||
struct list_head lru;
|
struct list_head lru;
|
||||||
struct list_head pinned;
|
struct list_head pinned;
|
||||||
|
@ -684,9 +685,10 @@ extern int drm_bo_mem_space(struct drm_buffer_object *bo,
|
||||||
extern int drm_bo_move_buffer(struct drm_buffer_object *bo,
|
extern int drm_bo_move_buffer(struct drm_buffer_object *bo,
|
||||||
uint64_t new_mem_flags,
|
uint64_t new_mem_flags,
|
||||||
int no_wait, int move_unfenced);
|
int no_wait, int move_unfenced);
|
||||||
extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type);
|
extern int drm_bo_clean_mm(struct drm_device *dev, unsigned mem_type, int kern_clean);
|
||||||
extern int drm_bo_init_mm(struct drm_device *dev, unsigned type,
|
extern int drm_bo_init_mm(struct drm_device *dev, unsigned type,
|
||||||
unsigned long p_offset, unsigned long p_size);
|
unsigned long p_offset, unsigned long p_size,
|
||||||
|
int kern_init);
|
||||||
extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle,
|
extern int drm_bo_handle_validate(struct drm_file *file_priv, uint32_t handle,
|
||||||
uint64_t flags, uint64_t mask, uint32_t hint,
|
uint64_t flags, uint64_t mask, uint32_t hint,
|
||||||
uint32_t fence_class, int use_old_fence_class,
|
uint32_t fence_class, int use_old_fence_class,
|
||||||
|
|
|
@ -376,7 +376,7 @@ nouveau_mem_init_ttm(struct drm_device *dev)
|
||||||
bar1_size = drm_get_resource_len(dev, 1) >> PAGE_SHIFT;
|
bar1_size = drm_get_resource_len(dev, 1) >> PAGE_SHIFT;
|
||||||
if (bar1_size < vram_size) {
|
if (bar1_size < vram_size) {
|
||||||
if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_PRIV0,
|
if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_PRIV0,
|
||||||
bar1_size, vram_size - bar1_size))) {
|
bar1_size, vram_size - bar1_size, 1))) {
|
||||||
DRM_ERROR("Failed PRIV0 mm init: %d\n", ret);
|
DRM_ERROR("Failed PRIV0 mm init: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -387,7 +387,7 @@ nouveau_mem_init_ttm(struct drm_device *dev)
|
||||||
#ifdef HACK_OLD_MM
|
#ifdef HACK_OLD_MM
|
||||||
vram_size /= 4;
|
vram_size /= 4;
|
||||||
#endif
|
#endif
|
||||||
if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, vram_size))) {
|
if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, vram_size, 1))) {
|
||||||
DRM_ERROR("Failed VRAM mm init: %d\n", ret);
|
DRM_ERROR("Failed VRAM mm init: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -407,7 +407,7 @@ nouveau_mem_init_ttm(struct drm_device *dev)
|
||||||
|
|
||||||
if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_TT, 0,
|
if ((ret = drm_bo_init_mm(dev, DRM_BO_MEM_TT, 0,
|
||||||
dev_priv->gart_info.aper_size >>
|
dev_priv->gart_info.aper_size >>
|
||||||
PAGE_SHIFT))) {
|
PAGE_SHIFT, 1))) {
|
||||||
DRM_ERROR("Failed TT mm init: %d\n", ret);
|
DRM_ERROR("Failed TT mm init: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue