minigbm: add validation during import

A common cause of bugs and security exploits are out-of-bounds
memory accesses. Let's add some validation when importing the
buffer to protect against this.

BUG=b:65566935
TEST=Boot Android and play games on Eve

Change-Id: I557f9b9849f267f5c87bb29648119b1c29695cd3
Reviewed-on: https://chromium-review.googlesource.com/692624
Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
diff --git a/drv.c b/drv.c
index b7a8f91..13722b0 100644
--- a/drv.c
+++ b/drv.c
@@ -259,8 +259,12 @@
 
 	pthread_mutex_lock(&drv->driver_lock);
 
-	for (plane = 0; plane < bo->num_planes; plane++)
+	for (plane = 0; plane < bo->num_planes; plane++) {
+		if (plane > 0)
+			assert(bo->offsets[plane] >= bo->offsets[plane - 1]);
+
 		drv_increment_reference_count(drv, bo, plane);
+	}
 
 	pthread_mutex_unlock(&drv->driver_lock);
 
@@ -293,8 +297,12 @@
 
 	pthread_mutex_lock(&drv->driver_lock);
 
-	for (plane = 0; plane < bo->num_planes; plane++)
+	for (plane = 0; plane < bo->num_planes; plane++) {
+		if (plane > 0)
+			assert(bo->offsets[plane] >= bo->offsets[plane - 1]);
+
 		drv_increment_reference_count(drv, bo, plane);
+	}
 
 	pthread_mutex_unlock(&drv->driver_lock);
 
@@ -330,6 +338,7 @@
 	int ret;
 	size_t plane;
 	struct bo *bo;
+	off_t seek_end;
 
 	bo = drv_bo_new(drv, data->width, data->height, data->format, data->use_flags);
 
@@ -346,18 +355,32 @@
 		bo->strides[plane] = data->strides[plane];
 		bo->offsets[plane] = data->offsets[plane];
 		bo->format_modifiers[plane] = data->format_modifiers[plane];
-		if (plane == bo->num_planes - 1 || data->offsets[plane + 1] == 0) {
-			bo->sizes[plane] =
-			    lseek(data->fds[plane], 0, SEEK_END) - data->offsets[plane];
-			lseek(data->fds[plane], 0, SEEK_SET);
-		} else {
+
+		seek_end = lseek(data->fds[plane], 0, SEEK_END);
+		if (seek_end == (off_t)(-1)) {
+			fprintf(stderr, "drv: lseek() failed with %s\n", strerror(errno));
+			goto destroy_bo;
+		}
+
+		lseek(data->fds[plane], 0, SEEK_SET);
+		if (plane == bo->num_planes - 1 || data->offsets[plane + 1] == 0)
+			bo->sizes[plane] = seek_end - data->offsets[plane];
+		else
 			bo->sizes[plane] = data->offsets[plane + 1] - data->offsets[plane];
+
+		if ((int64_t)bo->offsets[plane] + bo->sizes[plane] > seek_end) {
+			fprintf(stderr, "drv: buffer size is too large.\n");
+			goto destroy_bo;
 		}
 
 		bo->total_size += bo->sizes[plane];
 	}
 
 	return bo;
+
+destroy_bo:
+	drv_bo_destroy(bo);
+	return NULL;
 }
 
 void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height,