Linux-libre 4.4.228-gnu
[librecmc/linux-libre.git] / security / selinux / ss / conditional.c
1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
2  *          Frank Mayer <mayerf@tresys.com>
3  *
4  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
5  *      This program is free software; you can redistribute it and/or modify
6  *      it under the terms of the GNU General Public License as published by
7  *      the Free Software Foundation, version 2.
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/string.h>
13 #include <linux/spinlock.h>
14 #include <linux/slab.h>
15
16 #include "security.h"
17 #include "conditional.h"
18 #include "services.h"
19
20 /*
21  * cond_evaluate_expr evaluates a conditional expr
22  * in reverse polish notation. It returns true (1), false (0),
23  * or undefined (-1). Undefined occurs when the expression
24  * exceeds the stack depth of COND_EXPR_MAXDEPTH.
25  */
26 static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
27 {
28
29         struct cond_expr *cur;
30         int s[COND_EXPR_MAXDEPTH];
31         int sp = -1;
32
33         for (cur = expr; cur; cur = cur->next) {
34                 switch (cur->expr_type) {
35                 case COND_BOOL:
36                         if (sp == (COND_EXPR_MAXDEPTH - 1))
37                                 return -1;
38                         sp++;
39                         s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
40                         break;
41                 case COND_NOT:
42                         if (sp < 0)
43                                 return -1;
44                         s[sp] = !s[sp];
45                         break;
46                 case COND_OR:
47                         if (sp < 1)
48                                 return -1;
49                         sp--;
50                         s[sp] |= s[sp + 1];
51                         break;
52                 case COND_AND:
53                         if (sp < 1)
54                                 return -1;
55                         sp--;
56                         s[sp] &= s[sp + 1];
57                         break;
58                 case COND_XOR:
59                         if (sp < 1)
60                                 return -1;
61                         sp--;
62                         s[sp] ^= s[sp + 1];
63                         break;
64                 case COND_EQ:
65                         if (sp < 1)
66                                 return -1;
67                         sp--;
68                         s[sp] = (s[sp] == s[sp + 1]);
69                         break;
70                 case COND_NEQ:
71                         if (sp < 1)
72                                 return -1;
73                         sp--;
74                         s[sp] = (s[sp] != s[sp + 1]);
75                         break;
76                 default:
77                         return -1;
78                 }
79         }
80         return s[0];
81 }
82
83 /*
84  * evaluate_cond_node evaluates the conditional stored in
85  * a struct cond_node and if the result is different than the
86  * current state of the node it sets the rules in the true/false
87  * list appropriately. If the result of the expression is undefined
88  * all of the rules are disabled for safety.
89  */
90 int evaluate_cond_node(struct policydb *p, struct cond_node *node)
91 {
92         int new_state;
93         struct cond_av_list *cur;
94
95         new_state = cond_evaluate_expr(p, node->expr);
96         if (new_state != node->cur_state) {
97                 node->cur_state = new_state;
98                 if (new_state == -1)
99                         printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
100                 /* turn the rules on or off */
101                 for (cur = node->true_list; cur; cur = cur->next) {
102                         if (new_state <= 0)
103                                 cur->node->key.specified &= ~AVTAB_ENABLED;
104                         else
105                                 cur->node->key.specified |= AVTAB_ENABLED;
106                 }
107
108                 for (cur = node->false_list; cur; cur = cur->next) {
109                         /* -1 or 1 */
110                         if (new_state)
111                                 cur->node->key.specified &= ~AVTAB_ENABLED;
112                         else
113                                 cur->node->key.specified |= AVTAB_ENABLED;
114                 }
115         }
116         return 0;
117 }
118
119 int cond_policydb_init(struct policydb *p)
120 {
121         int rc;
122
123         p->bool_val_to_struct = NULL;
124         p->cond_list = NULL;
125
126         rc = avtab_init(&p->te_cond_avtab);
127         if (rc)
128                 return rc;
129
130         return 0;
131 }
132
133 static void cond_av_list_destroy(struct cond_av_list *list)
134 {
135         struct cond_av_list *cur, *next;
136         for (cur = list; cur; cur = next) {
137                 next = cur->next;
138                 /* the avtab_ptr_t node is destroy by the avtab */
139                 kfree(cur);
140         }
141 }
142
143 static void cond_node_destroy(struct cond_node *node)
144 {
145         struct cond_expr *cur_expr, *next_expr;
146
147         for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) {
148                 next_expr = cur_expr->next;
149                 kfree(cur_expr);
150         }
151         cond_av_list_destroy(node->true_list);
152         cond_av_list_destroy(node->false_list);
153         kfree(node);
154 }
155
156 static void cond_list_destroy(struct cond_node *list)
157 {
158         struct cond_node *next, *cur;
159
160         if (list == NULL)
161                 return;
162
163         for (cur = list; cur; cur = next) {
164                 next = cur->next;
165                 cond_node_destroy(cur);
166         }
167 }
168
169 void cond_policydb_destroy(struct policydb *p)
170 {
171         kfree(p->bool_val_to_struct);
172         avtab_destroy(&p->te_cond_avtab);
173         cond_list_destroy(p->cond_list);
174 }
175
176 int cond_init_bool_indexes(struct policydb *p)
177 {
178         kfree(p->bool_val_to_struct);
179         p->bool_val_to_struct =
180                 kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum *), GFP_KERNEL);
181         if (!p->bool_val_to_struct)
182                 return -ENOMEM;
183         return 0;
184 }
185
186 int cond_destroy_bool(void *key, void *datum, void *p)
187 {
188         kfree(key);
189         kfree(datum);
190         return 0;
191 }
192
193 int cond_index_bool(void *key, void *datum, void *datap)
194 {
195         struct policydb *p;
196         struct cond_bool_datum *booldatum;
197         struct flex_array *fa;
198
199         booldatum = datum;
200         p = datap;
201
202         if (!booldatum->value || booldatum->value > p->p_bools.nprim)
203                 return -EINVAL;
204
205         fa = p->sym_val_to_name[SYM_BOOLS];
206         if (flex_array_put_ptr(fa, booldatum->value - 1, key,
207                                GFP_KERNEL | __GFP_ZERO))
208                 BUG();
209         p->bool_val_to_struct[booldatum->value - 1] = booldatum;
210
211         return 0;
212 }
213
214 static int bool_isvalid(struct cond_bool_datum *b)
215 {
216         if (!(b->state == 0 || b->state == 1))
217                 return 0;
218         return 1;
219 }
220
221 int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
222 {
223         char *key = NULL;
224         struct cond_bool_datum *booldatum;
225         __le32 buf[3];
226         u32 len;
227         int rc;
228
229         booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
230         if (!booldatum)
231                 return -ENOMEM;
232
233         rc = next_entry(buf, fp, sizeof buf);
234         if (rc)
235                 goto err;
236
237         booldatum->value = le32_to_cpu(buf[0]);
238         booldatum->state = le32_to_cpu(buf[1]);
239
240         rc = -EINVAL;
241         if (!bool_isvalid(booldatum))
242                 goto err;
243
244         len = le32_to_cpu(buf[2]);
245
246         rc = -ENOMEM;
247         key = kmalloc(len + 1, GFP_KERNEL);
248         if (!key)
249                 goto err;
250         rc = next_entry(key, fp, len);
251         if (rc)
252                 goto err;
253         key[len] = '\0';
254         rc = hashtab_insert(h, key, booldatum);
255         if (rc)
256                 goto err;
257
258         return 0;
259 err:
260         cond_destroy_bool(key, booldatum, NULL);
261         return rc;
262 }
263
264 struct cond_insertf_data {
265         struct policydb *p;
266         struct cond_av_list *other;
267         struct cond_av_list *head;
268         struct cond_av_list *tail;
269 };
270
271 static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr)
272 {
273         struct cond_insertf_data *data = ptr;
274         struct policydb *p = data->p;
275         struct cond_av_list *other = data->other, *list, *cur;
276         struct avtab_node *node_ptr;
277         u8 found;
278         int rc = -EINVAL;
279
280         /*
281          * For type rules we have to make certain there aren't any
282          * conflicting rules by searching the te_avtab and the
283          * cond_te_avtab.
284          */
285         if (k->specified & AVTAB_TYPE) {
286                 if (avtab_search(&p->te_avtab, k)) {
287                         printk(KERN_ERR "SELinux: type rule already exists outside of a conditional.\n");
288                         goto err;
289                 }
290                 /*
291                  * If we are reading the false list other will be a pointer to
292                  * the true list. We can have duplicate entries if there is only
293                  * 1 other entry and it is in our true list.
294                  *
295                  * If we are reading the true list (other == NULL) there shouldn't
296                  * be any other entries.
297                  */
298                 if (other) {
299                         node_ptr = avtab_search_node(&p->te_cond_avtab, k);
300                         if (node_ptr) {
301                                 if (avtab_search_node_next(node_ptr, k->specified)) {
302                                         printk(KERN_ERR "SELinux: too many conflicting type rules.\n");
303                                         goto err;
304                                 }
305                                 found = 0;
306                                 for (cur = other; cur; cur = cur->next) {
307                                         if (cur->node == node_ptr) {
308                                                 found = 1;
309                                                 break;
310                                         }
311                                 }
312                                 if (!found) {
313                                         printk(KERN_ERR "SELinux: conflicting type rules.\n");
314                                         goto err;
315                                 }
316                         }
317                 } else {
318                         if (avtab_search(&p->te_cond_avtab, k)) {
319                                 printk(KERN_ERR "SELinux: conflicting type rules when adding type rule for true.\n");
320                                 goto err;
321                         }
322                 }
323         }
324
325         node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
326         if (!node_ptr) {
327                 printk(KERN_ERR "SELinux: could not insert rule.\n");
328                 rc = -ENOMEM;
329                 goto err;
330         }
331
332         list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL);
333         if (!list) {
334                 rc = -ENOMEM;
335                 goto err;
336         }
337
338         list->node = node_ptr;
339         if (!data->head)
340                 data->head = list;
341         else
342                 data->tail->next = list;
343         data->tail = list;
344         return 0;
345
346 err:
347         cond_av_list_destroy(data->head);
348         data->head = NULL;
349         return rc;
350 }
351
352 static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
353 {
354         int i, rc;
355         __le32 buf[1];
356         u32 len;
357         struct cond_insertf_data data;
358
359         *ret_list = NULL;
360
361         len = 0;
362         rc = next_entry(buf, fp, sizeof(u32));
363         if (rc)
364                 return rc;
365
366         len = le32_to_cpu(buf[0]);
367         if (len == 0)
368                 return 0;
369
370         data.p = p;
371         data.other = other;
372         data.head = NULL;
373         data.tail = NULL;
374         for (i = 0; i < len; i++) {
375                 rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
376                                      &data);
377                 if (rc)
378                         return rc;
379         }
380
381         *ret_list = data.head;
382         return 0;
383 }
384
385 static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
386 {
387         if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
388                 printk(KERN_ERR "SELinux: conditional expressions uses unknown operator.\n");
389                 return 0;
390         }
391
392         if (expr->bool > p->p_bools.nprim) {
393                 printk(KERN_ERR "SELinux: conditional expressions uses unknown bool.\n");
394                 return 0;
395         }
396         return 1;
397 }
398
399 static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
400 {
401         __le32 buf[2];
402         u32 len, i;
403         int rc;
404         struct cond_expr *expr = NULL, *last = NULL;
405
406         rc = next_entry(buf, fp, sizeof(u32) * 2);
407         if (rc)
408                 goto err;
409
410         node->cur_state = le32_to_cpu(buf[0]);
411
412         /* expr */
413         len = le32_to_cpu(buf[1]);
414
415         for (i = 0; i < len; i++) {
416                 rc = next_entry(buf, fp, sizeof(u32) * 2);
417                 if (rc)
418                         goto err;
419
420                 rc = -ENOMEM;
421                 expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL);
422                 if (!expr)
423                         goto err;
424
425                 expr->expr_type = le32_to_cpu(buf[0]);
426                 expr->bool = le32_to_cpu(buf[1]);
427
428                 if (!expr_isvalid(p, expr)) {
429                         rc = -EINVAL;
430                         kfree(expr);
431                         goto err;
432                 }
433
434                 if (i == 0)
435                         node->expr = expr;
436                 else
437                         last->next = expr;
438                 last = expr;
439         }
440
441         rc = cond_read_av_list(p, fp, &node->true_list, NULL);
442         if (rc)
443                 goto err;
444         rc = cond_read_av_list(p, fp, &node->false_list, node->true_list);
445         if (rc)
446                 goto err;
447         return 0;
448 err:
449         cond_node_destroy(node);
450         return rc;
451 }
452
453 int cond_read_list(struct policydb *p, void *fp)
454 {
455         struct cond_node *node, *last = NULL;
456         __le32 buf[1];
457         u32 i, len;
458         int rc;
459
460         rc = next_entry(buf, fp, sizeof buf);
461         if (rc)
462                 return rc;
463
464         len = le32_to_cpu(buf[0]);
465
466         rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
467         if (rc)
468                 goto err;
469
470         for (i = 0; i < len; i++) {
471                 rc = -ENOMEM;
472                 node = kzalloc(sizeof(struct cond_node), GFP_KERNEL);
473                 if (!node)
474                         goto err;
475
476                 rc = cond_read_node(p, node, fp);
477                 if (rc)
478                         goto err;
479
480                 if (i == 0)
481                         p->cond_list = node;
482                 else
483                         last->next = node;
484                 last = node;
485         }
486         return 0;
487 err:
488         cond_list_destroy(p->cond_list);
489         p->cond_list = NULL;
490         return rc;
491 }
492
493 int cond_write_bool(void *vkey, void *datum, void *ptr)
494 {
495         char *key = vkey;
496         struct cond_bool_datum *booldatum = datum;
497         struct policy_data *pd = ptr;
498         void *fp = pd->fp;
499         __le32 buf[3];
500         u32 len;
501         int rc;
502
503         len = strlen(key);
504         buf[0] = cpu_to_le32(booldatum->value);
505         buf[1] = cpu_to_le32(booldatum->state);
506         buf[2] = cpu_to_le32(len);
507         rc = put_entry(buf, sizeof(u32), 3, fp);
508         if (rc)
509                 return rc;
510         rc = put_entry(key, 1, len, fp);
511         if (rc)
512                 return rc;
513         return 0;
514 }
515
516 /*
517  * cond_write_cond_av_list doesn't write out the av_list nodes.
518  * Instead it writes out the key/value pairs from the avtab. This
519  * is necessary because there is no way to uniquely identifying rules
520  * in the avtab so it is not possible to associate individual rules
521  * in the avtab with a conditional without saving them as part of
522  * the conditional. This means that the avtab with the conditional
523  * rules will not be saved but will be rebuilt on policy load.
524  */
525 static int cond_write_av_list(struct policydb *p,
526                               struct cond_av_list *list, struct policy_file *fp)
527 {
528         __le32 buf[1];
529         struct cond_av_list *cur_list;
530         u32 len;
531         int rc;
532
533         len = 0;
534         for (cur_list = list; cur_list != NULL; cur_list = cur_list->next)
535                 len++;
536
537         buf[0] = cpu_to_le32(len);
538         rc = put_entry(buf, sizeof(u32), 1, fp);
539         if (rc)
540                 return rc;
541
542         if (len == 0)
543                 return 0;
544
545         for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
546                 rc = avtab_write_item(p, cur_list->node, fp);
547                 if (rc)
548                         return rc;
549         }
550
551         return 0;
552 }
553
554 static int cond_write_node(struct policydb *p, struct cond_node *node,
555                     struct policy_file *fp)
556 {
557         struct cond_expr *cur_expr;
558         __le32 buf[2];
559         int rc;
560         u32 len = 0;
561
562         buf[0] = cpu_to_le32(node->cur_state);
563         rc = put_entry(buf, sizeof(u32), 1, fp);
564         if (rc)
565                 return rc;
566
567         for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
568                 len++;
569
570         buf[0] = cpu_to_le32(len);
571         rc = put_entry(buf, sizeof(u32), 1, fp);
572         if (rc)
573                 return rc;
574
575         for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
576                 buf[0] = cpu_to_le32(cur_expr->expr_type);
577                 buf[1] = cpu_to_le32(cur_expr->bool);
578                 rc = put_entry(buf, sizeof(u32), 2, fp);
579                 if (rc)
580                         return rc;
581         }
582
583         rc = cond_write_av_list(p, node->true_list, fp);
584         if (rc)
585                 return rc;
586         rc = cond_write_av_list(p, node->false_list, fp);
587         if (rc)
588                 return rc;
589
590         return 0;
591 }
592
593 int cond_write_list(struct policydb *p, struct cond_node *list, void *fp)
594 {
595         struct cond_node *cur;
596         u32 len;
597         __le32 buf[1];
598         int rc;
599
600         len = 0;
601         for (cur = list; cur != NULL; cur = cur->next)
602                 len++;
603         buf[0] = cpu_to_le32(len);
604         rc = put_entry(buf, sizeof(u32), 1, fp);
605         if (rc)
606                 return rc;
607
608         for (cur = list; cur != NULL; cur = cur->next) {
609                 rc = cond_write_node(p, cur, fp);
610                 if (rc)
611                         return rc;
612         }
613
614         return 0;
615 }
616
617 void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key,
618                 struct extended_perms_decision *xpermd)
619 {
620         struct avtab_node *node;
621
622         if (!ctab || !key || !xpermd)
623                 return;
624
625         for (node = avtab_search_node(ctab, key); node;
626                         node = avtab_search_node_next(node, key->specified)) {
627                 if (node->key.specified & AVTAB_ENABLED)
628                         services_compute_xperms_decision(xpermd, node);
629         }
630         return;
631
632 }
633 /* Determine whether additional permissions are granted by the conditional
634  * av table, and if so, add them to the result
635  */
636 void cond_compute_av(struct avtab *ctab, struct avtab_key *key,
637                 struct av_decision *avd, struct extended_perms *xperms)
638 {
639         struct avtab_node *node;
640
641         if (!ctab || !key || !avd)
642                 return;
643
644         for (node = avtab_search_node(ctab, key); node;
645                                 node = avtab_search_node_next(node, key->specified)) {
646                 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==
647                     (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
648                         avd->allowed |= node->datum.u.data;
649                 if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) ==
650                     (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
651                         /* Since a '0' in an auditdeny mask represents a
652                          * permission we do NOT want to audit (dontaudit), we use
653                          * the '&' operand to ensure that all '0's in the mask
654                          * are retained (much unlike the allow and auditallow cases).
655                          */
656                         avd->auditdeny &= node->datum.u.data;
657                 if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
658                     (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
659                         avd->auditallow |= node->datum.u.data;
660                 if (xperms && (node->key.specified & AVTAB_ENABLED) &&
661                                 (node->key.specified & AVTAB_XPERMS))
662                         services_compute_xperms_drivers(xperms, node);
663         }
664         return;
665 }