OSDN Git Service

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