0001
0002
0003
0004
0005 #include <linux/device.h>
0006 #include <linux/slab.h>
0007 #include <linux/uaccess.h>
0008 #include "optee_private.h"
0009
0010 struct optee_supp_req {
0011 struct list_head link;
0012
0013 bool in_queue;
0014 u32 func;
0015 u32 ret;
0016 size_t num_params;
0017 struct tee_param *param;
0018
0019 struct completion c;
0020 };
0021
0022 void optee_supp_init(struct optee_supp *supp)
0023 {
0024 memset(supp, 0, sizeof(*supp));
0025 mutex_init(&supp->mutex);
0026 init_completion(&supp->reqs_c);
0027 idr_init(&supp->idr);
0028 INIT_LIST_HEAD(&supp->reqs);
0029 supp->req_id = -1;
0030 }
0031
0032 void optee_supp_uninit(struct optee_supp *supp)
0033 {
0034 mutex_destroy(&supp->mutex);
0035 idr_destroy(&supp->idr);
0036 }
0037
0038 void optee_supp_release(struct optee_supp *supp)
0039 {
0040 int id;
0041 struct optee_supp_req *req;
0042 struct optee_supp_req *req_tmp;
0043
0044 mutex_lock(&supp->mutex);
0045
0046
0047 idr_for_each_entry(&supp->idr, req, id) {
0048 idr_remove(&supp->idr, id);
0049 req->ret = TEEC_ERROR_COMMUNICATION;
0050 complete(&req->c);
0051 }
0052
0053
0054 list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
0055 list_del(&req->link);
0056 req->in_queue = false;
0057 req->ret = TEEC_ERROR_COMMUNICATION;
0058 complete(&req->c);
0059 }
0060
0061 supp->ctx = NULL;
0062 supp->req_id = -1;
0063
0064 mutex_unlock(&supp->mutex);
0065 }
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
0077 struct tee_param *param)
0078
0079 {
0080 struct optee *optee = tee_get_drvdata(ctx->teedev);
0081 struct optee_supp *supp = &optee->supp;
0082 struct optee_supp_req *req;
0083 bool interruptable;
0084 u32 ret;
0085
0086
0087
0088
0089
0090 if (!supp->ctx && ctx->supp_nowait)
0091 return TEEC_ERROR_COMMUNICATION;
0092
0093 req = kzalloc(sizeof(*req), GFP_KERNEL);
0094 if (!req)
0095 return TEEC_ERROR_OUT_OF_MEMORY;
0096
0097 init_completion(&req->c);
0098 req->func = func;
0099 req->num_params = num_params;
0100 req->param = param;
0101
0102
0103 mutex_lock(&supp->mutex);
0104 list_add_tail(&req->link, &supp->reqs);
0105 req->in_queue = true;
0106 mutex_unlock(&supp->mutex);
0107
0108
0109 complete(&supp->reqs_c);
0110
0111
0112
0113
0114
0115
0116 while (wait_for_completion_interruptible(&req->c)) {
0117 mutex_lock(&supp->mutex);
0118 interruptable = !supp->ctx;
0119 if (interruptable) {
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 if (req->in_queue) {
0134 list_del(&req->link);
0135 req->in_queue = false;
0136 }
0137 }
0138 mutex_unlock(&supp->mutex);
0139
0140 if (interruptable) {
0141 req->ret = TEEC_ERROR_COMMUNICATION;
0142 break;
0143 }
0144 }
0145
0146 ret = req->ret;
0147 kfree(req);
0148
0149 return ret;
0150 }
0151
0152 static struct optee_supp_req *supp_pop_entry(struct optee_supp *supp,
0153 int num_params, int *id)
0154 {
0155 struct optee_supp_req *req;
0156
0157 if (supp->req_id != -1) {
0158
0159
0160
0161
0162 return ERR_PTR(-EINVAL);
0163 }
0164
0165 if (list_empty(&supp->reqs))
0166 return NULL;
0167
0168 req = list_first_entry(&supp->reqs, struct optee_supp_req, link);
0169
0170 if (num_params < req->num_params) {
0171
0172 return ERR_PTR(-EINVAL);
0173 }
0174
0175 *id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
0176 if (*id < 0)
0177 return ERR_PTR(-ENOMEM);
0178
0179 list_del(&req->link);
0180 req->in_queue = false;
0181
0182 return req;
0183 }
0184
0185 static int supp_check_recv_params(size_t num_params, struct tee_param *params,
0186 size_t *num_meta)
0187 {
0188 size_t n;
0189
0190 if (!num_params)
0191 return -EINVAL;
0192
0193
0194
0195
0196
0197 for (n = 0; n < num_params; n++)
0198 if (tee_param_is_memref(params + n) && params[n].u.memref.shm)
0199 tee_shm_put(params[n].u.memref.shm);
0200
0201
0202
0203
0204
0205 for (n = 0; n < num_params; n++)
0206 if (params[n].attr &&
0207 params[n].attr != TEE_IOCTL_PARAM_ATTR_META)
0208 return -EINVAL;
0209
0210
0211 if (params->attr == TEE_IOCTL_PARAM_ATTR_META)
0212 *num_meta = 1;
0213 else
0214 *num_meta = 0;
0215
0216 return 0;
0217 }
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
0230 struct tee_param *param)
0231 {
0232 struct tee_device *teedev = ctx->teedev;
0233 struct optee *optee = tee_get_drvdata(teedev);
0234 struct optee_supp *supp = &optee->supp;
0235 struct optee_supp_req *req = NULL;
0236 int id;
0237 size_t num_meta;
0238 int rc;
0239
0240 rc = supp_check_recv_params(*num_params, param, &num_meta);
0241 if (rc)
0242 return rc;
0243
0244 while (true) {
0245 mutex_lock(&supp->mutex);
0246 req = supp_pop_entry(supp, *num_params - num_meta, &id);
0247 mutex_unlock(&supp->mutex);
0248
0249 if (req) {
0250 if (IS_ERR(req))
0251 return PTR_ERR(req);
0252 break;
0253 }
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263 if (wait_for_completion_interruptible(&supp->reqs_c))
0264 return -ERESTARTSYS;
0265 }
0266
0267 if (num_meta) {
0268
0269
0270
0271
0272 param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
0273 TEE_IOCTL_PARAM_ATTR_META;
0274 param->u.value.a = id;
0275 param->u.value.b = 0;
0276 param->u.value.c = 0;
0277 } else {
0278 mutex_lock(&supp->mutex);
0279 supp->req_id = id;
0280 mutex_unlock(&supp->mutex);
0281 }
0282
0283 *func = req->func;
0284 *num_params = req->num_params + num_meta;
0285 memcpy(param + num_meta, req->param,
0286 sizeof(struct tee_param) * req->num_params);
0287
0288 return 0;
0289 }
0290
0291 static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
0292 size_t num_params,
0293 struct tee_param *param,
0294 size_t *num_meta)
0295 {
0296 struct optee_supp_req *req;
0297 int id;
0298 size_t nm;
0299 const u32 attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
0300 TEE_IOCTL_PARAM_ATTR_META;
0301
0302 if (!num_params)
0303 return ERR_PTR(-EINVAL);
0304
0305 if (supp->req_id == -1) {
0306 if (param->attr != attr)
0307 return ERR_PTR(-EINVAL);
0308 id = param->u.value.a;
0309 nm = 1;
0310 } else {
0311 id = supp->req_id;
0312 nm = 0;
0313 }
0314
0315 req = idr_find(&supp->idr, id);
0316 if (!req)
0317 return ERR_PTR(-ENOENT);
0318
0319 if ((num_params - nm) != req->num_params)
0320 return ERR_PTR(-EINVAL);
0321
0322 idr_remove(&supp->idr, id);
0323 supp->req_id = -1;
0324 *num_meta = nm;
0325
0326 return req;
0327 }
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338 int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
0339 struct tee_param *param)
0340 {
0341 struct tee_device *teedev = ctx->teedev;
0342 struct optee *optee = tee_get_drvdata(teedev);
0343 struct optee_supp *supp = &optee->supp;
0344 struct optee_supp_req *req;
0345 size_t n;
0346 size_t num_meta;
0347
0348 mutex_lock(&supp->mutex);
0349 req = supp_pop_req(supp, num_params, param, &num_meta);
0350 mutex_unlock(&supp->mutex);
0351
0352 if (IS_ERR(req)) {
0353
0354 return PTR_ERR(req);
0355 }
0356
0357
0358 for (n = 0; n < req->num_params; n++) {
0359 struct tee_param *p = req->param + n;
0360
0361 switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
0362 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
0363 case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
0364 p->u.value.a = param[n + num_meta].u.value.a;
0365 p->u.value.b = param[n + num_meta].u.value.b;
0366 p->u.value.c = param[n + num_meta].u.value.c;
0367 break;
0368 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
0369 case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
0370 p->u.memref.size = param[n + num_meta].u.memref.size;
0371 break;
0372 default:
0373 break;
0374 }
0375 }
0376 req->ret = ret;
0377
0378
0379 complete(&req->c);
0380
0381 return 0;
0382 }