security: tlk_driver: add session tracking
[linux-3.10.git] / security / tlk_driver / ote_device.c
1 /*
2  * Copyright (c) 2013-2014 NVIDIA Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #include <linux/atomic.h>
20 #include <linux/uaccess.h>
21 #include <linux/module.h>
22 #include <linux/slab.h>
23 #include <linux/fs.h>
24 #include <linux/printk.h>
25 #include <linux/ioctl.h>
26 #include <linux/miscdevice.h>
27 #include <linux/mm.h>
28 #include <asm/cacheflush.h>
29 #include <asm/outercache.h>
30 #include <linux/list.h>
31 #include <linux/dma-mapping.h>
32
33 #include "ote_protocol.h"
34
35 #define SET_ANSWER(a, r, ro)    { a.result = r; a.result_origin = ro; }
36
37 struct tlk_device tlk_dev;
38 DEFINE_MUTEX(smc_lock);
39
40 static int te_create_free_cmd_list(struct tlk_device *dev)
41 {
42         int cmd_desc_count, ret = 0;
43         struct te_cmd_req_desc *req_desc;
44         int bitmap_size;
45         bool use_reqbuf;
46
47         /*
48          * Check if new shared req/param register SMC is supported.
49          *
50          * If it is, TLK can map in the shared req/param buffers and do_smc
51          * only needs to send the offsets within each (with cache coherency
52          * being maintained by HW through an NS mapping).
53          *
54          * If the SMC support is not yet present, then fallback to the old
55          * mode of writing to an uncached buffer to maintain coherency (and
56          * phys addresses are passed in do_smc).
57          */
58         dev->req_param_buf = NULL;
59         use_reqbuf = !tlk_generic_smc(TE_SMC_REGISTER_REQ_BUF, 0, 0);
60
61         if (use_reqbuf) {
62                 dev->req_param_buf = kmalloc((2 * PAGE_SIZE), GFP_KERNEL);
63
64                 /* requests in the first page, params in the second */
65                 dev->req_addr   = (struct te_request *) dev->req_param_buf;
66                 dev->param_addr = (struct te_oper_param *)
67                                         (dev->req_param_buf + PAGE_SIZE);
68
69                 tlk_generic_smc(TE_SMC_REGISTER_REQ_BUF,
70                                 (uintptr_t)dev->req_addr, (2 * PAGE_SIZE));
71         } else {
72                 dev->req_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
73                                         &dev->req_addr_phys, GFP_KERNEL);
74                 dev->param_addr = dma_alloc_coherent(NULL, PAGE_SIZE,
75                                         &dev->param_addr_phys, GFP_KERNEL);
76         }
77
78         if (!dev->req_addr || !dev->param_addr || !dev->req_param_buf) {
79                 ret = -ENOMEM;
80                 goto error;
81         }
82
83         /* alloc param bitmap allocator */
84         bitmap_size = BITS_TO_LONGS(TE_PARAM_MAX) * sizeof(long);
85         dev->param_bitmap = kzalloc(bitmap_size, GFP_KERNEL);
86
87         for (cmd_desc_count = 0;
88                 cmd_desc_count < TE_CMD_DESC_MAX; cmd_desc_count++) {
89
90                 req_desc = kzalloc(sizeof(struct te_cmd_req_desc), GFP_KERNEL);
91                 if (req_desc == NULL) {
92                         pr_err("Failed to allocate cmd req descriptor\n");
93                         ret = -ENOMEM;
94                         goto error;
95                 }
96                 req_desc->req_addr = dev->req_addr + cmd_desc_count;
97                 INIT_LIST_HEAD(&(req_desc->list));
98
99                 /* Add the cmd param descriptor to free list */
100                 list_add_tail(&req_desc->list, &(dev->free_cmd_list));
101         }
102
103 error:
104         return ret;
105 }
106
107 static struct te_oper_param *te_get_free_params(struct tlk_device *dev,
108         unsigned int nparams)
109 {
110         struct te_oper_param *params = NULL;
111         int idx, nbits;
112
113         if (nparams) {
114                 nbits = get_count_order(nparams);
115                 idx = bitmap_find_free_region(dev->param_bitmap,
116                                 TE_PARAM_MAX, nbits);
117                 if (idx >= 0)
118                         params = dev->param_addr + idx;
119         }
120         return params;
121 }
122
123 static void te_put_free_params(struct tlk_device *dev,
124         struct te_oper_param *params, uint32_t nparams)
125 {
126         int idx, nbits;
127
128         idx = (params - dev->param_addr);
129         nbits = get_count_order(nparams);
130         bitmap_release_region(dev->param_bitmap, idx, nbits);
131 }
132
133 static struct te_cmd_req_desc *te_get_free_cmd_desc(struct tlk_device *dev)
134 {
135         struct te_cmd_req_desc *cmd_desc = NULL;
136
137         if (!(list_empty(&(dev->free_cmd_list)))) {
138                 cmd_desc = list_first_entry(&(dev->free_cmd_list),
139                                 struct te_cmd_req_desc, list);
140                 list_del(&(cmd_desc->list));
141                 list_add_tail(&cmd_desc->list, &(dev->used_cmd_list));
142         }
143         return cmd_desc;
144 }
145
146 static void te_put_used_cmd_desc(struct tlk_device *dev,
147         struct te_cmd_req_desc *cmd_desc)
148 {
149         struct te_cmd_req_desc *param_desc, *tmp_param_desc;
150
151         if (cmd_desc) {
152                 list_for_each_entry_safe(param_desc, tmp_param_desc,
153                                 &(dev->used_cmd_list), list) {
154                         if (cmd_desc->req_addr == param_desc->req_addr) {
155                                 list_del(&param_desc->list);
156                                 list_add_tail(&param_desc->list,
157                                         &(dev->free_cmd_list));
158                         }
159                 }
160         }
161 }
162
163 static void __attribute__((unused)) te_print_cmd_list(
164         struct tlk_device *dev, int used_list)
165 {
166         struct te_cmd_req_desc *param_desc;
167
168         if (!used_list) {
169                 pr_info("Printing free cmd list\n");
170                 if (!(list_empty(&(dev->free_cmd_list)))) {
171                         list_for_each_entry(param_desc, &(dev->free_cmd_list),
172                                         list)
173                                 pr_info("Phys addr for cmd req desc (%p)\n",
174                                         param_desc->req_addr);
175                 }
176         } else {
177                 pr_info("Printing used cmd list\n");
178                 if (!(list_empty(&(dev->used_cmd_list)))) {
179                         list_for_each_entry(param_desc, &(dev->used_cmd_list),
180                                         list)
181                                 pr_info("Phys addr for cmd req desc (%p)\n",
182                                         param_desc->req_addr);
183                 }
184         }
185 }
186
187
188 static void te_close_sessions(struct tlk_context *context)
189 {
190         struct tlk_device *dev = context->dev;
191         union te_cmd cmd;
192         struct te_cmd_req_desc *cmd_desc = NULL;
193         struct te_request *request;
194         struct te_session *session, *tmp_session;
195
196         if (list_empty(&context->session_list))
197                 return;
198
199         cmd_desc = te_get_free_cmd_desc(dev);
200         if (!cmd_desc) {
201                 pr_err("%s: failed to get cmd_desc\n", __func__);
202                 return;
203         }
204
205         request = cmd_desc->req_addr;
206
207         list_for_each_entry_safe(session, tmp_session,
208                 &context->session_list, list) {
209
210                 memset(request, 0, sizeof(struct te_request));
211
212                 cmd.closesession.session_id = session->session_id;
213
214                 te_close_session(&cmd.closesession, request, context);
215         }
216
217         te_put_used_cmd_desc(dev, cmd_desc);
218 }
219
220 static int tlk_device_open(struct inode *inode, struct file *file)
221 {
222         struct tlk_context *context;
223         int ret = 0;
224
225         context = kzalloc(sizeof(struct tlk_context), GFP_KERNEL);
226         if (!context) {
227                 ret = -ENOMEM;
228                 goto error;
229         }
230         context->dev = &tlk_dev;
231         INIT_LIST_HEAD(&context->session_list);
232
233         file->private_data = context;
234         return 0;
235 error:
236         return ret;
237 }
238
239 static int tlk_device_release(struct inode *inode, struct file *file)
240 {
241         struct tlk_context *context = file->private_data;
242
243         /* close any open sessions */
244         te_close_sessions(context);
245
246         kfree(file->private_data);
247         file->private_data = NULL;
248         return 0;
249 }
250
251 static int copy_params_from_user(struct te_request *req,
252         struct te_operation *operation)
253 {
254         struct te_oper_param *param_array;
255         struct te_oper_param *user_param;
256         uint32_t i;
257
258         if (operation->list_count == 0)
259                 return 0;
260
261         param_array = (struct te_oper_param *)(uintptr_t)req->params;
262         if (param_array == NULL) {
263                 pr_err("param_array empty\n");
264                 return 1;
265         }
266
267         user_param = (struct te_oper_param *)(uintptr_t)operation->list_head;
268         for (i = 0; i < operation->list_count && user_param != NULL; i++) {
269                 if (copy_from_user(param_array + i, user_param,
270                                         sizeof(struct te_oper_param))) {
271                         pr_err("Failed to copy operation parameter:%d, %p, " \
272                                         "list_count: %d\n",
273                                         i, user_param, operation->list_count);
274                         return 1;
275                 }
276                 user_param = (struct te_oper_param *)(uintptr_t)
277                         param_array[i].next_ptr_user;
278         }
279         return 0;
280 }
281
282 static int copy_params_to_user(struct te_request *req,
283         struct te_operation *operation)
284 {
285         struct te_oper_param *param_array;
286         struct te_oper_param *user_param;
287         uint32_t i;
288
289         if (operation->list_count == 0)
290                 return 0;
291
292         param_array = (struct te_oper_param *)(uintptr_t)req->params;
293         if (param_array == NULL) {
294                 pr_err("param_array empty\n");
295                 return 1;
296         }
297
298         user_param =
299                 (struct te_oper_param *)(uintptr_t)operation->list_head;
300         for (i = 0; i < req->params_size; i++) {
301                 if (copy_to_user(user_param, param_array + i,
302                                         sizeof(struct te_oper_param))) {
303                         pr_err("Failed to copy back parameter:%d %p\n", i,
304                                         user_param);
305                         return 1;
306                 }
307                 user_param = (struct te_oper_param *)(uintptr_t)
308                         param_array[i].next_ptr_user;
309         }
310         return 0;
311 }
312
313 static long te_handle_trustedapp_ioctl(struct file *file,
314         unsigned int ioctl_num, unsigned long ioctl_param)
315 {
316         long err = 0;
317         union te_cmd cmd;
318         struct te_operation *operation = NULL;
319         struct te_oper_param *params = NULL;
320         struct te_request *request;
321         void __user *ptr_user_answer = NULL;
322         struct te_answer answer;
323         struct te_cmd_req_desc *cmd_desc = NULL;
324         struct tlk_context *context = file->private_data;
325         struct tlk_device *dev = context->dev;
326
327         if (copy_from_user(&cmd, (void __user *)ioctl_param,
328                                 sizeof(union te_cmd))) {
329                 pr_err("Failed to copy command request\n");
330                 err = -EFAULT;
331                 goto error;
332         }
333
334         memset(&answer, 0, sizeof(struct te_answer));
335
336         switch (ioctl_num) {
337         case TE_IOCTL_OPEN_CLIENT_SESSION:
338                 operation = &cmd.opensession.operation;
339                 ptr_user_answer = (void *)(uintptr_t)cmd.opensession.answer;
340
341                 cmd_desc = te_get_free_cmd_desc(dev);
342                 params = te_get_free_params(dev, operation->list_count);
343
344                 if (!cmd_desc || (operation->list_count && !params)) {
345                         SET_ANSWER(answer,
346                                    OTE_ERROR_OUT_OF_MEMORY,
347                                    OTE_RESULT_ORIGIN_COMMS);
348                         pr_err("failed to get cmd_desc/params\n");
349                         goto error;
350                 }
351
352                 request = cmd_desc->req_addr;
353                 memset(request, 0, sizeof(struct te_request));
354
355                 request->params = (uintptr_t)params;
356                 request->params_size = operation->list_count;
357
358                 if (copy_params_from_user(request, operation)) {
359                         err = -EFAULT;
360                         pr_info("failed to copy params from user\n");
361                         goto error;
362                 }
363
364                 te_open_session(&cmd.opensession, request, context);
365
366                 SET_ANSWER(answer, request->result, request->result_origin);
367                 answer.session_id = request->session_id;
368                 break;
369
370         case TE_IOCTL_CLOSE_CLIENT_SESSION:
371                 ptr_user_answer = (void *)(uintptr_t)cmd.closesession.answer;
372                 cmd_desc = te_get_free_cmd_desc(dev);
373                 if (!cmd_desc) {
374                         SET_ANSWER(answer,
375                                    OTE_ERROR_OUT_OF_MEMORY,
376                                    OTE_RESULT_ORIGIN_COMMS);
377                         pr_err("failed to get cmd_desc\n");
378                         goto error;
379                 }
380
381                 request = cmd_desc->req_addr;
382                 memset(request, 0, sizeof(struct te_request));
383
384                 /* close session cannot fail */
385                 te_close_session(&cmd.closesession, request, context);
386                 break;
387
388         case TE_IOCTL_LAUNCH_OPERATION:
389                 operation = &cmd.launchop.operation;
390                 ptr_user_answer = (void *)(uintptr_t)cmd.launchop.answer;
391
392                 cmd_desc = te_get_free_cmd_desc(dev);
393                 params = te_get_free_params(dev, operation->list_count);
394
395                 if (!cmd_desc || (operation->list_count && !params)) {
396                         SET_ANSWER(answer,
397                                    OTE_ERROR_OUT_OF_MEMORY,
398                                    OTE_RESULT_ORIGIN_COMMS);
399                         pr_err("failed to get cmd_desc/params\n");
400                         goto error;
401                 }
402
403                 request = cmd_desc->req_addr;
404                 memset(request, 0, sizeof(struct te_request));
405
406                 request->params = (uintptr_t)params;
407                 request->params_size = operation->list_count;
408
409                 if (copy_params_from_user(request, operation)) {
410                         err = -EFAULT;
411                         pr_info("failed to copy params from user\n");
412                         goto error;
413                 }
414
415                 te_launch_operation(&cmd.launchop, request, context);
416
417                 SET_ANSWER(answer, request->result, request->result_origin);
418                 break;
419
420         default:
421                 pr_err("Invalid IOCTL Cmd\n");
422                 err = -EINVAL;
423                 goto error;
424         }
425         if (ptr_user_answer && !err) {
426                 if (copy_to_user(ptr_user_answer, &answer,
427                         sizeof(struct te_answer))) {
428                         pr_err("Failed to copy answer\n");
429                         err = -EFAULT;
430                 }
431         }
432         if (request->params && !err) {
433                 if (copy_params_to_user(request, operation)) {
434                         pr_err("Failed to copy return params\n");
435                         err = -EFAULT;
436                 }
437         }
438
439 error:
440         if (cmd_desc)
441                 te_put_used_cmd_desc(dev, cmd_desc);
442         if (params)
443                 te_put_free_params(dev, params, operation->list_count);
444         return err;
445 }
446
447 static long tlk_device_ioctl(struct file *file, unsigned int ioctl_num,
448         unsigned long ioctl_param)
449 {
450         int err;
451
452         switch (ioctl_num) {
453         case TE_IOCTL_OPEN_CLIENT_SESSION:
454         case TE_IOCTL_CLOSE_CLIENT_SESSION:
455         case TE_IOCTL_LAUNCH_OPERATION:
456                 mutex_lock(&smc_lock);
457                 err = te_handle_trustedapp_ioctl(file, ioctl_num, ioctl_param);
458                 mutex_unlock(&smc_lock);
459                 break;
460
461         case TE_IOCTL_SS_CMD:
462                 err = te_handle_ss_ioctl(file, ioctl_num, ioctl_param);
463                 break;
464
465         default:
466                 pr_err("%s: Invalid IOCTL (0x%x) id 0x%x max 0x%lx\n",
467                         __func__, ioctl_num, _IOC_NR(ioctl_num),
468                         (unsigned long)TE_IOCTL_MAX_NR);
469                 err = -EINVAL;
470                 break;
471         }
472
473         return err;
474 }
475
476 /*
477  * tlk_driver function definitions.
478  */
479 static const struct file_operations tlk_device_fops = {
480         .owner = THIS_MODULE,
481         .open = tlk_device_open,
482         .release = tlk_device_release,
483         .unlocked_ioctl = tlk_device_ioctl,
484 #ifdef CONFIG_COMPAT
485         .compat_ioctl = tlk_device_ioctl,
486 #endif
487 };
488
489 struct miscdevice tlk_misc_device = {
490         .minor = MISC_DYNAMIC_MINOR,
491         .name = "tlk_device",
492         .fops = &tlk_device_fops,
493 };
494
495 static int __init tlk_init(void)
496 {
497         int ret;
498
499         INIT_LIST_HEAD(&(tlk_dev.used_cmd_list));
500         INIT_LIST_HEAD(&(tlk_dev.free_cmd_list));
501
502         ret = te_create_free_cmd_list(&tlk_dev);
503         if (ret != 0)
504                 return ret;
505
506         return misc_register(&tlk_misc_device);
507 }
508
509 module_init(tlk_init);