diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index ef9642d72672..1aac50c7c1de 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -530,11 +530,24 @@ static int params_to_user(struct tee_ioctl_param __user *uparams, return 0; } +static void free_params(struct tee_param *params, size_t num_params) +{ + size_t n; + + if (!params) + return; + + for (n = 0; n < num_params; n++) + if (tee_param_is_memref(params + n) && params[n].u.memref.shm) + tee_shm_put(params[n].u.memref.shm); + + kfree(params); +} + static int tee_ioctl_open_session(struct tee_context *ctx, struct tee_ioctl_buf_data __user *ubuf) { int rc; - size_t n; struct tee_ioctl_buf_data buf; struct tee_ioctl_open_session_arg __user *uarg; struct tee_ioctl_open_session_arg arg; @@ -595,16 +608,7 @@ out: */ if (rc && have_session && ctx->teedev->desc->ops->close_session) ctx->teedev->desc->ops->close_session(ctx, arg.session); - - if (params) { - /* Decrease ref count for all valid shared memory pointers */ - for (n = 0; n < arg.num_params; n++) - if (tee_param_is_memref(params + n) && - params[n].u.memref.shm) - tee_shm_put(params[n].u.memref.shm); - kfree(params); - } - + free_params(params, arg.num_params); return rc; } @@ -612,7 +616,6 @@ static int tee_ioctl_invoke(struct tee_context *ctx, struct tee_ioctl_buf_data __user *ubuf) { int rc; - size_t n; struct tee_ioctl_buf_data buf; struct tee_ioctl_invoke_arg __user *uarg; struct tee_ioctl_invoke_arg arg; @@ -657,14 +660,7 @@ static int tee_ioctl_invoke(struct tee_context *ctx, } rc = params_to_user(uparams, arg.num_params, params); out: - if (params) { - /* Decrease ref count for all valid shared memory pointers */ - for (n = 0; n < arg.num_params; n++) - if (tee_param_is_memref(params + n) && - params[n].u.memref.shm) - tee_shm_put(params[n].u.memref.shm); - kfree(params); - } + free_params(params, arg.num_params); return rc; } @@ -672,7 +668,6 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx, struct tee_ioctl_buf_data __user *ubuf) { int rc; - size_t n; struct tee_ioctl_buf_data buf; struct tee_ioctl_object_invoke_arg __user *uarg; struct tee_ioctl_object_invoke_arg arg; @@ -716,14 +711,7 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx, } rc = params_to_user(uparams, arg.num_params, params); out: - if (params) { - /* Decrease ref count for all valid shared memory pointers */ - for (n = 0; n < arg.num_params; n++) - if (tee_param_is_memref(params + n) && - params[n].u.memref.shm) - tee_shm_put(params[n].u.memref.shm); - kfree(params); - } + free_params(params, arg.num_params); return rc; } @@ -846,9 +834,15 @@ static int tee_ioctl_supp_recv(struct tee_context *ctx, return -ENOMEM; rc = params_from_user(ctx, params, num_params, uarg->params); - if (rc) - goto out; + if (rc) { + free_params(params, num_params); + return rc; + } + /* + * supp_recv() may consume and replace the supplied parameters, so the + * final cleanup cannot use free_params() like the other ioctl paths. + */ rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params); if (rc) goto out; diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index e9ea9f80cfd9..6742b3579c86 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -435,7 +435,7 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, num_pages = iov_iter_npages(iter, INT_MAX); if (!num_pages) { ret = ERR_PTR(-ENOMEM); - goto err_ctx_put; + goto err_free_shm; } shm->pages = kzalloc_objs(*shm->pages, num_pages); diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index cab5cadca8ef..5203977ed35d 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h @@ -470,6 +470,7 @@ struct tee_ioctl_object_invoke_arg { __u32 op; __u32 ret; __u32 num_params; + __u32 :32; /* num_params tells the actual number of element in params */ struct tee_ioctl_param params[]; };