^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2015, Linaro Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "optee_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) struct optee_supp_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct list_head link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) bool in_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) u32 func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) size_t num_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct tee_param *param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct completion c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) void optee_supp_init(struct optee_supp *supp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) memset(supp, 0, sizeof(*supp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) mutex_init(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) init_completion(&supp->reqs_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) idr_init(&supp->idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) INIT_LIST_HEAD(&supp->reqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) supp->req_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) void optee_supp_uninit(struct optee_supp *supp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) mutex_destroy(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) idr_destroy(&supp->idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) void optee_supp_release(struct optee_supp *supp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct optee_supp_req *req_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* Abort all request retrieved by supplicant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) idr_for_each_entry(&supp->idr, req, id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) idr_remove(&supp->idr, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) req->ret = TEEC_ERROR_COMMUNICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) complete(&req->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* Abort all queued requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) list_del(&req->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) req->in_queue = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) req->ret = TEEC_ERROR_COMMUNICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) complete(&req->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) supp->ctx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) supp->req_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * optee_supp_thrd_req() - request service from supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * @ctx: context doing the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * @func: function requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @num_params: number of elements in @param array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * @param: parameters for function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Returns result of operation to be passed to secure world
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct tee_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct optee *optee = tee_get_drvdata(ctx->teedev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct optee_supp *supp = &optee->supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bool interruptable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Return in case there is no supplicant available and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * non-blocking request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!supp->ctx && ctx->supp_nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return TEEC_ERROR_COMMUNICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) req = kzalloc(sizeof(*req), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return TEEC_ERROR_OUT_OF_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) init_completion(&req->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) req->func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) req->num_params = num_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) req->param = param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* Insert the request in the request list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) list_add_tail(&req->link, &supp->reqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) req->in_queue = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* Tell an eventual waiter there's a new request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) complete(&supp->reqs_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * Wait for supplicant to process and return result, once we've
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * returned from wait_for_completion(&req->c) successfully we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * exclusive access again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) while (wait_for_completion_interruptible(&req->c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) interruptable = !supp->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (interruptable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * There's no supplicant available and since the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * supp->mutex currently is held none can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * become available until the mutex released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Interrupting an RPC to supplicant is only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * allowed as a way of slightly improving the user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * experience in case the supplicant hasn't been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * started yet. During normal operation the supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * will serve all requests in a timely manner and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * interrupting then wouldn't make sense.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (req->in_queue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) list_del(&req->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) req->in_queue = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (interruptable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) req->ret = TEEC_ERROR_COMMUNICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ret = req->ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) kfree(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static struct optee_supp_req *supp_pop_entry(struct optee_supp *supp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int num_params, int *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (supp->req_id != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Supplicant should not mix synchronous and asnynchronous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (list_empty(&supp->reqs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) req = list_first_entry(&supp->reqs, struct optee_supp_req, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (num_params < req->num_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Not enough room for parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (*id < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) list_del(&req->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) req->in_queue = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int supp_check_recv_params(size_t num_params, struct tee_param *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) size_t *num_meta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) size_t n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!num_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * If there's memrefs we need to decrease those as they where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * increased earlier and we'll even refuse to accept any below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (n = 0; n < num_params; n++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (tee_param_is_memref(params + n) && params[n].u.memref.shm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) tee_shm_put(params[n].u.memref.shm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * We only expect parameters as TEE_IOCTL_PARAM_ATTR_TYPE_NONE with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * or without the TEE_IOCTL_PARAM_ATTR_META bit set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) for (n = 0; n < num_params; n++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (params[n].attr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) params[n].attr != TEE_IOCTL_PARAM_ATTR_META)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* At most we'll need one meta parameter so no need to check for more */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (params->attr == TEE_IOCTL_PARAM_ATTR_META)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) *num_meta = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *num_meta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * optee_supp_recv() - receive request for supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * @ctx: context receiving the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * @func: requested function in supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * @num_params: number of elements allocated in @param, updated with number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * used elements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @param: space for parameters for @func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * Returns 0 on success or <0 on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct tee_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct tee_device *teedev = ctx->teedev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) struct optee *optee = tee_get_drvdata(teedev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct optee_supp *supp = &optee->supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct optee_supp_req *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) size_t num_meta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) rc = supp_check_recv_params(*num_params, param, &num_meta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) req = supp_pop_entry(supp, *num_params - num_meta, &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (IS_ERR(req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * If we didn't get a request we'll block in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * wait_for_completion() to avoid needless spinning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * This is where supplicant will be hanging most of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * the time, let's make this interruptable so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * can easily restart supplicant if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (wait_for_completion_interruptible(&supp->reqs_c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (num_meta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * tee-supplicant support meta parameters -> requsts can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * processed asynchronously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) TEE_IOCTL_PARAM_ATTR_META;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) param->u.value.a = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) param->u.value.b = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) param->u.value.c = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) supp->req_id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *func = req->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *num_params = req->num_params + num_meta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) memcpy(param + num_meta, req->param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) sizeof(struct tee_param) * req->num_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) size_t num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct tee_param *param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) size_t *num_meta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) size_t nm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) const u32 attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) TEE_IOCTL_PARAM_ATTR_META;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!num_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (supp->req_id == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (param->attr != attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) id = param->u.value.a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) nm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) id = supp->req_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) nm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) req = idr_find(&supp->idr, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if ((num_params - nm) != req->num_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) idr_remove(&supp->idr, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) supp->req_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *num_meta = nm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * optee_supp_send() - send result of request from supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * @ctx: context sending result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * @ret: return value of request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * @num_params: number of parameters returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * @param: returned parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * Returns 0 on success or <0 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct tee_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct tee_device *teedev = ctx->teedev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct optee *optee = tee_get_drvdata(teedev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct optee_supp *supp = &optee->supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) size_t n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) size_t num_meta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) req = supp_pop_req(supp, num_params, param, &num_meta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (IS_ERR(req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* Something is wrong, let supplicant restart. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) return PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) /* Update out and in/out parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) for (n = 0; n < req->num_params; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct tee_param *p = req->param + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) p->u.value.a = param[n + num_meta].u.value.a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) p->u.value.b = param[n + num_meta].u.value.b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) p->u.value.c = param[n + num_meta].u.value.c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) p->u.memref.size = param[n + num_meta].u.memref.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) req->ret = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* Let the requesting thread continue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) complete(&req->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }