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

Commit ffa2a297 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 b53c6bb3
Loading
Loading
Loading
Loading
+32 −8
Original line number Original line Diff line number Diff line
@@ -482,7 +482,7 @@ static void kgsl_page_alloc_unmap_kernel(struct kgsl_memdesc *memdesc)
	mutex_unlock(&kernel_map_global_lock);
	mutex_unlock(&kernel_map_global_lock);
}
}


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


	ret = hyp_assign_table(sgt, &source_vm, 1, &dest_vm, &dest_perms, 1);
	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 */
	/* Set private bit for each sg to indicate that its secured */
	for_each_sg(sgt->sgl, sg, sgt->nents, i)
	for_each_sg(sgt->sgl, sg, sgt->nents, i)
		SetPagePrivate(sg_page(sg));
		SetPagePrivate(sg_page(sg));
	}

	return ret;
	return 0;
}
}


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


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

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

			goto done;
			goto done;
		}
		}


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


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

		__free_page(page);
		__free_page(page);
		return NULL;
		return NULL;
	}
	}