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