OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [src/] [generic/] [capability.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
/*
2
 * Capability checking for all system calls
3
 *
4
 * Copyright (C) 2009 Bahadir Balban
5
 */
6
#include <l4/generic/resource.h>
7
#include <l4/generic/capability.h>
8
#include <l4/generic/container.h>
9
#include <l4/generic/cap-types.h>
10
#include <l4/generic/tcb.h>
11
#include <l4/api/capability.h>
12
#include <l4/api/thread.h>
13
#include <l4/api/errno.h>
14
#include <l4/lib/printk.h>
15
#include <l4/api/thread.h>
16
#include <l4/api/exregs.h>
17
#include <l4/api/ipc.h>
18
#include <l4/api/irq.h>
19
#include <l4/api/cache.h>
20
#include INC_GLUE(message.h)
21
#include INC_GLUE(ipc.h)
22
 
23
void capability_init(struct capability *cap)
24
{
25
        cap->capid = id_new(&kernel_resources.capability_ids);
26
        link_init(&cap->list);
27
}
28
 
29
/*
30
 * Boot-time function to create capability without
31
 * capability checking
32
 */
33
struct capability *boot_capability_create(void)
34
{
35
        struct capability *cap = boot_alloc_capability();
36
 
37
        capability_init(cap);
38
 
39
        return cap;
40
}
41
 
42
struct capability *capability_create(void)
43
{
44
        struct capability *cap;
45
 
46
        if (!(cap = alloc_capability()))
47
                return 0;
48
 
49
        capability_init(cap);
50
 
51
        return cap;
52
}
53
 
54
#if defined(CONFIG_CAPABILITIES)
55
int capability_consume(struct capability *cap, int quantity)
56
{
57
        if (cap->size < cap->used + quantity)
58
                return -ENOCAP;
59
 
60
        cap->used += quantity;
61
 
62
        return 0;
63
}
64
 
65
int capability_free(struct capability *cap, int quantity)
66
{
67
        BUG_ON((cap->used -= quantity) < 0);
68
        return 0;
69
}
70
 
71
#else
72
int capability_consume(struct capability *cap, int quantity)
73
{
74
        return 0;
75
}
76
 
77
int capability_free(struct capability *cap, int quantity)
78
{
79
        return 0;
80
}
81
#endif
82
 
83
struct capability *cap_list_find_by_rtype(struct cap_list *cap_list,
84
                                          unsigned int rtype)
85
{
86
        struct capability *cap;
87
 
88
        list_foreach_struct(cap, &cap_list->caps, list)
89
                if (cap_rtype(cap) == rtype)
90
                        return cap;
91
 
92
        return 0;
93
}
94
 
95
/*
96
 * Find a capability from a list by its resource type
97
 * Search all capability lists that task is allowed.
98
 *
99
 * FIXME:
100
 * Tasks should not always search for a capability randomly. Consider
101
 * mutexes, if a mutex is freed, it needs to be accounted to private
102
 * pool first if that is not full, because freeing it into shared
103
 * pool may lose the mutex right to another task. In other words,
104
 * when you're freeing a mutex, we should know which capability pool
105
 * to free it to.
106
 *
107
 * In conclusion freeing of pool-type capabilities need to be done
108
 * in order of privacy.
109
 */
110
struct capability *capability_find_by_rtype(struct ktcb *task,
111
                                            unsigned int rtype)
112
{
113
        struct capability *cap;
114
 
115
        /* Search task's own list */
116
        list_foreach_struct(cap, &task->cap_list.caps, list)
117
                if (cap_rtype(cap) == rtype)
118
                        return cap;
119
 
120
        /* Search space list */
121
        list_foreach_struct(cap, &task->space->cap_list.caps, list)
122
                if (cap_rtype(cap) == rtype)
123
                        return cap;
124
 
125
        /* Search container list */
126
        list_foreach_struct(cap, &task->container->cap_list.caps, list)
127
                if (cap_rtype(cap) == rtype)
128
                        return cap;
129
 
130
        return 0;
131
}
132
 
133
struct capability *cap_find_by_capid(l4id_t capid, struct cap_list **cap_list)
134
{
135
        struct capability *cap;
136
        struct ktcb *task = current;
137
 
138
        /* Search task's own list */
139
        list_foreach_struct(cap, &task->cap_list.caps, list)
140
                if (cap->capid == capid) {
141
                        *cap_list = &task->cap_list;
142
                        return cap;
143
                }
144
 
145
        /* Search space list */
146
        list_foreach_struct(cap, &task->space->cap_list.caps, list)
147
                if (cap->capid == capid) {
148
                        *cap_list = &task->space->cap_list;
149
                        return cap;
150
                }
151
 
152
        /* Search container list */
153
        list_foreach_struct(cap, &task->container->cap_list.caps, list)
154
                if (cap->capid == capid) {
155
                        *cap_list = &task->container->cap_list;
156
                        return cap;
157
                }
158
 
159
        return 0;
160
}
161
 
162
int cap_count(struct ktcb *task)
163
{
164
        return task->cap_list.ncaps +
165
               task->space->cap_list.ncaps +
166
               task->container->cap_list.ncaps;
167
}
168
 
169
typedef struct capability *(*cap_match_func_t) \
170
        (struct capability *cap, void *match_args);
171
 
172
/*
173
 * This is used by every system call to match each
174
 * operation with a capability in a syscall-specific way.
175
 */
176
struct capability *cap_find(struct ktcb *task, cap_match_func_t cap_match_func,
177
                             void *match_args, unsigned int cap_type)
178
{
179
        struct capability *cap, *found;
180
 
181
        /* Search task's own list */
182
        list_foreach_struct(cap, &task->cap_list.caps, list)
183
                if (cap_type(cap) == cap_type &&
184
                    ((found = cap_match_func(cap, match_args))))
185
                        return found;
186
 
187
        /* Search space list */
188
        list_foreach_struct(cap, &task->space->cap_list.caps, list)
189
                if (cap_type(cap) == cap_type &&
190
                    ((found = cap_match_func(cap, match_args))))
191
                        return found;
192
 
193
        /* Search container list */
194
        list_foreach_struct(cap, &task->container->cap_list.caps, list)
195
                if (cap_type(cap) == cap_type &&
196
                    ((found = cap_match_func(cap, match_args))))
197
                        return found;
198
 
199
        return 0;
200
}
201
 
202
struct sys_mutex_args {
203
        unsigned long address;
204
        unsigned int op;
205
};
206
 
207
/*
208
 * Check broadly the ability to do mutex ops. Check it by
209
 * the thread, space or container, (i.e. the group that can
210
 * do this operation broadly)
211
 *
212
 * Note, that we check mutex_address elsewhere as a quick,
213
 * per-task virt_to_phys translation that would not get
214
 * easily/quickly satisfied by a memory capability checking.
215
 *
216
 * While this is not %100 right from a capability checking
217
 * point-of-view, it is a shortcut that works and makes sense.
218
 *
219
 * For sake of completion, the right way to do it would be to
220
 * add MUTEX_LOCKABLE, MUTEX_UNLOCKABLE attributes to both
221
 * virtual and physical memory caps of a task, search those
222
 * to validate the address. But we would have to translate
223
 * from the page tables either ways.
224
 */
225
struct capability *
226
cap_match_mutex(struct capability *cap, void *args)
227
{
228
        /* Unconditionally expect these flags */
229
        unsigned int perms = CAP_UMUTEX_LOCK | CAP_UMUTEX_UNLOCK;
230
 
231
        if ((cap->access & perms) != perms)
232
                return 0;
233
 
234
        /* Now check the usual restype/resid pair */
235
        switch (cap_rtype(cap)) {
236
        case CAP_RTYPE_THREAD:
237
                if (current->tid != cap->resid)
238
                        return 0;
239
                break;
240
        case CAP_RTYPE_SPACE:
241
                if (current->space->spid != cap->resid)
242
                        return 0;
243
                break;
244
        case CAP_RTYPE_CONTAINER:
245
                if (current->container->cid != cap->resid)
246
                        return 0;
247
                break;
248
        default:
249
                BUG(); /* Unknown cap type is a bug */
250
        }
251
 
252
        return cap;
253
}
254
 
255
struct sys_capctrl_args {
256
        unsigned int req;
257
        unsigned int flags;
258
        struct ktcb *task;
259
};
260
 
261
struct capability *
262
cap_match_capctrl(struct capability *cap, void *args_ptr)
263
{
264
        struct sys_capctrl_args *args = args_ptr;
265
        unsigned int req = args->req;
266
        struct ktcb *target = args->task;
267
 
268
        /* Check operation privileges */
269
        switch (req) {
270
        case CAP_CONTROL_NCAPS:
271
        case CAP_CONTROL_READ:
272
                if (!(cap->access & CAP_CAP_READ))
273
                        return 0;
274
                break;
275
        case CAP_CONTROL_SHARE:
276
                if (!(cap->access & CAP_CAP_SHARE))
277
                        return 0;
278
                break;
279
        case CAP_CONTROL_GRANT:
280
                if (!(cap->access & CAP_CAP_GRANT))
281
                        return 0;
282
                break;
283
        case CAP_CONTROL_REPLICATE:
284
                if (!(cap->access & CAP_CAP_REPLICATE))
285
                        return 0;
286
                break;
287
        case CAP_CONTROL_SPLIT:
288
                if (!(cap->access & CAP_CAP_SPLIT))
289
                        return 0;
290
                break;
291
        case CAP_CONTROL_DEDUCE:
292
                if (!(cap->access & CAP_CAP_DEDUCE))
293
                        return 0;
294
                break;
295
        case CAP_CONTROL_DESTROY:
296
                if (!(cap->access & CAP_CAP_DESTROY))
297
                        return 0;
298
                break;
299
        default:
300
                /* We refuse to accept anything else */
301
                return 0;
302
        }
303
 
304
        /* Now check the usual restype/resid pair */
305
        switch (cap_rtype(cap)) {
306
        case CAP_RTYPE_THREAD:
307
                if (target->tid != cap->resid)
308
                        return 0;
309
                break;
310
        case CAP_RTYPE_SPACE:
311
                if (target->space->spid != cap->resid)
312
                        return 0;
313
                break;
314
        case CAP_RTYPE_CONTAINER:
315
                if (target->container->cid != cap->resid)
316
                        return 0;
317
                break;
318
        default:
319
                BUG(); /* Unknown cap type is a bug */
320
        }
321
 
322
        return cap;
323
}
324
 
325
struct sys_ipc_args {
326
        struct ktcb *task;
327
        unsigned int ipc_type;
328
        unsigned int xfer_type;
329
};
330
 
331
/*
332
 * Matches ipc direction, transfer type and target resource.
333
 *
334
 * Currently, receives are not checked as only sends have
335
 * a solid target id. Receives can be from any thread with
336
 * no particular target.
337
 */
338
struct capability *
339
cap_match_ipc(struct capability *cap, void *args_ptr)
340
{
341
        struct sys_ipc_args *args = args_ptr;
342
        struct ktcb *target = args->task;
343
 
344
        /* Check ipc type privileges */
345
        switch (args->xfer_type) {
346
        case IPC_FLAGS_SHORT:
347
                if (!(cap->access & CAP_IPC_SHORT))
348
                        return 0;
349
                break;
350
        case IPC_FLAGS_FULL:
351
                if (!(cap->access & CAP_IPC_FULL))
352
                        return 0;
353
                break;
354
        case IPC_FLAGS_EXTENDED:
355
                if (!(cap->access & CAP_IPC_EXTENDED))
356
                        return 0;
357
                break;
358
        default:
359
                return 0;
360
        }
361
 
362
        /* NOTE: We only check on send capability */
363
        if (args->ipc_type & IPC_SEND)
364
                if (!(cap->access & CAP_IPC_SEND))
365
                        return 0;
366
 
367
        /*
368
         * We have a target thread, check if capability match
369
         * any resource fields in target
370
         */
371
        switch (cap_rtype(cap)) {
372
        case CAP_RTYPE_THREAD:
373
                if (target->tid != cap->resid)
374
                        return 0;
375
                break;
376
        case CAP_RTYPE_SPACE:
377
                if (target->space->spid != cap->resid)
378
                        return 0;
379
                break;
380
        case CAP_RTYPE_CONTAINER:
381
                if (target->container->cid != cap->resid)
382
                        return 0;
383
                break;
384
        default:
385
                BUG(); /* Unknown cap type is a bug */
386
        }
387
 
388
        return cap;
389
}
390
 
391
struct sys_exregs_args {
392
        struct exregs_data *exregs;
393
        struct ktcb *task;
394
};
395
 
396
/*
397
 * CAP_TYPE_EXREGS already matched upon entry
398
 */
399
struct capability *
400
cap_match_exregs(struct capability *cap, void *args_ptr)
401
{
402
        struct sys_exregs_args *args = args_ptr;
403
        struct exregs_data *exregs = args->exregs;
404
        struct ktcb *target = args->task;
405
 
406
        /* Check operation privileges */
407
        if (exregs->valid_vect & EXREGS_VALID_REGULAR_REGS)
408
                if (!(cap->access & CAP_EXREGS_RW_REGS))
409
                        return 0;
410
        if (exregs->valid_vect & EXREGS_VALID_SP)
411
                if (!(cap->access & CAP_EXREGS_RW_SP))
412
                        return 0;
413
        if (exregs->valid_vect & EXREGS_VALID_PC)
414
                if (!(cap->access & CAP_EXREGS_RW_PC))
415
                        return 0;
416
        if (args->exregs->valid_vect & EXREGS_SET_UTCB)
417
                if (!(cap->access & CAP_EXREGS_RW_UTCB))
418
                        return 0;
419
        if (args->exregs->valid_vect & EXREGS_SET_PAGER)
420
                if (!(cap->access & CAP_EXREGS_RW_PAGER))
421
                        return 0;
422
 
423
        /*
424
         * We have a target thread, check if capability
425
         * match any resource fields in target.
426
         */
427
        switch (cap_rtype(cap)) {
428
        case CAP_RTYPE_THREAD:
429
                if (target->tid != cap->resid)
430
                        return 0;
431
                break;
432
        case CAP_RTYPE_SPACE:
433
                if (target->space->spid != cap->resid)
434
                        return 0;
435
                break;
436
        case CAP_RTYPE_CONTAINER:
437
                if (target->container->cid != cap->resid)
438
                        return 0;
439
                break;
440
        default:
441
                BUG(); /* Unknown cap type is a bug */
442
        }
443
 
444
        return cap;
445
}
446
 
447
/*
448
 * FIXME: Issues on capabilities:
449
 *
450
 * As new pagers, thread groups,
451
 * thread ids, spaces are created, we need to
452
 * give them thread_control capabilities dynamically,
453
 * based on those ids!!! How do we get to do that, so that
454
 * in userspace it looks not so difficult ???
455
 *
456
 * What do you match here?
457
 *
458
 * THREAD_CREATE:
459
 *  - TC_SAME_SPACE
460
 *    - spid -> Does thread have cap to create in that space?
461
 *    - cid -> Does thread have cap to create in that container?
462
 *    - tgid -> Does thread have cap to create in that thread group?
463
 *    - pagerid -> Does thread have cap to create in that group of paged threads?
464
 *  - TC_NEW_SPACE or TC_COPY_SPACE
465
 *    - Check cid, tgid, pagerid,
466
 *  - TC_SHARE_GROUP
467
 *    - Check tgid
468
 *  - TC_AS_PAGER
469
 *    - pagerid -> Does thread have cap to create in that group of paged threads?
470
 *  - TC_SHARE_PAGER
471
 *    - pagerid -> Does thread have cap to create in that group of paged threads?
472
 *   New group -> New set of caps, thread_control, exregs, ipc, ... all of them!
473
 *   New pager -> New set of caps for that pager.
474
 *   New thread -> New set of caps for that thread!
475
 *   New space -> New set of caps for that space! So many capabilities!
476
 */
477
 
478
struct sys_tctrl_args {
479
        struct ktcb *task;
480
        unsigned int flags;
481
        struct task_ids *ids;
482
};
483
 
484
/*
485
 * CAP_TYPE_TCTRL matched upon entry
486
 */
487
struct capability *cap_match_thread(struct capability *cap,
488
                                    void *args_ptr)
489
{
490
        struct sys_tctrl_args *args = args_ptr;
491
        struct ktcb *target = args->task;
492
        unsigned int action_flags = args->flags & THREAD_ACTION_MASK;
493
 
494
        /* Check operation privileges */
495
        switch (action_flags) {
496
        case THREAD_CREATE:
497
                if (!(cap->access & CAP_TCTRL_CREATE))
498
                        return 0;
499
                break;
500
        case THREAD_DESTROY:
501
                if (!(cap->access & CAP_TCTRL_DESTROY))
502
                        return 0;
503
                break;
504
        case THREAD_SUSPEND:
505
                if (!(cap->access & CAP_TCTRL_SUSPEND))
506
                        return 0;
507
                break;
508
        case THREAD_RUN:
509
                if (!(cap->access & CAP_TCTRL_RUN))
510
                        return 0;
511
                break;
512
        case THREAD_RECYCLE:
513
                if (!(cap->access & CAP_TCTRL_RECYCLE))
514
                        return 0;
515
                break;
516
        case THREAD_WAIT:
517
                if (!(cap->access & CAP_TCTRL_WAIT))
518
                        return 0;
519
                break;
520
        default:
521
                /* We refuse to accept anything else */
522
                return 0;
523
        }
524
 
525
        /* If no target and create, or vice versa, it really is a bug */
526
        BUG_ON(!target && action_flags != THREAD_CREATE);
527
        BUG_ON(target && action_flags == THREAD_CREATE);
528
 
529
        if (action_flags == THREAD_CREATE) {
530
                /*
531
                 * NOTE: Currently we only allow creation in
532
                 * current container.
533
                 *
534
                 * TODO: Add capability checking for space,
535
                 * as well.
536
                 *
537
                 * We _assume_ target is the largest group,
538
                 * e.g. same container as current. We check
539
                 * for `container' as target in capability
540
                 */
541
                if (cap_rtype(cap) != CAP_RTYPE_CONTAINER)
542
                        return 0;
543
                if (cap->resid != curcont->cid)
544
                        return 0;
545
                /* Resource type and id match, success */
546
                return cap;
547
        }
548
 
549
        /*
550
         * We have a target thread, check if capability match
551
         * any resource fields in target
552
         */
553
        switch (cap_rtype(cap)) {
554
        case CAP_RTYPE_THREAD:
555
                if (target->tid != cap->resid)
556
                        return 0;
557
                break;
558
        case CAP_RTYPE_SPACE:
559
                if (target->space->spid != cap->resid)
560
                        return 0;
561
                break;
562
        case CAP_RTYPE_CONTAINER:
563
                if (target->container->cid != cap->resid)
564
                        return 0;
565
                break;
566
        default:
567
                BUG(); /* Unknown cap type is a bug */
568
        }
569
        return cap;
570
}
571
 
572
struct sys_map_args {
573
        struct ktcb *task;
574
        unsigned long phys;
575
        unsigned long virt;
576
        unsigned long npages;
577
        unsigned int flags;
578
};
579
 
580
/*
581
 * CAP_TYPE_MAP already matched upon entry
582
 */
583
struct capability *cap_match_mem(struct capability *cap,
584
                                 void *args_ptr)
585
{
586
        struct sys_map_args *args = args_ptr;
587
        struct ktcb *target = args->task;
588
        unsigned long long start, end, pfn_point;
589
        unsigned long pfn;
590
        unsigned int perms;
591
 
592
        /* Set base according to what type of mem type we're matching */
593
        if (cap_type(cap) == CAP_TYPE_MAP_PHYSMEM)
594
                pfn = __pfn(args->phys);
595
        else
596
                pfn = __pfn(args->virt);
597
 
598
        /* Long long range check to avoid overflow */
599
        start = cap->start;
600
        end = cap->end;
601
        pfn_point = pfn;
602
        if (start > pfn_point || cap->end < pfn_point + args->npages)
603
                return 0;
604
 
605
        /* Check permissions */
606
        switch (args->flags) {
607
        case MAP_USR_RW:
608
                perms = CAP_MAP_READ | CAP_MAP_WRITE | CAP_MAP_CACHED;
609
                if ((cap->access & perms) != perms)
610
                        return 0;
611
                break;
612
        case MAP_USR_RWX:
613
                perms = CAP_MAP_READ | CAP_MAP_WRITE |
614
                        CAP_MAP_EXEC | CAP_MAP_CACHED;
615
                if ((cap->access & perms) != perms)
616
                        return 0;
617
                break;
618
        case MAP_USR_RO:
619
                perms = CAP_MAP_READ | CAP_MAP_CACHED;
620
                if ((cap->access & perms) != perms)
621
                        return 0;
622
                break;
623
        case MAP_USR_RX:
624
                perms = CAP_MAP_READ | CAP_MAP_EXEC | CAP_MAP_CACHED;
625
                if ((cap->access & perms) != perms)
626
                        return 0;
627
                break;
628
        case MAP_USR_IO:
629
                perms = CAP_MAP_READ | CAP_MAP_WRITE | CAP_MAP_UNCACHED;
630
                if ((cap->access & perms) != perms)
631
                        return 0;
632
                break;
633
        case MAP_UNMAP: /* Check for unmap syscall */
634
                if (!(cap->access & CAP_MAP_UNMAP))
635
                        return 0;
636
                break;
637
        default:
638
                /* Anything else is an invalid/unrecognised argument */
639
                return 0;
640
        }
641
 
642
        /*
643
         * We have a target thread, check if capability match
644
         * any resource fields in target
645
         */
646
        switch (cap_rtype(cap)) {
647
        case CAP_RTYPE_THREAD:
648
                if (target->tid != cap->resid)
649
                        return 0;
650
                break;
651
        case CAP_RTYPE_SPACE:
652
                if (target->space->spid != cap->resid)
653
                        return 0;
654
                break;
655
        case CAP_RTYPE_CONTAINER:
656
                if (target->container->cid != cap->resid)
657
                        return 0;
658
                break;
659
        default:
660
                BUG(); /* Unknown cap type is a bug */
661
        }
662
 
663
        return cap;
664
}
665
 
666
struct sys_irqctrl_args {
667
        struct ktcb *registrant;
668
        unsigned int req;
669
        unsigned int flags;
670
        l4id_t irq;
671
};
672
 
673
/*
674
 * CAP_TYPE_MAP already matched upon entry.
675
 *
676
 * Match only device-specific details, e.g. irq registration
677
 * capability
678
 */
679
struct capability *cap_match_devmem(struct capability *cap,
680
                                    void *args_ptr)
681
{
682
        struct sys_irqctrl_args *args = args_ptr;
683
        struct ktcb *target = args->registrant;
684
        unsigned int perms;
685
 
686
        /* It must be a physmem type */
687
        if (cap_type(cap) != CAP_TYPE_MAP_PHYSMEM)
688
                return 0;
689
 
690
        /* It must be a device */
691
        if (!cap_is_devmem(cap))
692
                return 0;
693
 
694
        /* Irq numbers should match */
695
        if (cap->irq != args->irq)
696
                return 0;
697
 
698
        /* Check permissions, we only check irq specific */
699
        switch (args->req) {
700
        case IRQ_CONTROL_REGISTER:
701
                perms = CAP_IRQCTRL_REGISTER;
702
                if ((cap->access & perms) != perms)
703
                        return 0;
704
                break;
705
        default:
706
                /* Anything else is an invalid/unrecognised argument */
707
                return 0;
708
        }
709
 
710
        /*
711
         * Check that irq registration to target is covered
712
         * by the capability containment rules.
713
         */
714
        switch (cap_rtype(cap)) {
715
        case CAP_RTYPE_THREAD:
716
                if (target->tid != cap->resid)
717
                        return 0;
718
                break;
719
        case CAP_RTYPE_SPACE:
720
                if (target->space->spid != cap->resid)
721
                        return 0;
722
                break;
723
        case CAP_RTYPE_CONTAINER:
724
                if (target->container->cid != cap->resid)
725
                        return 0;
726
                break;
727
        default:
728
                BUG(); /* Unknown cap type is a bug */
729
        }
730
 
731
        return cap;
732
}
733
 
734
/*
735
 * CAP_TYPE_IRQCTRL already matched
736
 */
737
struct capability *cap_match_irqctrl(struct capability *cap,
738
                                     void *args_ptr)
739
{
740
        struct sys_irqctrl_args *args = args_ptr;
741
        struct ktcb *target = args->registrant;
742
 
743
        /* Check operation privileges */
744
        switch (args->req) {
745
        case IRQ_CONTROL_REGISTER:
746
                if (!(cap->access & CAP_IRQCTRL_REGISTER))
747
                        return 0;
748
                break;
749
        case IRQ_CONTROL_WAIT:
750
                if (!(cap->access & CAP_IRQCTRL_WAIT))
751
                        return 0;
752
                break;
753
        default:
754
                /* We refuse to accept anything else */
755
                return 0;
756
        }
757
 
758
        /*
759
         * Target thread is the thread that is going to
760
         * handle the irqs. Check if capability matches
761
         * the target in any of its containment level.
762
         */
763
        switch (cap_rtype(cap)) {
764
        case CAP_RTYPE_THREAD:
765
                if (target->tid != cap->resid)
766
                        return 0;
767
                break;
768
        case CAP_RTYPE_SPACE:
769
                if (target->space->spid != cap->resid)
770
                        return 0;
771
                break;
772
        case CAP_RTYPE_CONTAINER:
773
                if (target->container->cid != cap->resid)
774
                        return 0;
775
                break;
776
        default:
777
                BUG(); /* Unknown cap type is a bug */
778
        }
779
 
780
        return cap;
781
}
782
 
783
 
784
struct sys_cache_args {
785
        unsigned long start;
786
        unsigned long npages;
787
        unsigned int flags;
788
};
789
 
790
struct capability *cap_match_cache(struct capability *cap, void *args_ptr)
791
{
792
        struct sys_cache_args *args = args_ptr;
793
        unsigned long pfn = __pfn(args->start);
794
        unsigned long long start, end, pfn_point;
795
        unsigned int perms;
796
 
797
        /* Long long range check to avoid overflow */
798
        start = cap->start;
799
        end = cap->end;
800
        pfn_point = pfn;
801
        if (start > pfn_point || end < pfn_point + args->npages)
802
                return 0;
803
 
804
        /* Check permissions */
805
        switch (args->flags) {
806
        /* check for cache functionality flags */
807
        case L4_INVALIDATE_DCACHE:
808
        case L4_INVALIDATE_ICACHE:
809
        case L4_INVALIDATE_TLB:
810
                perms = CAP_CACHE_INVALIDATE;
811
                if ((cap->access & perms) != perms)
812
                        return 0;
813
                break;
814
 
815
        case L4_CLEAN_DCACHE:
816
        case L4_CLEAN_INVALIDATE_DCACHE:
817
                perms = CAP_CACHE_CLEAN;
818
                if ((cap->access & perms) != perms)
819
                        return 0;
820
                break;
821
 
822
        default:
823
                /* Anything else is an invalid/unrecognised argument */
824
                return 0;
825
        }
826
 
827
        return cap;
828
}
829
 
830
#if defined(CONFIG_CAPABILITIES)
831
int cap_mutex_check(unsigned long mutex_address, int mutex_op)
832
{
833
        struct sys_mutex_args args = {
834
                .address = mutex_address,
835
                .op = mutex_op,
836
        };
837
 
838
        if (!(cap_find(current, cap_match_mutex,
839
                       &args, CAP_TYPE_UMUTEX)))
840
                return -ENOCAP;
841
 
842
        return 0;
843
}
844
 
845
int cap_cap_check(struct ktcb *task, unsigned int req, unsigned int flags)
846
{
847
        struct sys_capctrl_args args = {
848
                .req = req,
849
                .flags = flags,
850
                .task = task,
851
        };
852
 
853
        if (!(cap_find(current, cap_match_capctrl,
854
                       &args, CAP_TYPE_CAP)))
855
                return -ENOCAP;
856
 
857
        return 0;
858
}
859
 
860
int cap_map_check(struct ktcb *target, unsigned long phys, unsigned long virt,
861
                  unsigned long npages, unsigned int flags)
862
{
863
        struct capability *physmem, *virtmem;
864
        struct sys_map_args args = {
865
                .task = target,
866
                .phys = phys,
867
                .virt = virt,
868
                .npages = npages,
869
                .flags = flags,
870
        };
871
 
872
        if (!(physmem = cap_find(current, cap_match_mem,
873
                                 &args, CAP_TYPE_MAP_PHYSMEM)))
874
                return -ENOCAP;
875
 
876
        if (!(virtmem = cap_find(current, cap_match_mem,
877
                                 &args, CAP_TYPE_MAP_VIRTMEM)))
878
                return -ENOCAP;
879
 
880
        return 0;
881
}
882
 
883
int cap_unmap_check(struct ktcb *target, unsigned long virt,
884
                    unsigned long npages)
885
{
886
        struct capability *virtmem;
887
 
888
        /* Unmap check also uses identical struct as map check */
889
        struct sys_map_args args = {
890
                .task = target,
891
                .virt = virt,
892
                .npages = npages,
893
                .flags = MAP_UNMAP,
894
        };
895
 
896
        if (!(virtmem = cap_find(current, cap_match_mem,
897
                                 &args, CAP_TYPE_MAP_VIRTMEM)))
898
                return -ENOCAP;
899
 
900
        return 0;
901
}
902
 
903
/*
904
 * Limitation: We currently only check from sender's
905
 * perspective. This is because sender always targets a
906
 * real thread. Does sender have the right to do this ipc?
907
 */
908
int cap_ipc_check(l4id_t to, l4id_t from,
909
                  unsigned int flags, unsigned int ipc_type)
910
{
911
        struct ktcb *target;
912
        struct sys_ipc_args args;
913
 
914
        /* TODO: We don't check receivers, this works well for now. */
915
        if (ipc_type != IPC_SEND  && ipc_type != IPC_SENDRECV)
916
                return 0;
917
 
918
        /*
919
         * We're the sender, meaning we have
920
         * a real target
921
         */
922
        if (!(target = tcb_find(to)))
923
                return -ESRCH;
924
 
925
        /* Set up other args */
926
        args.xfer_type = ipc_flags_get_type(flags);
927
        args.ipc_type = ipc_type;
928
        args.task = target;
929
 
930
        if (!(cap_find(current, cap_match_ipc,
931
                       &args, CAP_TYPE_IPC)))
932
                return -ENOCAP;
933
 
934
        return 0;
935
}
936
 
937
int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs)
938
{
939
        struct sys_exregs_args args = {
940
                .exregs = exregs,
941
                .task = task,
942
        };
943
 
944
        /* We always search for current's caps */
945
        if (!(cap_find(current, cap_match_exregs,
946
                       &args, CAP_TYPE_EXREGS)))
947
                return -ENOCAP;
948
 
949
        return 0;
950
}
951
 
952
int cap_thread_check(struct ktcb *task,
953
                     unsigned int flags,
954
                     struct task_ids *ids)
955
{
956
        struct sys_tctrl_args args = {
957
                .task = task,
958
                .flags = flags,
959
                .ids = ids,
960
        };
961
 
962
        if (!(cap_find(current, cap_match_thread,
963
                       &args, CAP_TYPE_TCTRL)))
964
                return -ENOCAP;
965
 
966
        return 0;
967
}
968
 
969
 
970
int cap_irq_check(struct ktcb *registrant, unsigned int req,
971
                  unsigned int flags, l4id_t irq)
972
{
973
        struct sys_irqctrl_args args = {
974
                .registrant = registrant,
975
                .req = req,
976
                .flags = flags,
977
                .irq = irq,
978
        };
979
 
980
        /* Find the irq control capability of caller */
981
        if (!(cap_find(current, cap_match_irqctrl,
982
                       &args, CAP_TYPE_IRQCTRL)))
983
                return -ENOCAP;
984
 
985
        /*
986
         * If it is an irq registration, find the device
987
         * capability and check that it allows irq registration.
988
         */
989
        if (req == IRQ_CONTROL_REGISTER)
990
                if (!cap_find(current, cap_match_devmem,
991
                              &args, CAP_TYPE_MAP_PHYSMEM))
992
                        return -ENOCAP;
993
        return 0;
994
}
995
 
996
/*
997
 * This is just a wrapper call for l4_cache_control
998
 * system call sanity check
999
 */
1000
int cap_cache_check(unsigned long start, unsigned long end, unsigned int flags)
1001
{
1002
        struct capability *virtmem;
1003
        struct sys_cache_args args = {
1004
                .start = start,
1005
                .npages = __pfn(end) - __pfn(start),
1006
                .flags = flags,
1007
        };
1008
 
1009
        /*
1010
          * We just want to check if the virtual memory region
1011
          * concerned here has
1012
          *  appropriate permissions for cache calls
1013
          */
1014
        if (!(virtmem = cap_find(current, cap_match_cache,
1015
                                 &args, CAP_TYPE_MAP_VIRTMEM)))
1016
        return -ENOCAP;
1017
 
1018
        return 0;
1019
}
1020
 
1021
#else /* Meaning !CONFIG_CAPABILITIES */
1022
int cap_mutex_check(unsigned long mutex_address, int mutex_op)
1023
{
1024
        return 0;
1025
}
1026
 
1027
int cap_cap_check(struct ktcb *task, unsigned int req, unsigned int flags)
1028
{
1029
        return 0;
1030
}
1031
 
1032
int cap_ipc_check(l4id_t to, l4id_t from,
1033
                  unsigned int flags, unsigned int ipc_type)
1034
{
1035
        return 0;
1036
}
1037
 
1038
int cap_map_check(struct ktcb *task, unsigned long phys, unsigned long virt,
1039
                  unsigned long npages, unsigned int flags)
1040
{
1041
        return 0;
1042
}
1043
 
1044
int cap_unmap_check(struct ktcb *target, unsigned long virt,
1045
                    unsigned long npages)
1046
{
1047
        return 0;
1048
}
1049
 
1050
int cap_exregs_check(struct ktcb *task, struct exregs_data *exregs)
1051
{
1052
        return 0;
1053
}
1054
 
1055
int cap_thread_check(struct ktcb *task,
1056
                     unsigned int flags,
1057
                     struct task_ids *ids)
1058
{
1059
        return 0;
1060
}
1061
 
1062
int cap_irq_check(struct ktcb *registrant, unsigned int req,
1063
                  unsigned int flags, l4id_t irq)
1064
{
1065
        return 0;
1066
}
1067
 
1068
int cap_cache_check(unsigned long start, unsigned long end,
1069
                    unsigned int flags)
1070
{
1071
        return 0;
1072
}
1073
#endif /* End of !CONFIG_CAPABILITIES */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.