From: Russell King <rmk+ker...@arm.linux.org.uk> Currently, relocations can apply an unbounded amount of offset to the address member. This permits the offset to be used to access memory outside of the associated buffer.
Ensure that the offset is within the size of the object. This is not a complete fix, as we are unaware of the size of the GPU rectangles operation, but this at least ensures that we catch this form of abuse. Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk> --- drivers/staging/etnaviv/etnaviv_gem_submit.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/staging/etnaviv/etnaviv_gem_submit.c b/drivers/staging/etnaviv/etnaviv_gem_submit.c index 39ae61ab43fd..78c56adfcffc 100644 --- a/drivers/staging/etnaviv/etnaviv_gem_submit.c +++ b/drivers/staging/etnaviv/etnaviv_gem_submit.c @@ -245,6 +245,7 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, struct etnaviv_gem_ob for (i = 0; i < nr_relocs; i++) { struct drm_etnaviv_gem_submit_reloc submit_reloc; + struct etnaviv_gem_object *bobj; void __user *userptr = to_user_ptr(relocs + (i * sizeof(submit_reloc))); uint32_t iova, off; @@ -269,13 +270,20 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, struct etnaviv_gem_ob return -EINVAL; } - ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, &valid); + ret = submit_bo(submit, submit_reloc.reloc_idx, &bobj, + &iova, &valid); if (ret) return ret; if (valid) continue; + if (submit_reloc.reloc_offset >= + bobj->base.size - sizeof(*ptr)) { + DRM_ERROR("relocation %u outside object", i); + return -EINVAL; + } + iova += submit_reloc.reloc_offset; if (submit_reloc.shift < 0) -- 2.1.4