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 areas
main
Dave Airlie 2008-02-18 10:39:21 +10:00 committed by Dave Airlie
parent 180c9188f4
commit d5c0101252
3 changed files with 27 additions and 15 deletions

View File

@ -2180,7 +2180,7 @@ restart:
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_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);
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->has_type = 0;
@ -2247,9 +2254,9 @@ static int drm_bo_lock_mm(struct drm_device *dev, unsigned mem_type)
return ret;
}
int drm_bo_init_mm(struct drm_device *dev,
unsigned type,
unsigned long p_offset, unsigned long p_size)
int drm_bo_init_mm(struct drm_device *dev, unsigned type,
unsigned long p_offset, unsigned long p_size,
int kern_init)
{
struct drm_buffer_manager *bm = &dev->bm;
int ret = -EINVAL;
@ -2283,6 +2290,7 @@ int drm_bo_init_mm(struct drm_device *dev,
}
man->has_type = 1;
man->use_type = 1;
man->kern_init_type = kern_init;
man->size = p_size;
INIT_LIST_HEAD(&man->lru);
@ -2316,7 +2324,7 @@ int drm_bo_driver_finish(struct drm_device *dev)
man = &bm->man[i];
if (man->has_type) {
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;
DRM_ERROR("DRM memory manager type %d "
"is not clean.\n", i);
@ -2386,7 +2394,7 @@ int drm_bo_driver_init(struct drm_device *dev)
* Initialize the system memory buffer type.
* 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)
goto out_unlock;
@ -2446,7 +2454,7 @@ int drm_mm_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_
goto out;
}
ret = drm_bo_init_mm(dev, arg->mem_type,
arg->p_offset, arg->p_size);
arg->p_offset, arg->p_size, 0);
out:
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;
}
ret = 0;
if (drm_bo_clean_mm(dev, arg->mem_type)) {
DRM_ERROR("Memory manager type %d not clean. "
"Delaying takedown\n", arg->mem_type);
if ((ret = drm_bo_clean_mm(dev, arg->mem_type, 0))) {
if (ret == -EINVAL)
DRM_ERROR("Memory manager type %d not clean. "
"Delaying takedown\n", arg->mem_type);
ret = 0;
}
out:
mutex_unlock(&dev->struct_mutex);

View File

@ -516,6 +516,7 @@ struct drm_buffer_object {
struct drm_mem_type_manager {
int has_type;
int use_type;
int kern_init_type;
struct drm_mm manager;
struct list_head lru;
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,
uint64_t new_mem_flags,
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,
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,
uint64_t flags, uint64_t mask, uint32_t hint,
uint32_t fence_class, int use_old_fence_class,

View File

@ -376,7 +376,7 @@ nouveau_mem_init_ttm(struct drm_device *dev)
bar1_size = drm_get_resource_len(dev, 1) >> PAGE_SHIFT;
if (bar1_size < vram_size) {
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);
return ret;
}
@ -387,7 +387,7 @@ nouveau_mem_init_ttm(struct drm_device *dev)
#ifdef HACK_OLD_MM
vram_size /= 4;
#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);
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,
dev_priv->gart_info.aper_size >>
PAGE_SHIFT))) {
PAGE_SHIFT, 1))) {
DRM_ERROR("Failed TT mm init: %d\n", ret);
return ret;
}