drm/vmwgfx: Protect from excessive execbuf kernel memory allocations v3

With the new validation code, a malicious user-space app could
potentially submit command streams with enough buffer-object and resource
references in them to have the resulting allocated validion nodes and
relocations make the kernel run out of GFP_KERNEL memory.

Protect from this by having the validation code reserve TTM graphics
memory when allocating.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Deepak Rawat <drawat@vmware.com>
---
v2: Removed leftover debug printouts
This commit is contained in:
Thomas Hellstrom
2018-12-12 11:52:08 +01:00
parent e06d45d8c1
commit fd56746775
6 changed files with 103 additions and 2 deletions

View File

@@ -33,6 +33,21 @@
#include <linux/ww_mutex.h>
#include <drm/ttm/ttm_execbuf_util.h>
/**
* struct vmw_validation_mem - Custom interface to provide memory reservations
* for the validation code.
* @reserve_mem: Callback to reserve memory
* @unreserve_mem: Callback to unreserve memory
* @gran: Reservation granularity. Contains a hint how much memory should
* be reserved in each call to @reserve_mem(). A slow implementation may want
* reservation to be done in large batches.
*/
struct vmw_validation_mem {
int (*reserve_mem)(struct vmw_validation_mem *m, size_t size);
void (*unreserve_mem)(struct vmw_validation_mem *m, size_t size);
size_t gran;
};
/**
* struct vmw_validation_context - Per command submission validation context
* @ht: Hash table used to find resource- or buffer object duplicates
@@ -47,6 +62,10 @@
* buffer objects
* @mem_size_left: Free memory left in the last page in @page_list
* @page_address: Kernel virtual address of the last page in @page_list
* @vm: A pointer to the memory reservation interface or NULL if no
* memory reservation is needed.
* @vm_size_left: Amount of reserved memory that so far has not been allocated.
* @total_mem: Amount of reserved memory.
*/
struct vmw_validation_context {
struct drm_open_hash *ht;
@@ -59,6 +78,9 @@ struct vmw_validation_context {
unsigned int merge_dups;
unsigned int mem_size_left;
u8 *page_address;
struct vmw_validation_mem *vm;
size_t vm_size_left;
size_t total_mem;
};
struct vmw_buffer_object;
@@ -101,6 +123,21 @@ vmw_validation_has_bos(struct vmw_validation_context *ctx)
return !list_empty(&ctx->bo_list);
}
/**
* vmw_validation_set_val_mem - Register a validation mem object for
* validation memory reservation
* @ctx: The validation context
* @vm: Pointer to a struct vmw_validation_mem
*
* Must be set before the first attempt to allocate validation memory.
*/
static inline void
vmw_validation_set_val_mem(struct vmw_validation_context *ctx,
struct vmw_validation_mem *vm)
{
ctx->vm = vm;
}
/**
* vmw_validation_set_ht - Register a hash table for duplicate finding
* @ctx: The validation context