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