Commit ffdc98c4 authored by Olof Johansson's avatar Olof Johansson

Merge tag 'tee-drv-dynamic-shm+fixes-for-v4.16' of...

Merge tag 'tee-drv-dynamic-shm+fixes-for-v4.16' of https://git.linaro.org/people/jens.wiklander/linux-tee into next/drivers

This pull request updates the previous tee-drv-dynamic-shm-for-v4.16 pull
request with five new patches fixing review comments and errors.

Apart from three small fixes there's two larger patches that in the end
checks that memory to be registered really is normal cached memory.

* tag 'tee-drv-dynamic-shm+fixes-for-v4.16' of https://git.linaro.org/people/jens.wiklander/linux-tee:
  tee: shm: Potential NULL dereference calling tee_shm_register()
  tee: shm: don't put_page on null shm->pages
  tee: shm: make function __tee_shm_alloc static
  tee: optee: check type of registered shared memory
  tee: add start argument to shm_register callback
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents be60566e 2490cdf6
...@@ -535,18 +535,58 @@ void optee_free_pages_list(void *list, size_t num_entries) ...@@ -535,18 +535,58 @@ void optee_free_pages_list(void *list, size_t num_entries)
free_pages_exact(list, get_pages_list_size(num_entries)); free_pages_exact(list, get_pages_list_size(num_entries));
} }
static bool is_normal_memory(pgprot_t p)
{
#if defined(CONFIG_ARM)
return (pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC;
#elif defined(CONFIG_ARM64)
return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL);
#else
#error "Unuspported architecture"
#endif
}
static int __check_mem_type(struct vm_area_struct *vma, unsigned long end)
{
while (vma && is_normal_memory(vma->vm_page_prot)) {
if (vma->vm_end >= end)
return 0;
vma = vma->vm_next;
}
return -EINVAL;
}
static int check_mem_type(unsigned long start, size_t num_pages)
{
struct mm_struct *mm = current->mm;
int rc;
down_read(&mm->mmap_sem);
rc = __check_mem_type(find_vma(mm, start),
start + num_pages * PAGE_SIZE);
up_read(&mm->mmap_sem);
return rc;
}
int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
struct page **pages, size_t num_pages) struct page **pages, size_t num_pages,
unsigned long start)
{ {
struct tee_shm *shm_arg = NULL; struct tee_shm *shm_arg = NULL;
struct optee_msg_arg *msg_arg; struct optee_msg_arg *msg_arg;
u64 *pages_list; u64 *pages_list;
phys_addr_t msg_parg; phys_addr_t msg_parg;
int rc = 0; int rc;
if (!num_pages) if (!num_pages)
return -EINVAL; return -EINVAL;
rc = check_mem_type(start, num_pages);
if (rc)
return rc;
pages_list = optee_allocate_pages_list(num_pages); pages_list = optee_allocate_pages_list(num_pages);
if (!pages_list) if (!pages_list)
return -ENOMEM; return -ENOMEM;
...@@ -606,13 +646,14 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm) ...@@ -606,13 +646,14 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
} }
int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
struct page **pages, size_t num_pages) struct page **pages, size_t num_pages,
unsigned long start)
{ {
/* /*
* We don't want to register supplicant memory in OP-TEE. * We don't want to register supplicant memory in OP-TEE.
* Instead information about it will be passed in RPC code. * Instead information about it will be passed in RPC code.
*/ */
return 0; return check_mem_type(start, num_pages);
} }
int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm) int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
......
...@@ -162,11 +162,13 @@ void optee_enable_shm_cache(struct optee *optee); ...@@ -162,11 +162,13 @@ void optee_enable_shm_cache(struct optee *optee);
void optee_disable_shm_cache(struct optee *optee); void optee_disable_shm_cache(struct optee *optee);
int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm, int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
struct page **pages, size_t num_pages); struct page **pages, size_t num_pages,
unsigned long start);
int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm); int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm);
int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm, int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
struct page **pages, size_t num_pages); struct page **pages, size_t num_pages,
unsigned long start);
int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm); int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm);
int optee_from_msg_param(struct tee_param *params, size_t num_params, int optee_from_msg_param(struct tee_param *params, size_t num_params,
......
...@@ -112,9 +112,9 @@ static const struct dma_buf_ops tee_shm_dma_buf_ops = { ...@@ -112,9 +112,9 @@ static const struct dma_buf_ops tee_shm_dma_buf_ops = {
.mmap = tee_shm_op_mmap, .mmap = tee_shm_op_mmap,
}; };
struct tee_shm *__tee_shm_alloc(struct tee_context *ctx, static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
struct tee_device *teedev, struct tee_device *teedev,
size_t size, u32 flags) size_t size, u32 flags)
{ {
struct tee_shm_pool_mgr *poolm = NULL; struct tee_shm_pool_mgr *poolm = NULL;
struct tee_shm *shm; struct tee_shm *shm;
...@@ -283,7 +283,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, ...@@ -283,7 +283,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
if (rc > 0) if (rc > 0)
shm->num_pages = rc; shm->num_pages = rc;
if (rc != num_pages) { if (rc != num_pages) {
if (rc > 0) if (rc >= 0)
rc = -ENOMEM; rc = -ENOMEM;
ret = ERR_PTR(rc); ret = ERR_PTR(rc);
goto err; goto err;
...@@ -299,7 +299,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, ...@@ -299,7 +299,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
} }
rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages, rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages,
shm->num_pages); shm->num_pages, start);
if (rc) { if (rc) {
ret = ERR_PTR(rc); ret = ERR_PTR(rc);
goto err; goto err;
...@@ -335,9 +335,11 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, ...@@ -335,9 +335,11 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
idr_remove(&teedev->idr, shm->id); idr_remove(&teedev->idr, shm->id);
mutex_unlock(&teedev->mutex); mutex_unlock(&teedev->mutex);
} }
for (n = 0; n < shm->num_pages; n++) if (shm->pages) {
put_page(shm->pages[n]); for (n = 0; n < shm->num_pages; n++)
kfree(shm->pages); put_page(shm->pages[n]);
kfree(shm->pages);
}
} }
kfree(shm); kfree(shm);
teedev_ctx_put(ctx); teedev_ctx_put(ctx);
......
...@@ -108,7 +108,8 @@ struct tee_driver_ops { ...@@ -108,7 +108,8 @@ struct tee_driver_ops {
int (*supp_send)(struct tee_context *ctx, u32 ret, u32 num_params, int (*supp_send)(struct tee_context *ctx, u32 ret, u32 num_params,
struct tee_param *param); struct tee_param *param);
int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm, int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm,
struct page **pages, size_t num_pages); struct page **pages, size_t num_pages,
unsigned long start);
int (*shm_unregister)(struct tee_context *ctx, struct tee_shm *shm); int (*shm_unregister)(struct tee_context *ctx, struct tee_shm *shm);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment