Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61576b99 authored by Deepak Kumar's avatar Deepak Kumar
Browse files

msm: kgsl: Don't free memory if locking failed with error EADDRNOTAVAIL



While allocating a secure memory if locking fails with error code
EADDRNOTAVAIL then don't free the allocated memory either to pool
or buddy system as security state of the pages is unknown after
this failure which make this memory unusable.

Change-Id: Ia9dff942193d8d88871a15bc855264eb37fc7b56
Signed-off-by: default avatarDeepak Kumar <dkumar@codeaurora.org>
parent 55cb9664
Loading
Loading
Loading
Loading
+32 −8
Original line number Diff line number Diff line
@@ -469,7 +469,7 @@ static void kgsl_page_alloc_unmap_kernel(struct kgsl_memdesc *memdesc)
	mutex_unlock(&kernel_map_global_lock);
}

static int kgsl_lock_sgt(struct sg_table *sgt)
static int kgsl_lock_sgt(struct sg_table *sgt, u64 size)
{
	struct scatterlist *sg;
	int dest_perms = PERM_READ | PERM_WRITE;
@@ -479,12 +479,26 @@ static int kgsl_lock_sgt(struct sg_table *sgt)
	int i;

	ret = hyp_assign_table(sgt, &source_vm, 1, &dest_vm, &dest_perms, 1);
	if (!ret) {
	if (ret) {
		/*
		 * If returned error code is EADDRNOTAVAIL, then this
		 * memory may no longer be in a usable state as security
		 * state of the pages is unknown after this failure. This
		 * memory can neither be added back to the pool nor buddy
		 * system.
		 */
		if (ret == -EADDRNOTAVAIL)
			pr_err("Failure to lock secure GPU memory 0x%llx bytes will not be recoverable\n",
				size);

		return ret;
	}

	/* Set private bit for each sg to indicate that its secured */
	for_each_sg(sgt->sgl, sg, sgt->nents, i)
		SetPagePrivate(sg_page(sg));
	}
	return ret;

	return 0;
}

static int kgsl_unlock_sgt(struct sg_table *sgt)
@@ -935,11 +949,18 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
			goto done;
		}

		ret = kgsl_lock_sgt(memdesc->sgt);
		ret = kgsl_lock_sgt(memdesc->sgt, memdesc->size);
		if (ret) {
			sg_free_table(memdesc->sgt);
			kfree(memdesc->sgt);
			memdesc->sgt = NULL;

			if (ret == -EADDRNOTAVAIL) {
				kgsl_free(memdesc->pages);
				memset(memdesc, 0, sizeof(*memdesc));
				return ret;
			}

			goto done;
		}

@@ -1039,8 +1060,11 @@ struct page *kgsl_alloc_secure_page(void)
	sg_init_table(&sgl, 1);
	sg_set_page(&sgl, page, PAGE_SIZE, 0);

	status = kgsl_lock_sgt(&sgt);
	status = kgsl_lock_sgt(&sgt, PAGE_SIZE);
	if (status) {
		if (status == -EADDRNOTAVAIL)
			return NULL;

		__free_page(page);
		return NULL;
	}