1 /*
2  * Implementation of the security services.
3  *
4  * Authors : Stephen Smalley, <sds@epoch.ncsc.mil>
5  *           James Morris <jmorris@redhat.com>
6  *
7  * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
8  *
9  *    Support for enhanced MLS infrastructure.
10  *
11  * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
12  *
13  *     Added conditional policy language extensions
14  *
15  * Updated: Hewlett-Packard <paul.moore@hp.com>
16  *
17  *      Added support for the policy capability bitmap
18  *
19  * Updated: Chad Sellers <csellers@tresys.com>
20  *
21  *  Added validation of kernel classes and permissions
22  *
23  * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
24  *
25  *  Added support for bounds domain and audit messaged on masked permissions
26  *
27  * Copyright (C) 2008, 2009 NEC Corporation
28  * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
29  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
30  * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
31  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
32  *    This program is free software; you can redistribute it and/or modify
33  *      it under the terms of the GNU General Public License as published by
34  *    the Free Software Foundation, version 2.
35  */
36 
37 /* Ported to Xen 3.0, George Coker, <gscoker@alpha.ncsc.mil> */
38 
39 #include <xen/lib.h>
40 #include <xen/xmalloc.h>
41 #include <xen/string.h>
42 #include <xen/spinlock.h>
43 #include <xen/rwlock.h>
44 #include <xen/errno.h>
45 #include "flask.h"
46 #include "avc.h"
47 #include "avc_ss.h"
48 #include "security.h"
49 #include "context.h"
50 #include "policydb.h"
51 #include "sidtab.h"
52 #include "services.h"
53 #include "conditional.h"
54 #include "mls.h"
55 
56 unsigned int policydb_loaded_version;
57 
58 static DEFINE_RWLOCK(policy_rwlock);
59 #define POLICY_RDLOCK read_lock(&policy_rwlock)
60 #define POLICY_WRLOCK write_lock(&policy_rwlock)
61 #define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
62 #define POLICY_WRUNLOCK write_unlock(&policy_rwlock)
63 
64 static DEFINE_SPINLOCK(load_sem);
65 #define LOAD_LOCK spin_lock(&load_sem)
66 #define LOAD_UNLOCK spin_unlock(&load_sem)
67 
68 static struct sidtab sidtab;
69 struct policydb policydb;
70 int ss_initialized = 0;
71 
72 /*
73  * The largest sequence number that has been used when
74  * providing an access decision to the access vector cache.
75  * The sequence number only changes when a policy change
76  * occurs.
77  */
78 static u32 latest_granting = 0;
79 
80 /* Forward declaration. */
81 static int context_struct_to_string(struct context *context, char **scontext,
82                                                             u32 *scontext_len);
83 
84 static int context_struct_compute_av(struct context *scontext,
85 				     struct context *tcontext,
86 				     u16 tclass,
87 				     u32 requested,
88 				     struct av_decision *avd);
89 
90 /*
91  * Return the boolean value of a constraint expression
92  * when it is applied to the specified source and target
93  * security contexts.
94  *
95  * xcontext is a special beast...  It is used by the validatetrans rules
96  * only.  For these rules, scontext is the context before the transition,
97  * tcontext is the context after the transition, and xcontext is the context
98  * of the process performing the transition.  All other callers of
99  * constraint_expr_eval should pass in NULL for xcontext.
100  */
constraint_expr_eval(struct context * scontext,struct context * tcontext,struct context * xcontext,struct constraint_expr * cexpr)101 static int constraint_expr_eval(struct context *scontext,
102                             struct context *tcontext, struct context *xcontext,
103                                                 struct constraint_expr *cexpr)
104 {
105     u32 val1, val2;
106     struct context *c;
107     struct role_datum *r1, *r2;
108     struct mls_level *l1, *l2;
109     struct constraint_expr *e;
110     int s[CEXPR_MAXDEPTH];
111     int sp = -1;
112 
113     for ( e = cexpr; e; e = e->next )
114     {
115         switch ( e->expr_type )
116         {
117             case CEXPR_NOT:
118                 BUG_ON(sp < 0);
119                 s[sp] = !s[sp];
120             break;
121             case CEXPR_AND:
122                 BUG_ON(sp < 1);
123                 sp--;
124                 s[sp] &= s[sp+1];
125             break;
126             case CEXPR_OR:
127                 BUG_ON(sp < 1);
128                 sp--;
129                 s[sp] |= s[sp+1];
130             break;
131             case CEXPR_ATTR:
132                 if ( sp == (CEXPR_MAXDEPTH-1) )
133                     return 0;
134             switch ( e->attr )
135             {
136                 case CEXPR_USER:
137                     val1 = scontext->user;
138                     val2 = tcontext->user;
139                     break;
140                 case CEXPR_TYPE:
141                     val1 = scontext->type;
142                     val2 = tcontext->type;
143                     break;
144                 case CEXPR_ROLE:
145                     val1 = scontext->role;
146                     val2 = tcontext->role;
147                     r1 = policydb.role_val_to_struct[val1 - 1];
148                     r2 = policydb.role_val_to_struct[val2 - 1];
149                 switch ( e->op )
150                 {
151                     case CEXPR_DOM:
152                         s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1);
153                     continue;
154                     case CEXPR_DOMBY:
155                         s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1);
156                     continue;
157                     case CEXPR_INCOMP:
158                         s[++sp] = ( !ebitmap_get_bit(&r1->dominates,
159                                          val2 - 1) &&
160                                 !ebitmap_get_bit(&r2->dominates,
161                                          val1 - 1) );
162                     continue;
163                     default:
164                     break;
165                 }
166                 break;
167                 case CEXPR_L1L2:
168                     l1 = &(scontext->range.level[0]);
169                     l2 = &(tcontext->range.level[0]);
170                     goto mls_ops;
171                 case CEXPR_L1H2:
172                     l1 = &(scontext->range.level[0]);
173                     l2 = &(tcontext->range.level[1]);
174                     goto mls_ops;
175                 case CEXPR_H1L2:
176                     l1 = &(scontext->range.level[1]);
177                     l2 = &(tcontext->range.level[0]);
178                     goto mls_ops;
179                 case CEXPR_H1H2:
180                     l1 = &(scontext->range.level[1]);
181                     l2 = &(tcontext->range.level[1]);
182                     goto mls_ops;
183                 case CEXPR_L1H1:
184                     l1 = &(scontext->range.level[0]);
185                     l2 = &(scontext->range.level[1]);
186                     goto mls_ops;
187                 case CEXPR_L2H2:
188                     l1 = &(tcontext->range.level[0]);
189                     l2 = &(tcontext->range.level[1]);
190                     goto mls_ops;
191 mls_ops:
192             switch ( e->op )
193             {
194                 case CEXPR_EQ:
195                     s[++sp] = mls_level_eq(l1, l2);
196                 continue;
197                 case CEXPR_NEQ:
198                     s[++sp] = !mls_level_eq(l1, l2);
199                 continue;
200                 case CEXPR_DOM:
201                     s[++sp] = mls_level_dom(l1, l2);
202                 continue;
203                 case CEXPR_DOMBY:
204                     s[++sp] = mls_level_dom(l2, l1);
205                 continue;
206                 case CEXPR_INCOMP:
207                     s[++sp] = mls_level_incomp(l2, l1);
208                 continue;
209                 default:
210                     BUG();
211                     return 0;
212             }
213             break;
214             default:
215                 BUG();
216                 return 0;
217             }
218 
219             switch ( e->op )
220             {
221                 case CEXPR_EQ:
222                     s[++sp] = (val1 == val2);
223                 break;
224                 case CEXPR_NEQ:
225                     s[++sp] = (val1 != val2);
226                 break;
227                 default:
228                     BUG();
229                     return 0;
230             }
231             break;
232             case CEXPR_NAMES:
233                 if ( sp == (CEXPR_MAXDEPTH-1) )
234                     return 0;
235                 c = scontext;
236                 if ( e->attr & CEXPR_TARGET )
237                     c = tcontext;
238                 else if ( e->attr & CEXPR_XTARGET )
239                 {
240                     c = xcontext;
241                     if ( !c )
242                     {
243                         BUG();
244                         return 0;
245                     }
246                 }
247                 if ( e->attr & CEXPR_USER )
248                     val1 = c->user;
249                 else if ( e->attr & CEXPR_ROLE )
250                     val1 = c->role;
251                 else if ( e->attr & CEXPR_TYPE )
252                     val1 = c->type;
253                 else
254                 {
255                     BUG();
256                     return 0;
257                 }
258 
259             switch ( e->op )
260             {
261                 case CEXPR_EQ:
262                     s[++sp] = ebitmap_get_bit(&e->names, val1 - 1);
263                 break;
264                 case CEXPR_NEQ:
265                     s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1);
266                 break;
267                 default:
268                     BUG();
269                     return 0;
270             }
271             break;
272             default:
273                 BUG();
274                 return 0;
275         }
276     }
277 
278     BUG_ON(sp != 0);
279     return s[0];
280 }
281 
282 /*
283  * security_dump_masked_av - dumps masked permissions during
284  * security_compute_av due to RBAC, MLS/Constraint and Type bounds.
285  */
dump_masked_av_helper(void * k,void * d,void * args)286 static int dump_masked_av_helper(void *k, void *d, void *args)
287 {
288     struct perm_datum *pdatum = d;
289     char **permission_names = args;
290 
291     BUG_ON(pdatum->value < 1 || pdatum->value > 32);
292 
293     permission_names[pdatum->value - 1] = (char *)k;
294 
295     return 0;
296 }
297 
security_dump_masked_av(struct context * scontext,struct context * tcontext,u16 tclass,u32 permissions,const char * reason)298 static void security_dump_masked_av(struct context *scontext,
299 				    struct context *tcontext,
300 				    u16 tclass,
301 				    u32 permissions,
302 				    const char *reason)
303 {
304     struct common_datum *common_dat;
305     struct class_datum *tclass_dat;
306     char *tclass_name;
307     char *scontext_name = NULL;
308     char *tcontext_name = NULL;
309     char *permission_names[32];
310     int index;
311     u32 length;
312     unsigned char need_comma = 0;
313 
314     if ( !permissions )
315         return;
316 
317     tclass_name = policydb.p_class_val_to_name[tclass - 1];
318     tclass_dat = policydb.class_val_to_struct[tclass - 1];
319     common_dat = tclass_dat->comdatum;
320 
321     /* init permission_names */
322     if ( common_dat &&
323          hashtab_map(common_dat->permissions.table,
324                      dump_masked_av_helper, permission_names) < 0 )
325         goto out;
326 
327     if ( hashtab_map(tclass_dat->permissions.table,
328                     dump_masked_av_helper, permission_names) < 0 )
329         goto out;
330 
331 	/* get scontext/tcontext in text form */
332     if ( context_struct_to_string(scontext,
333                                  &scontext_name, &length) < 0 )
334         goto out;
335 
336     if ( context_struct_to_string(tcontext,
337                                  &tcontext_name, &length) < 0 )
338         goto out;
339 
340     printk("Flask: op=security_compute_av reason=%s "
341            "scontext=%s tcontext=%s tclass=%s perms=",
342            reason, scontext_name, tcontext_name, tclass_name);
343 
344     for ( index = 0; index < 32; index++ )
345     {
346         u32 mask = (1 << index);
347 
348         if ( (mask & permissions) == 0 )
349             continue;
350 
351         printk("%s%s",
352                need_comma ? "," : "",
353                permission_names[index]
354                ? permission_names[index] : "????");
355         need_comma = 1;
356     }
357     printk("\n");
358 out:
359     /* release scontext/tcontext */
360     xfree(tcontext_name);
361     xfree(scontext_name);
362 
363     return;
364 }
365 
366 /*
367  * security_boundary_permission - drops violated permissions
368  * on boundary constraint.
369  */
type_attribute_bounds_av(struct context * scontext,struct context * tcontext,u16 tclass,u32 requested,struct av_decision * avd)370 static void type_attribute_bounds_av(struct context *scontext,
371                                      struct context *tcontext,
372                                      u16 tclass,
373                                      u32 requested,
374                                      struct av_decision *avd)
375 {
376     struct context lo_scontext;
377     struct context lo_tcontext;
378     struct av_decision lo_avd;
379     struct type_datum *source
380         = policydb.type_val_to_struct[scontext->type - 1];
381     struct type_datum *target
382         = policydb.type_val_to_struct[tcontext->type - 1];
383     u32 masked = 0;
384 
385     if ( source->bounds )
386     {
387         memset(&lo_avd, 0, sizeof(lo_avd));
388 
389         memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
390         lo_scontext.type = source->bounds;
391 
392         context_struct_compute_av(&lo_scontext,
393                                   tcontext,
394                                   tclass,
395                                   requested,
396                                   &lo_avd);
397         if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
398             return;		/* no masked permission */
399         masked = ~lo_avd.allowed & avd->allowed;
400     }
401 
402     if ( target->bounds )
403     {
404         memset(&lo_avd, 0, sizeof(lo_avd));
405 
406         memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
407         lo_tcontext.type = target->bounds;
408 
409         context_struct_compute_av(scontext,
410                                   &lo_tcontext,
411                                   tclass,
412                                   requested,
413                                   &lo_avd);
414         if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
415             return;		/* no masked permission */
416         masked = ~lo_avd.allowed & avd->allowed;
417     }
418 
419     if ( source->bounds && target->bounds )
420     {
421         memset(&lo_avd, 0, sizeof(lo_avd));
422         /*
423          * lo_scontext and lo_tcontext are already
424          * set up.
425          */
426 
427         context_struct_compute_av(&lo_scontext,
428                                   &lo_tcontext,
429                                   tclass,
430                                   requested,
431                                   &lo_avd);
432         if ( (lo_avd.allowed & avd->allowed) == avd->allowed )
433             return;		/* no masked permission */
434         masked = ~lo_avd.allowed & avd->allowed;
435     }
436 
437     if ( masked )
438     {
439         /* mask violated permissions */
440         avd->allowed &= ~masked;
441 
442         /* audit masked permissions */
443         security_dump_masked_av(scontext, tcontext,
444                                 tclass, masked, "bounds");
445     }
446 }
447 
448 /*
449  * Compute access vectors based on a context structure pair for
450  * the permissions in a particular class.
451  */
context_struct_compute_av(struct context * scontext,struct context * tcontext,u16 tclass,u32 requested,struct av_decision * avd)452 static int context_struct_compute_av(struct context *scontext,
453 				     struct context *tcontext,
454 				     u16 tclass,
455 				     u32 requested,
456 				     struct av_decision *avd)
457 {
458     struct constraint_node *constraint;
459     struct role_allow *ra;
460     struct avtab_key avkey;
461     struct avtab_node *node;
462     struct class_datum *tclass_datum;
463     struct ebitmap *sattr, *tattr;
464     struct ebitmap_node *snode, *tnode;
465     unsigned int i, j;
466 
467     /*
468      * Initialize the access vectors to the default values.
469      */
470     avd->allowed = 0;
471     avd->auditallow = 0;
472     avd->auditdeny = 0xffffffff;
473     avd->seqno = latest_granting;
474     avd->flags = 0;
475 
476     /*
477      * We do not presently support policydb.handle_unknown == allow in Xen.
478      */
479     if ( !tclass || tclass > policydb.p_classes.nprim )
480         return -EINVAL;
481 
482     tclass_datum = policydb.class_val_to_struct[tclass - 1];
483 
484     /*
485      * If a specific type enforcement rule was defined for
486      * this permission check, then use it.
487      */
488     avkey.target_class = tclass;
489     avkey.specified = AVTAB_AV;
490     sattr = &policydb.type_attr_map[scontext->type - 1];
491     tattr = &policydb.type_attr_map[tcontext->type - 1];
492     ebitmap_for_each_positive_bit(sattr, snode, i)
493     {
494         ebitmap_for_each_positive_bit(tattr, tnode, j)
495         {
496             avkey.source_type = i + 1;
497             avkey.target_type = j + 1;
498             for ( node = avtab_search_node(&policydb.te_avtab, &avkey);
499                  node != NULL;
500                  node = avtab_search_node_next(node, avkey.specified) )
501             {
502                 if ( node->key.specified == AVTAB_ALLOWED )
503                     avd->allowed |= node->datum.data;
504                 else if ( node->key.specified == AVTAB_AUDITALLOW )
505                     avd->auditallow |= node->datum.data;
506                 else if ( node->key.specified == AVTAB_AUDITDENY )
507                     avd->auditdeny &= node->datum.data;
508             }
509 
510             /* Check conditional av table for additional permissions */
511             cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
512 
513         }
514     }
515 
516     /*
517      * Remove any permissions prohibited by a constraint (this includes
518      * the MLS policy).
519      */
520     constraint = tclass_datum->constraints;
521     while ( constraint )
522     {
523         if ( (constraint->permissions & (avd->allowed) ) &&
524             !constraint_expr_eval(scontext, tcontext, NULL, constraint->expr))
525         {
526 	    avd->allowed &= ~(constraint->permissions);
527         }
528         constraint = constraint->next;
529     }
530 
531     /*
532      * If checking process transition permission and the
533      * role is changing, then check the (current_role, new_role)
534      * pair.
535      */
536     if ( tclass == SECCLASS_DOMAIN &&
537          (avd->allowed & DOMAIN__TRANSITION) &&
538          scontext->role != tcontext->role )
539     {
540         for ( ra = policydb.role_allow; ra; ra = ra->next )
541         {
542             if ( scontext->role == ra->role && tcontext->role == ra->new_role )
543                 break;
544         }
545         if (!ra)
546             avd->allowed &= ~DOMAIN__TRANSITION;
547     }
548 
549     /*
550      * If the given source and target types have boundary
551      * constraint, lazy checks have to mask any violated
552      * permission and notice it to userspace via audit.
553      */
554     type_attribute_bounds_av(scontext, tcontext,
555 			     tclass, requested, avd);
556     return 0;
557 }
558 
security_validtrans_handle_fail(struct context * ocontext,struct context * ncontext,struct context * tcontext,u16 tclass)559 static int security_validtrans_handle_fail(struct context *ocontext,
560                 struct context *ncontext, struct context *tcontext, u16 tclass)
561 {
562     char *o = NULL, *n = NULL, *t = NULL;
563     u32 olen, nlen, tlen;
564 
565     if ( context_struct_to_string(ocontext, &o, &olen) < 0 )
566         goto out;
567     if ( context_struct_to_string(ncontext, &n, &nlen) < 0 )
568         goto out;
569     if ( context_struct_to_string(tcontext, &t, &tlen) < 0 )
570         goto out;
571     printk("security_validate_transition:  denied for"
572               " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
573               o, n, t, policydb.p_class_val_to_name[tclass-1]);
574 out:
575     xfree(o);
576     xfree(n);
577     xfree(t);
578 
579     if ( !flask_enforcing )
580         return 0;
581     return -EPERM;
582 }
583 
security_validate_transition(u32 oldsid,u32 newsid,u32 tasksid,u16 tclass)584 int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
585                                  u16 tclass)
586 {
587     struct context *ocontext;
588     struct context *ncontext;
589     struct context *tcontext;
590     struct class_datum *tclass_datum;
591     struct constraint_node *constraint;
592     int rc = 0;
593 
594     if ( !ss_initialized )
595         return 0;
596 
597     POLICY_RDLOCK;
598 
599     if ( !tclass || tclass > policydb.p_classes.nprim )
600     {
601         printk(KERN_ERR "security_validate_transition: "
602                                             "unrecognized class %d\n", tclass);
603         rc = -EINVAL;
604         goto out;
605     }
606     tclass_datum = policydb.class_val_to_struct[tclass - 1];
607 
608     ocontext = sidtab_search(&sidtab, oldsid);
609     if ( !ocontext )
610     {
611         printk(KERN_ERR "security_validate_transition: "
612                " unrecognized SID %d\n", oldsid);
613         rc = -EINVAL;
614         goto out;
615     }
616 
617     ncontext = sidtab_search(&sidtab, newsid);
618     if ( !ncontext )
619     {
620         printk(KERN_ERR "security_validate_transition: "
621                " unrecognized SID %d\n", newsid);
622         rc = -EINVAL;
623         goto out;
624     }
625 
626     tcontext = sidtab_search(&sidtab, tasksid);
627     if ( !tcontext )
628     {
629         printk(KERN_ERR "security_validate_transition: "
630                " unrecognized SID %d\n", tasksid);
631         rc = -EINVAL;
632         goto out;
633     }
634 
635     constraint = tclass_datum->validatetrans;
636     while ( constraint )
637     {
638         if ( !constraint_expr_eval(ocontext, ncontext, tcontext,
639                                                             constraint->expr) )
640         {
641             rc = security_validtrans_handle_fail(ocontext, ncontext,
642                                                  tcontext, tclass);
643             goto out;
644         }
645         constraint = constraint->next;
646     }
647 
648 out:
649     POLICY_RDUNLOCK;
650     return rc;
651 }
652 
653 /**
654  * security_compute_av - Compute access vector decisions.
655  * @ssid: source security identifier
656  * @tsid: target security identifier
657  * @tclass: target security class
658  * @requested: requested permissions
659  * @avd: access vector decisions
660  *
661  * Compute a set of access vector decisions based on the
662  * SID pair (@ssid, @tsid) for the permissions in @tclass.
663  * Return -%EINVAL if any of the parameters are invalid or %0
664  * if the access vector decisions were computed successfully.
665  */
security_compute_av(u32 ssid,u32 tsid,u16 tclass,u32 requested,struct av_decision * avd)666 int security_compute_av(u32 ssid, u32 tsid, u16 tclass, u32 requested,
667                         struct av_decision *avd)
668 {
669     struct context *scontext = NULL, *tcontext = NULL;
670     int rc = 0;
671 
672     if ( !ss_initialized )
673     {
674         avd->allowed = 0xffffffff;
675         avd->auditallow = 0;
676         avd->auditdeny = 0xffffffff;
677         avd->seqno = latest_granting;
678         return 0;
679     }
680 
681     POLICY_RDLOCK;
682 
683     scontext = sidtab_search(&sidtab, ssid);
684     if ( !scontext )
685     {
686         printk("security_compute_av:  unrecognized SID %d\n", ssid);
687         rc = -EINVAL;
688         goto out;
689     }
690     tcontext = sidtab_search(&sidtab, tsid);
691     if ( !tcontext )
692     {
693         printk("security_compute_av:  unrecognized SID %d\n", tsid);
694         rc = -EINVAL;
695         goto out;
696     }
697 
698     rc = context_struct_compute_av(scontext, tcontext, tclass, requested, avd);
699 
700     /* permissive domain? */
701     if ( ebitmap_get_bit(&policydb.permissive_map, scontext->type) )
702         avd->flags |= AVD_FLAGS_PERMISSIVE;
703 out:
704     POLICY_RDUNLOCK;
705     return rc;
706 }
707 
708 /*
709  * Write the security context string representation of
710  * the context structure `context' into a dynamically
711  * allocated string of the correct size.  Set `*scontext'
712  * to point to this string and set `*scontext_len' to
713  * the length of the string.
714  */
context_struct_to_string(struct context * context,char ** scontext,u32 * scontext_len)715 static int context_struct_to_string(struct context *context, char **scontext, u32 *scontext_len)
716 {
717     char *scontextp;
718 
719     *scontext = NULL;
720     *scontext_len = 0;
721 
722     /* Compute the size of the context. */
723     *scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
724     *scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
725     *scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
726     *scontext_len += mls_compute_context_len(context);
727 
728     /* Allocate space for the context; caller must free this space. */
729     scontextp = xmalloc_array(char, *scontext_len);
730     if ( !scontextp )
731         return -ENOMEM;
732 
733     *scontext = scontextp;
734 
735     /*
736      * Copy the user name, role name and type name into the context.
737      */
738     snprintf(scontextp, *scontext_len, "%s:%s:%s",
739         policydb.p_user_val_to_name[context->user - 1],
740         policydb.p_role_val_to_name[context->role - 1],
741         policydb.p_type_val_to_name[context->type - 1]);
742     scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
743                  1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
744                  1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
745 
746     mls_sid_to_context(context, &scontextp);
747 
748     *scontextp = 0;
749 
750     return 0;
751 }
752 
753 #include "initial_sid_to_string.h"
754 
755 /**
756  * security_sid_to_context - Obtain a context for a given SID.
757  * @sid: security identifier, SID
758  * @scontext: security context
759  * @scontext_len: length in bytes
760  *
761  * Write the string representation of the context associated with @sid
762  * into a dynamically allocated string of the correct size.  Set @scontext
763  * to point to this string and set @scontext_len to the length of the string.
764  */
security_sid_to_context(u32 sid,char ** scontext,u32 * scontext_len)765 int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
766 {
767     struct context *context;
768     int rc = 0;
769 
770     if ( !ss_initialized )
771     {
772         if ( sid <= SECINITSID_NUM )
773         {
774             char *scontextp;
775 
776             *scontext_len = strlen(initial_sid_to_string[sid]) + 1;
777             scontextp = xmalloc_array(char, *scontext_len);
778             if ( !scontextp )
779                 return -ENOMEM;
780             strlcpy(scontextp, initial_sid_to_string[sid], *scontext_len);
781             *scontext = scontextp;
782             goto out;
783         }
784         printk(KERN_ERR "security_sid_to_context:  called before initial "
785                "load_policy on unknown SID %d\n", sid);
786         rc = -EINVAL;
787         goto out;
788     }
789     POLICY_RDLOCK;
790     context = sidtab_search(&sidtab, sid);
791     if ( !context )
792     {
793         printk(KERN_ERR "security_sid_to_context:  unrecognized SID "
794                "%d\n", sid);
795         rc = -EINVAL;
796         goto out_unlock;
797     }
798     rc = context_struct_to_string(context, scontext, scontext_len);
799 out_unlock:
800     POLICY_RDUNLOCK;
801 out:
802     return rc;
803 
804 }
805 
806 /**
807  * security_context_to_sid - Obtain a SID for a given security context.
808  * @scontext: security context
809  * @scontext_len: length in bytes
810  * @sid: security identifier, SID
811  *
812  * Obtains a SID associated with the security context that
813  * has the string representation specified by @scontext.
814  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
815  * memory is available, or 0 on success.
816  */
security_context_to_sid(char * scontext,u32 scontext_len,u32 * sid)817 int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
818 {
819     char *scontext2;
820     struct context context;
821     struct role_datum *role;
822     struct type_datum *typdatum;
823     struct user_datum *usrdatum;
824     char *scontextp, *p, oldc;
825     int rc = 0;
826 
827     if ( !ss_initialized )
828     {
829         int i;
830 
831         for ( i = 1; i < SECINITSID_NUM; i++ )
832         {
833             if ( !strcmp(initial_sid_to_string[i], scontext) )
834             {
835                 *sid = i;
836                 goto out;
837             }
838         }
839         *sid = SECINITSID_XEN;
840         goto out;
841     }
842     *sid = SECSID_NULL;
843 
844     /* Copy the string so that we can modify the copy as we parse it.
845        The string should already by null terminated, but we append a
846        null suffix to the copy to avoid problems with the existing
847        attr package, which doesn't view the null terminator as part
848        of the attribute value. */
849     scontext2 = xmalloc_array(char, scontext_len+1);
850     if ( !scontext2 )
851     {
852         rc = -ENOMEM;
853         goto out;
854     }
855     memcpy(scontext2, scontext, scontext_len);
856     scontext2[scontext_len] = 0;
857 
858     context_init(&context);
859     *sid = SECSID_NULL;
860 
861     POLICY_RDLOCK;
862 
863     /* Parse the security context. */
864 
865     rc = -EINVAL;
866     scontextp = (char *) scontext2;
867 
868     /* Extract the user. */
869     p = scontextp;
870     while ( *p && *p != ':' )
871         p++;
872 
873     if (*p == 0)
874         goto out_unlock;
875 
876     *p++ = 0;
877 
878     usrdatum = hashtab_search(policydb.p_users.table, scontextp);
879     if ( !usrdatum )
880         goto out_unlock;
881 
882     context.user = usrdatum->value;
883 
884     /* Extract role. */
885     scontextp = p;
886     while ( *p && *p != ':' )
887         p++;
888 
889     if ( *p == 0 )
890         goto out_unlock;
891 
892     *p++ = 0;
893 
894     role = hashtab_search(policydb.p_roles.table, scontextp);
895     if ( !role )
896         goto out_unlock;
897     context.role = role->value;
898 
899     /* Extract type. */
900     scontextp = p;
901     while ( *p && *p != ':' )
902         p++;
903     oldc = *p;
904     *p++ = 0;
905 
906     typdatum = hashtab_search(policydb.p_types.table, scontextp);
907     if ( !typdatum || typdatum->attribute )
908         goto out_unlock;
909 
910     context.type = typdatum->value;
911 
912     rc = mls_context_to_sid(oldc, &p, &context, &sidtab);
913     if ( rc )
914         goto out_unlock;
915 
916     if ( (p - scontext2) < scontext_len )
917     {
918         rc = -EINVAL;
919         goto out_unlock;
920     }
921 
922     /* Check the validity of the new context. */
923     if ( !policydb_context_isvalid(&policydb, &context) )
924     {
925         rc = -EINVAL;
926         goto out_unlock;
927     }
928     /* Obtain the new sid. */
929     rc = sidtab_context_to_sid(&sidtab, &context, sid);
930 out_unlock:
931     POLICY_RDUNLOCK;
932     context_destroy(&context);
933     xfree(scontext2);
934 out:
935     return rc;
936 }
937 
compute_sid_handle_invalid_context(struct context * scontext,struct context * tcontext,u16 tclass,struct context * newcontext)938 static int compute_sid_handle_invalid_context(
939                 struct context *scontext, struct context *tcontext, u16 tclass,
940                                                     struct context *newcontext)
941 {
942     char *s = NULL, *t = NULL, *n = NULL;
943     u32 slen, tlen, nlen;
944 
945     if ( context_struct_to_string(scontext, &s, &slen) < 0 )
946         goto out;
947     if ( context_struct_to_string(tcontext, &t, &tlen) < 0 )
948         goto out;
949     if ( context_struct_to_string(newcontext, &n, &nlen) < 0 )
950         goto out;
951     printk("security_compute_sid:  invalid context %s"
952           " for scontext=%s"
953           " tcontext=%s"
954           " tclass=%s",
955           n, s, t, policydb.p_class_val_to_name[tclass-1]);
956 out:
957     xfree(s);
958     xfree(t);
959     xfree(n);
960     if ( !flask_enforcing )
961         return 0;
962     return -EACCES;
963 }
964 
security_compute_sid(u32 ssid,u32 tsid,u16 tclass,u32 specified,u32 * out_sid)965 static int security_compute_sid(u32 ssid,
966                 u32 tsid,
967                 u16 tclass,
968                 u32 specified,
969                 u32 *out_sid)
970 {
971     struct context *scontext = NULL, *tcontext = NULL, newcontext;
972     struct role_trans *roletr = NULL;
973     struct avtab_key avkey;
974     struct avtab_datum *avdatum;
975     struct avtab_node *node;
976     int rc = 0;
977 
978     if ( !ss_initialized )
979     {
980         switch ( tclass )
981         {
982             case SECCLASS_DOMAIN:
983                 *out_sid = ssid;
984             break;
985             default:
986                 *out_sid = tsid;
987             break;
988         }
989         goto out;
990     }
991 
992     POLICY_RDLOCK;
993 
994     scontext = sidtab_search(&sidtab, ssid);
995     if ( !scontext )
996     {
997         printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n", ssid);
998         rc = -EINVAL;
999         goto out_unlock;
1000     }
1001     tcontext = sidtab_search(&sidtab, tsid);
1002     if ( !tcontext )
1003     {
1004         printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n", tsid);
1005         rc = -EINVAL;
1006         goto out_unlock;
1007     }
1008 
1009     context_init(&newcontext);
1010 
1011     /* Set the user identity. */
1012     switch ( specified )
1013     {
1014         case AVTAB_TRANSITION:
1015         case AVTAB_CHANGE:
1016             /* Use the process user identity. */
1017             newcontext.user = scontext->user;
1018         break;
1019         case AVTAB_MEMBER:
1020             /* Use the related object owner. */
1021             newcontext.user = tcontext->user;
1022         break;
1023     }
1024 
1025     /* Set the role and type to default values. */
1026     switch ( tclass )
1027     {
1028         case SECCLASS_DOMAIN:
1029             /* Use the current role and type of process. */
1030             newcontext.role = scontext->role;
1031             newcontext.type = scontext->type;
1032         break;
1033         default:
1034             /* Use the well-defined object role. */
1035             newcontext.role = OBJECT_R_VAL;
1036             /* Use the type of the related object. */
1037             newcontext.type = tcontext->type;
1038     }
1039 
1040     /* Look for a type transition/member/change rule. */
1041     avkey.source_type = scontext->type;
1042     avkey.target_type = tcontext->type;
1043     avkey.target_class = tclass;
1044     avkey.specified = specified;
1045     avdatum = avtab_search(&policydb.te_avtab, &avkey);
1046 
1047     /* If no permanent rule, also check for enabled conditional rules */
1048     if ( !avdatum )
1049     {
1050         node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
1051         for ( ; node != NULL; node = avtab_search_node_next(node, specified) )
1052         {
1053             if ( node->key.specified & AVTAB_ENABLED )
1054             {
1055                 avdatum = &node->datum;
1056                 break;
1057             }
1058         }
1059     }
1060 
1061     if ( avdatum )
1062     {
1063         /* Use the type from the type transition/member/change rule. */
1064         newcontext.type = avdatum->data;
1065     }
1066 
1067     /* Check for class-specific changes. */
1068     switch ( tclass )
1069     {
1070         case SECCLASS_DOMAIN:
1071             if ( specified & AVTAB_TRANSITION )
1072             {
1073                 /* Look for a role transition rule. */
1074                 for ( roletr = policydb.role_tr; roletr; roletr = roletr->next )
1075                 {
1076                     if ( roletr->role == scontext->role &&
1077                                             roletr->type == tcontext->type )
1078                     {
1079                         /* Use the role transition rule. */
1080                         newcontext.role = roletr->new_role;
1081                         break;
1082                     }
1083                 }
1084             }
1085         break;
1086         default:
1087         break;
1088     }
1089 
1090     /* Set the MLS attributes.
1091        This is done last because it may allocate memory. */
1092     rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
1093     if ( rc )
1094         goto out_unlock;
1095 
1096     /* Check the validity of the context. */
1097     if ( !policydb_context_isvalid(&policydb, &newcontext) )
1098     {
1099         rc = compute_sid_handle_invalid_context(scontext, tcontext, tclass,
1100                                                                 &newcontext);
1101         if ( rc )
1102             goto out_unlock;
1103     }
1104     /* Obtain the sid for the context. */
1105     rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
1106 out_unlock:
1107     POLICY_RDUNLOCK;
1108     context_destroy(&newcontext);
1109 out:
1110     return rc;
1111 }
1112 
1113 /**
1114  * security_transition_sid - Compute the SID for a new subject/object.
1115  * @ssid: source security identifier
1116  * @tsid: target security identifier
1117  * @tclass: target security class
1118  * @out_sid: security identifier for new subject/object
1119  *
1120  * Compute a SID to use for labeling a new subject or object in the
1121  * class @tclass based on a SID pair (@ssid, @tsid).
1122  * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1123  * if insufficient memory is available, or %0 if the new SID was
1124  * computed successfully.
1125  */
security_transition_sid(u32 ssid,u32 tsid,u16 tclass,u32 * out_sid)1126 int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
1127 {
1128     return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);
1129 }
1130 
1131 /**
1132  * security_member_sid - Compute the SID for member selection.
1133  * @ssid: source security identifier
1134  * @tsid: target security identifier
1135  * @tclass: target security class
1136  * @out_sid: security identifier for selected member
1137  *
1138  * Compute a SID to use when selecting a member of a polyinstantiated
1139  * object of class @tclass based on a SID pair (@ssid, @tsid).
1140  * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1141  * if insufficient memory is available, or %0 if the SID was
1142  * computed successfully.
1143  */
security_member_sid(u32 ssid,u32 tsid,u16 tclass,u32 * out_sid)1144 int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
1145 {
1146     return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);
1147 }
1148 
1149 /**
1150  * security_change_sid - Compute the SID for object relabeling.
1151  * @ssid: source security identifier
1152  * @tsid: target security identifier
1153  * @tclass: target security class
1154  * @out_sid: security identifier for selected member
1155  *
1156  * Compute a SID to use for relabeling an object of class @tclass
1157  * based on a SID pair (@ssid, @tsid).
1158  * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1159  * if insufficient memory is available, or %0 if the SID was
1160  * computed successfully.
1161  */
security_change_sid(u32 ssid,u32 tsid,u16 tclass,u32 * out_sid)1162 int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
1163 {
1164     return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);
1165 }
1166 
1167 /*
1168  * Verify that each kernel class that is defined in the
1169  * policy is correct
1170  */
validate_classes(struct policydb * p)1171 static int validate_classes(struct policydb *p)
1172 {
1173     int i;
1174     struct class_datum *cladatum;
1175     struct perm_datum *perdatum;
1176     u32 nprim, perm_val, pol_val;
1177     u16 class_val;
1178     const struct selinux_class_perm *kdefs = &selinux_class_perm;
1179     const char *def_class, *def_perm, *pol_class;
1180     struct symtab *perms;
1181 
1182     for ( i = 1; i < kdefs->cts_len; i++ )
1183     {
1184         def_class = kdefs->class_to_string[i];
1185         if ( !def_class )
1186             continue;
1187         if ( i > p->p_classes.nprim )
1188         {
1189             printk(KERN_INFO
1190                    "Flask:  class %s not defined in policy\n",
1191                    def_class);
1192             return -EINVAL;
1193         }
1194         pol_class = p->p_class_val_to_name[i-1];
1195         if ( strcmp(pol_class, def_class) )
1196         {
1197             printk(KERN_ERR
1198                    "Flask:  class %d is incorrect, found %s but should be %s\n",
1199                    i, pol_class, def_class);
1200             return -EINVAL;
1201         }
1202     }
1203     for ( i = 0; i < kdefs->av_pts_len; i++ )
1204     {
1205         class_val = kdefs->av_perm_to_string[i].tclass;
1206         perm_val = kdefs->av_perm_to_string[i].value;
1207         def_perm = kdefs->av_perm_to_string[i].name;
1208         if ( class_val > p->p_classes.nprim )
1209             continue;
1210         pol_class = p->p_class_val_to_name[class_val-1];
1211         cladatum = hashtab_search(p->p_classes.table, pol_class);
1212         BUG_ON( !cladatum );
1213         perms = &cladatum->permissions;
1214         nprim = 1 << (perms->nprim - 1);
1215         if ( perm_val > nprim )
1216         {
1217             printk(KERN_INFO
1218                    "Flask:  permission %s in class %s not defined in policy\n",
1219                    def_perm, pol_class);
1220             return -EINVAL;
1221         }
1222         perdatum = hashtab_search(perms->table, def_perm);
1223         if ( perdatum == NULL )
1224         {
1225             printk(KERN_ERR
1226                    "Flask:  permission %s in class %s not found in policy\n",
1227                    def_perm, pol_class);
1228             return -EINVAL;
1229         }
1230         pol_val = 1 << (perdatum->value - 1);
1231         if ( pol_val != perm_val )
1232         {
1233             printk(KERN_ERR
1234                    "Flask:  permission %s in class %s has incorrect value\n",
1235                    def_perm, pol_class);
1236             return -EINVAL;
1237         }
1238     }
1239     return 0;
1240 }
1241 
1242 /* Clone the SID into the new SID table. */
clone_sid(u32 sid,struct context * context,void * arg)1243 static int clone_sid(u32 sid, struct context *context, void *arg)
1244 {
1245     struct sidtab *s = arg;
1246 
1247     return sidtab_insert(s, sid, context);
1248 }
1249 
convert_context_handle_invalid_context(struct context * context)1250 static inline int convert_context_handle_invalid_context(struct context *context)
1251 {
1252     int rc = 0;
1253 
1254     if ( flask_enforcing )
1255         rc = -EINVAL;
1256     else
1257     {
1258         char *s;
1259         u32 len;
1260 
1261         context_struct_to_string(context, &s, &len);
1262         printk(KERN_ERR "Flask:  context %s is invalid\n", s);
1263         xfree(s);
1264     }
1265     return rc;
1266 }
1267 
1268 struct convert_context_args {
1269     struct policydb *oldp;
1270     struct policydb *newp;
1271 };
1272 
1273 /*
1274  * Convert the values in the security context
1275  * structure `c' from the values specified
1276  * in the policy `p->oldp' to the values specified
1277  * in the policy `p->newp'.  Verify that the
1278  * context is valid under the new policy.
1279  */
convert_context(u32 key,struct context * c,void * p)1280 static int convert_context(u32 key, struct context *c, void *p)
1281 {
1282     struct convert_context_args *args;
1283     struct context oldc;
1284     struct role_datum *role;
1285     struct type_datum *typdatum;
1286     struct user_datum *usrdatum;
1287     char *s;
1288     u32 len;
1289     int rc;
1290 
1291     args = p;
1292 
1293     rc = context_cpy(&oldc, c);
1294     if ( rc )
1295         goto out;
1296 
1297     rc = -EINVAL;
1298 
1299     /* Convert the user. */
1300     usrdatum = hashtab_search(args->newp->p_users.table,
1301                               args->oldp->p_user_val_to_name[c->user - 1]);
1302     if ( !usrdatum )
1303         goto bad;
1304 
1305     c->user = usrdatum->value;
1306 
1307     /* Convert the role. */
1308     role = hashtab_search(args->newp->p_roles.table,
1309                           args->oldp->p_role_val_to_name[c->role - 1]);
1310     if ( !role )
1311         goto bad;
1312 
1313     c->role = role->value;
1314 
1315     /* Convert the type. */
1316     typdatum = hashtab_search(args->newp->p_types.table,
1317                               args->oldp->p_type_val_to_name[c->type - 1]);
1318     if ( !typdatum )
1319         goto bad;
1320 
1321     c->type = typdatum->value;
1322 
1323     rc = mls_convert_context(args->oldp, args->newp, c);
1324     if ( rc )
1325         goto bad;
1326 
1327     /* Check the validity of the new context. */
1328     if ( !policydb_context_isvalid(args->newp, c) )
1329     {
1330         rc = convert_context_handle_invalid_context(&oldc);
1331         if ( rc )
1332             goto bad;
1333     }
1334 
1335     context_destroy(&oldc);
1336 out:
1337     return rc;
1338 bad:
1339     context_struct_to_string(&oldc, &s, &len);
1340     context_destroy(&oldc);
1341     printk(KERN_ERR "Flask:  invalidating context %s\n", s);
1342     xfree(s);
1343     goto out;
1344 }
1345 
1346 static int security_preserve_bools(struct policydb *p);
1347 
1348 /**
1349  * security_load_policy - Load a security policy configuration.
1350  * @data: binary policy data
1351  * @len: length of data in bytes
1352  *
1353  * Load a new set of security policy configuration data,
1354  * validate it and convert the SID table as necessary.
1355  * This function will flush the access vector cache after
1356  * loading the new policy.
1357  */
security_load_policy(const void * data,size_t len)1358 int security_load_policy(const void *data, size_t len)
1359 {
1360     struct policydb oldpolicydb, newpolicydb;
1361     struct sidtab oldsidtab, newsidtab;
1362     struct convert_context_args args;
1363     u32 seqno;
1364     int rc = 0;
1365     struct policy_file file = { data, len }, *fp = &file;
1366 
1367     LOAD_LOCK;
1368 
1369     if ( !ss_initialized )
1370     {
1371         if ( policydb_read(&policydb, fp) )
1372         {
1373             LOAD_UNLOCK;
1374             return -EINVAL;
1375         }
1376         if ( policydb_load_isids(&policydb, &sidtab) )
1377         {
1378             LOAD_UNLOCK;
1379             policydb_destroy(&policydb);
1380             return -EINVAL;
1381         }
1382         if ( validate_classes(&policydb) )
1383         {
1384             LOAD_UNLOCK;
1385             printk(KERN_ERR
1386                    "Flask:  the definition of a class is incorrect\n");
1387             sidtab_destroy(&sidtab);
1388             policydb_destroy(&policydb);
1389             return -EINVAL;
1390         }
1391         policydb_loaded_version = policydb.policyvers;
1392         ss_initialized = 1;
1393         seqno = ++latest_granting;
1394         LOAD_UNLOCK;
1395         avc_ss_reset(seqno);
1396         return 0;
1397     }
1398 
1399 #if 0
1400     sidtab_hash_eval(&sidtab, "sids");
1401 #endif
1402 
1403     if ( policydb_read(&newpolicydb, fp) )
1404     {
1405         LOAD_UNLOCK;
1406         return -EINVAL;
1407     }
1408 
1409     sidtab_init(&newsidtab);
1410 
1411     /* Verify that the kernel defined classes are correct. */
1412     if ( validate_classes(&newpolicydb) )
1413     {
1414         printk(KERN_ERR
1415                "Flask:  the definition of a class is incorrect\n");
1416         rc = -EINVAL;
1417         goto err;
1418     }
1419 
1420     rc = security_preserve_bools(&newpolicydb);
1421     if ( rc )
1422     {
1423         printk(KERN_ERR "Flask:  unable to preserve booleans\n");
1424         goto err;
1425     }
1426 
1427     /* Clone the SID table. */
1428     sidtab_shutdown(&sidtab);
1429     if ( sidtab_map(&sidtab, clone_sid, &newsidtab) )
1430     {
1431         rc = -ENOMEM;
1432         goto err;
1433     }
1434 
1435     /* Convert the internal representations of contexts
1436        in the new SID table and remove invalid SIDs. */
1437     args.oldp = &policydb;
1438     args.newp = &newpolicydb;
1439     sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
1440 
1441     /* Save the old policydb and SID table to free later. */
1442     memcpy(&oldpolicydb, &policydb, sizeof policydb);
1443     sidtab_set(&oldsidtab, &sidtab);
1444 
1445     /* Install the new policydb and SID table. */
1446     POLICY_WRLOCK;
1447     memcpy(&policydb, &newpolicydb, sizeof policydb);
1448     sidtab_set(&sidtab, &newsidtab);
1449     seqno = ++latest_granting;
1450     policydb_loaded_version = policydb.policyvers;
1451     POLICY_WRUNLOCK;
1452     LOAD_UNLOCK;
1453 
1454     /* Free the old policydb and SID table. */
1455     policydb_destroy(&oldpolicydb);
1456     sidtab_destroy(&oldsidtab);
1457 
1458     avc_ss_reset(seqno);
1459 
1460     return 0;
1461 
1462 err:
1463     LOAD_UNLOCK;
1464     sidtab_destroy(&newsidtab);
1465     policydb_destroy(&newpolicydb);
1466     return rc;
1467 
1468 }
1469 
security_get_allow_unknown(void)1470 int security_get_allow_unknown(void)
1471 {
1472     return policydb.allow_unknown;
1473 }
1474 
1475 /**
1476  * security_irq_sid - Obtain the SID for a physical irq.
1477  * @pirq: physical irq
1478  * @out_sid: security identifier
1479  */
security_irq_sid(int pirq,u32 * out_sid)1480 int security_irq_sid(int pirq, u32 *out_sid)
1481 {
1482     int rc = 0;
1483     struct ocontext *c;
1484 
1485     POLICY_RDLOCK;
1486 
1487     c = policydb.ocontexts[OCON_PIRQ];
1488 
1489     while ( c )
1490     {
1491         if ( c->u.pirq == pirq )
1492             break;
1493         c = c->next;
1494     }
1495 
1496     if ( c )
1497     {
1498         if ( !c->sid )
1499         {
1500             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1501             if ( rc )
1502                 goto out;
1503         }
1504         *out_sid = c->sid;
1505     }
1506     else
1507     {
1508         *out_sid = SECINITSID_IRQ;
1509     }
1510 
1511 out:
1512     POLICY_RDUNLOCK;
1513     return rc;
1514 }
1515 
1516 /**
1517  * security_iomem_sid - Obtain the SID for a page of iomem.
1518  * @mfn: iomem mfn
1519  * @out_sid: security identifier
1520  */
security_iomem_sid(unsigned long mfn,u32 * out_sid)1521 int security_iomem_sid(unsigned long mfn, u32 *out_sid)
1522 {
1523     struct ocontext *c;
1524     int rc = 0;
1525 
1526     POLICY_RDLOCK;
1527 
1528     c = policydb.ocontexts[OCON_IOMEM];
1529     while ( c )
1530     {
1531         if ( c->u.iomem.low_iomem <= mfn  && c->u.iomem.high_iomem >= mfn )
1532             break;
1533         c = c->next;
1534     }
1535 
1536     if ( c )
1537     {
1538         if ( !c->sid )
1539         {
1540             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1541             if ( rc )
1542                 goto out;
1543         }
1544         *out_sid = c->sid;
1545     }
1546     else
1547     {
1548         *out_sid = SECINITSID_IOMEM;
1549     }
1550 
1551 out:
1552     POLICY_RDUNLOCK;
1553     return rc;
1554 }
1555 
security_iterate_iomem_sids(unsigned long start,unsigned long end,security_iterate_fn fn,void * data)1556 int security_iterate_iomem_sids(unsigned long start, unsigned long end,
1557                                 security_iterate_fn fn, void *data)
1558 {
1559     struct ocontext *c;
1560     int rc = 0;
1561 
1562     POLICY_RDLOCK;
1563 
1564     c = policydb.ocontexts[OCON_IOMEM];
1565     while (c && c->u.iomem.high_iomem < start)
1566         c = c->next;
1567 
1568     while (c && c->u.iomem.low_iomem <= end) {
1569         if (!c->sid)
1570         {
1571             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1572             if ( rc )
1573                 goto out;
1574         }
1575         if (start < c->u.iomem.low_iomem) {
1576             /* found a gap */
1577             rc = fn(data, SECINITSID_IOMEM, start, c->u.iomem.low_iomem - 1);
1578             if (rc)
1579                 goto out;
1580             start = c->u.iomem.low_iomem;
1581         }
1582         if (end <= c->u.iomem.high_iomem) {
1583             /* iteration ends in the middle of this range */
1584             rc = fn(data, c->sid, start, end);
1585             goto out;
1586         }
1587 
1588         rc = fn(data, c->sid, start, c->u.iomem.high_iomem);
1589         if (rc)
1590             goto out;
1591         start = c->u.iomem.high_iomem + 1;
1592 
1593         c = c->next;
1594     }
1595 
1596     rc = fn(data, SECINITSID_IOMEM, start, end);
1597 
1598 out:
1599     POLICY_RDUNLOCK;
1600     return rc;
1601 }
1602 
1603 /**
1604  * security_ioport_sid - Obtain the SID for an ioport.
1605  * @ioport: ioport
1606  * @out_sid: security identifier
1607  */
security_ioport_sid(u32 ioport,u32 * out_sid)1608 int security_ioport_sid(u32 ioport, u32 *out_sid)
1609 {
1610     struct ocontext *c;
1611     int rc = 0;
1612 
1613     POLICY_RDLOCK;
1614 
1615     c = policydb.ocontexts[OCON_IOPORT];
1616     while ( c )
1617     {
1618         if ( c->u.ioport.low_ioport <= ioport &&
1619              c->u.ioport.high_ioport >= ioport )
1620             break;
1621         c = c->next;
1622     }
1623 
1624     if ( c )
1625     {
1626         if ( !c->sid )
1627         {
1628             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1629             if ( rc )
1630                 goto out;
1631         }
1632         *out_sid = c->sid;
1633     }
1634     else
1635     {
1636         *out_sid = SECINITSID_IOPORT;
1637     }
1638 
1639 out:
1640     POLICY_RDUNLOCK;
1641     return rc;
1642 }
1643 
security_iterate_ioport_sids(u32 start,u32 end,security_iterate_fn fn,void * data)1644 int security_iterate_ioport_sids(u32 start, u32 end,
1645                                 security_iterate_fn fn, void *data)
1646 {
1647     struct ocontext *c;
1648     int rc = 0;
1649 
1650     POLICY_RDLOCK;
1651 
1652     c = policydb.ocontexts[OCON_IOPORT];
1653     while (c && c->u.ioport.high_ioport < start)
1654         c = c->next;
1655 
1656     while (c && c->u.ioport.low_ioport <= end) {
1657         if (!c->sid)
1658         {
1659             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1660             if ( rc )
1661                 goto out;
1662         }
1663         if (start < c->u.ioport.low_ioport) {
1664             /* found a gap */
1665             rc = fn(data, SECINITSID_IOPORT, start, c->u.ioport.low_ioport - 1);
1666             if (rc)
1667                 goto out;
1668             start = c->u.ioport.low_ioport;
1669         }
1670         if (end <= c->u.ioport.high_ioport) {
1671             /* iteration ends in the middle of this range */
1672             rc = fn(data, c->sid, start, end);
1673             goto out;
1674         }
1675 
1676         rc = fn(data, c->sid, start, c->u.ioport.high_ioport);
1677         if (rc)
1678             goto out;
1679         start = c->u.ioport.high_ioport + 1;
1680 
1681         c = c->next;
1682     }
1683 
1684     rc = fn(data, SECINITSID_IOPORT, start, end);
1685 
1686 out:
1687     POLICY_RDUNLOCK;
1688     return rc;
1689 }
1690 
1691 /**
1692  * security_device_sid - Obtain the SID for a PCI device.
1693  * @ioport: device
1694  * @out_sid: security identifier
1695  */
security_device_sid(u32 device,u32 * out_sid)1696 int security_device_sid(u32 device, u32 *out_sid)
1697 {
1698     struct ocontext *c;
1699     int rc = 0;
1700 
1701     POLICY_RDLOCK;
1702 
1703     c = policydb.ocontexts[OCON_DEVICE];
1704     while ( c )
1705     {
1706         if ( c->u.device == device )
1707             break;
1708         c = c->next;
1709     }
1710 
1711     if ( c )
1712     {
1713         if ( !c->sid )
1714         {
1715             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1716             if ( rc )
1717                 goto out;
1718         }
1719         *out_sid = c->sid;
1720     }
1721     else
1722     {
1723         *out_sid = SECINITSID_DEVICE;
1724     }
1725 
1726 out:
1727     POLICY_RDUNLOCK;
1728     return rc;
1729 }
1730 
security_devicetree_sid(const char * path,u32 * out_sid)1731 int security_devicetree_sid(const char *path, u32 *out_sid)
1732 {
1733     struct ocontext *c;
1734     int rc = 0;
1735 
1736     POLICY_RDLOCK;
1737 
1738     c = policydb.ocontexts[OCON_DTREE];
1739     while ( c )
1740     {
1741         if ( strcmp(c->u.name, path) == 0 )
1742             break;
1743         c = c->next;
1744     }
1745 
1746     if ( c )
1747     {
1748         if ( !c->sid )
1749         {
1750             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1751             if ( rc )
1752                 goto out;
1753         }
1754         *out_sid = c->sid;
1755     }
1756     else
1757     {
1758         *out_sid = SECINITSID_DEVICE;
1759     }
1760 
1761 out:
1762     POLICY_RDUNLOCK;
1763     return rc;
1764 }
1765 
security_find_bool(const char * name)1766 int security_find_bool(const char *name)
1767 {
1768     int i, rv = -ENOENT;
1769     POLICY_RDLOCK;
1770     for ( i = 0; i < policydb.p_bools.nprim; i++ )
1771     {
1772         if (!strcmp(name, policydb.p_bool_val_to_name[i]))
1773         {
1774             rv = i;
1775             break;
1776         }
1777     }
1778 
1779     POLICY_RDUNLOCK;
1780     return rv;
1781 }
1782 
security_get_bools(int * len,char *** names,int ** values,size_t * maxstr)1783 int security_get_bools(int *len, char ***names, int **values, size_t *maxstr)
1784 {
1785     int i, rc = -ENOMEM;
1786 
1787     POLICY_RDLOCK;
1788     if ( names )
1789         *names = NULL;
1790     *values = NULL;
1791     if ( maxstr )
1792         *maxstr = 0;
1793 
1794     *len = policydb.p_bools.nprim;
1795     if ( !*len )
1796     {
1797         rc = 0;
1798         goto out;
1799     }
1800 
1801     if ( names )
1802     {
1803         *names = xzalloc_array(char *, *len);
1804         if ( !*names )
1805             goto err;
1806     }
1807 
1808     *values = xmalloc_array(int, *len);
1809     if ( !*values )
1810         goto err;
1811 
1812     for ( i = 0; i < *len; i++ )
1813     {
1814         size_t name_len = strlen(policydb.p_bool_val_to_name[i]);
1815 
1816         (*values)[i] = policydb.bool_val_to_struct[i]->state;
1817         if ( names ) {
1818             (*names)[i] = xmalloc_array(char, name_len + 1);
1819             if ( !(*names)[i] )
1820                 goto err;
1821             strlcpy((*names)[i], policydb.p_bool_val_to_name[i], name_len + 1);
1822         }
1823         if ( maxstr && name_len > *maxstr )
1824             *maxstr = name_len;
1825     }
1826     rc = 0;
1827 out:
1828     POLICY_RDUNLOCK;
1829     return rc;
1830 err:
1831     if ( names && *names )
1832     {
1833         for ( i = 0; i < *len; i++ )
1834             xfree((*names)[i]);
1835         xfree(*names);
1836     }
1837     xfree(*values);
1838     goto out;
1839 }
1840 
1841 
security_set_bools(int len,int * values)1842 int security_set_bools(int len, int *values)
1843 {
1844     int i, rc = 0;
1845     int lenp, seqno = 0;
1846     struct cond_node *cur;
1847 
1848     POLICY_WRLOCK;
1849 
1850     lenp = policydb.p_bools.nprim;
1851     if ( len != lenp )
1852     {
1853         rc = -EFAULT;
1854         goto out;
1855     }
1856 
1857     printk(KERN_INFO "Flask: committed booleans { ");
1858     for ( i = 0; i < len; i++ )
1859     {
1860         if ( values[i] )
1861         {
1862             policydb.bool_val_to_struct[i]->state = 1;
1863         }
1864         else
1865         {
1866             policydb.bool_val_to_struct[i]->state = 0;
1867         }
1868         if ( i != 0 )
1869             printk(", ");
1870         printk("%s:%d", policydb.p_bool_val_to_name[i],
1871                policydb.bool_val_to_struct[i]->state);
1872     }
1873     printk(" }\n");
1874 
1875     for ( cur = policydb.cond_list; cur != NULL; cur = cur->next )
1876     {
1877         rc = evaluate_cond_node(&policydb, cur);
1878         if ( rc )
1879             goto out;
1880     }
1881 
1882     seqno = ++latest_granting;
1883 
1884 out:
1885     POLICY_WRUNLOCK;
1886     if ( !rc )
1887     {
1888         avc_ss_reset(seqno);
1889     }
1890     return rc;
1891 }
1892 
security_get_bool_value(unsigned int b)1893 int security_get_bool_value(unsigned int b)
1894 {
1895     int rc = 0;
1896     unsigned int len;
1897 
1898     POLICY_RDLOCK;
1899 
1900     len = policydb.p_bools.nprim;
1901     if ( b >= len )
1902     {
1903         rc = -ENOENT;
1904         goto out;
1905     }
1906 
1907     rc = policydb.bool_val_to_struct[b]->state;
1908 out:
1909     POLICY_RDUNLOCK;
1910     return rc;
1911 }
1912 
security_get_bool_name(unsigned int b)1913 char *security_get_bool_name(unsigned int b)
1914 {
1915     unsigned int len;
1916     char *rv = NULL;
1917 
1918     POLICY_RDLOCK;
1919 
1920     len = policydb.p_bools.nprim;
1921     if ( b >= len )
1922     {
1923         goto out;
1924     }
1925 
1926     len = strlen(policydb.p_bool_val_to_name[b]) + 1;
1927     rv = xmalloc_array(char, len);
1928     if ( !rv )
1929         goto out;
1930     memcpy(rv, policydb.p_bool_val_to_name[b], len);
1931 out:
1932     POLICY_RDUNLOCK;
1933     return rv;
1934 }
1935 
security_preserve_bools(struct policydb * p)1936 static int security_preserve_bools(struct policydb *p)
1937 {
1938     int rc, nbools = 0, *bvalues = NULL, i;
1939     char **bnames = NULL;
1940     struct cond_bool_datum *booldatum;
1941     struct cond_node *cur;
1942 
1943     rc = security_get_bools(&nbools, &bnames, &bvalues, NULL);
1944     if ( rc )
1945         return rc;
1946     for ( i = 0; i < nbools; i++ )
1947     {
1948         booldatum = hashtab_search(p->p_bools.table, bnames[i]);
1949         if ( booldatum )
1950             booldatum->state = bvalues[i];
1951     }
1952     for ( cur = p->cond_list; cur; cur = cur->next )
1953     {
1954         rc = evaluate_cond_node(p, cur);
1955         if ( rc )
1956             goto out;
1957     }
1958 
1959 out:
1960     if ( bnames )
1961     {
1962         for ( i = 0; i < nbools; i++ )
1963             xfree(bnames[i]);
1964     }
1965     xfree(bnames);
1966     xfree(bvalues);
1967     return rc;
1968 }
1969 
security_ocontext_add(u32 ocon,unsigned long low,unsigned long high,u32 sid)1970 int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high
1971                             ,u32 sid )
1972 {
1973     int ret = 0;
1974     struct ocontext *c;
1975     struct ocontext *prev;
1976     struct ocontext *add;
1977 
1978     if ( (add = xzalloc(struct ocontext)) == NULL )
1979         return -ENOMEM;
1980     add->sid = sid;
1981 
1982     POLICY_WRLOCK;
1983     switch( ocon )
1984     {
1985     case OCON_PIRQ:
1986         add->u.pirq = (u16)low;
1987         if ( high != low )
1988         {
1989             ret = -EINVAL;
1990             break;
1991         }
1992 
1993         c = policydb.ocontexts[OCON_PIRQ];
1994         while ( c )
1995         {
1996             if ( c->u.pirq == add->u.pirq )
1997             {
1998                 if ( c->sid == sid )
1999                     break;
2000                 printk("flask: Duplicate pirq %d\n", add->u.pirq);
2001                 ret = -EEXIST;
2002                 break;
2003             }
2004             c = c->next;
2005         }
2006 
2007         if ( ret == 0 )
2008         {
2009             add->next = policydb.ocontexts[OCON_PIRQ];
2010             policydb.ocontexts[OCON_PIRQ] = add;
2011         }
2012         break;
2013 
2014     case OCON_IOPORT:
2015         add->u.ioport.low_ioport = low;
2016         add->u.ioport.high_ioport = high;
2017 
2018         prev = NULL;
2019         c = policydb.ocontexts[OCON_IOPORT];
2020 
2021         while ( c && c->u.ioport.high_ioport < low ) {
2022             prev = c;
2023             c = c->next;
2024         }
2025 
2026         if (c && c->u.ioport.low_ioport <= high)
2027         {
2028             if (c->u.ioport.low_ioport == low &&
2029                 c->u.ioport.high_ioport == high && c->sid == sid)
2030                 break;
2031 
2032             printk("flask: IO Port overlap with entry %#x - %#x\n",
2033                    c->u.ioport.low_ioport, c->u.ioport.high_ioport);
2034             ret = -EEXIST;
2035             break;
2036         }
2037 
2038         if (prev) {
2039             add->next = prev->next;
2040             prev->next = add;
2041         } else {
2042             add->next = policydb.ocontexts[OCON_IOPORT];
2043             policydb.ocontexts[OCON_IOPORT] = add;
2044         }
2045         break;
2046 
2047     case OCON_IOMEM:
2048         add->u.iomem.low_iomem = low;
2049         add->u.iomem.high_iomem = high;
2050 
2051         prev = NULL;
2052         c = policydb.ocontexts[OCON_IOMEM];
2053 
2054         while ( c && c->u.iomem.high_iomem < low ) {
2055             prev = c;
2056             c = c->next;
2057         }
2058 
2059         if (c && c->u.iomem.low_iomem <= high)
2060         {
2061             if (c->u.iomem.low_iomem == low &&
2062                 c->u.iomem.high_iomem == high && c->sid == sid)
2063                 break;
2064 
2065             printk("flask: IO Memory overlap with entry %#"PRIx64" - %#"PRIx64"\n",
2066                    c->u.iomem.low_iomem, c->u.iomem.high_iomem);
2067             ret = -EEXIST;
2068             break;
2069         }
2070 
2071         if (prev) {
2072             add->next = prev->next;
2073             prev->next = add;
2074         } else {
2075             add->next = policydb.ocontexts[OCON_IOMEM];
2076             policydb.ocontexts[OCON_IOMEM] = add;
2077         }
2078         break;
2079 
2080      case OCON_DEVICE:
2081         add->u.device = low;
2082         if ( high != low )
2083         {
2084             ret = -EINVAL;
2085             break;
2086         }
2087 
2088         c = policydb.ocontexts[OCON_DEVICE];
2089         while ( c )
2090         {
2091             if ( c->u.device == add->u.device )
2092             {
2093                 if ( c->sid == sid )
2094                     break;
2095 
2096                 printk("flask: Duplicate PCI Device %#x\n", add->u.device);
2097                 ret = -EEXIST;
2098                 break;
2099             }
2100             c = c->next;
2101         }
2102 
2103         if ( ret == 0 )
2104         {
2105             add->next = policydb.ocontexts[OCON_DEVICE];
2106             policydb.ocontexts[OCON_DEVICE] = add;
2107         }
2108         break;
2109 
2110      default:
2111          ret = -EINVAL;
2112     }
2113     POLICY_WRUNLOCK;
2114 
2115     if ( ret != 0 )
2116         xfree(add);
2117     return ret;
2118 }
2119 
security_ocontext_del(u32 ocon,unsigned long low,unsigned long high)2120 int security_ocontext_del( u32 ocon, unsigned long low, unsigned long high )
2121 {
2122     int ret = 0;
2123     struct ocontext *c, *before_c;
2124 
2125     POLICY_WRLOCK;
2126     switch( ocon )
2127     {
2128     case OCON_PIRQ:
2129         for ( before_c = NULL, c = policydb.ocontexts[OCON_PIRQ];
2130               c; before_c = c, c = c->next )
2131         {
2132             if ( c->u.pirq == low )
2133             {
2134                 if ( before_c == NULL )
2135                 {
2136                     policydb.ocontexts[OCON_PIRQ] = c->next;
2137                     xfree(c);
2138                     goto out;
2139                 }
2140                 else
2141                 {
2142                     before_c->next = c->next;
2143                     xfree(c);
2144                     goto out;
2145                 }
2146             }
2147         }
2148 
2149         printk("flask: ocontext not found: pirq %ld\n", low);
2150         ret = -ENOENT;
2151         break;
2152 
2153     case OCON_IOPORT:
2154         for ( before_c = NULL, c = policydb.ocontexts[OCON_IOPORT];
2155               c; before_c = c, c = c->next )
2156         {
2157             if ( c->u.ioport.low_ioport == low &&
2158                  c->u.ioport.high_ioport == high )
2159             {
2160                 if ( before_c == NULL )
2161                 {
2162                     policydb.ocontexts[OCON_IOPORT] = c->next;
2163                     xfree(c);
2164                     goto out;
2165                 }
2166                 else
2167                 {
2168                     before_c->next = c->next;
2169                     xfree(c);
2170                     goto out;
2171                 }
2172             }
2173         }
2174 
2175         printk("flask: ocontext not found: ioport %#lx - %#lx\n", low, high);
2176         ret = -ENOENT;
2177         break;
2178 
2179     case OCON_IOMEM:
2180         for ( before_c = NULL, c = policydb.ocontexts[OCON_IOMEM];
2181               c; before_c = c, c = c->next )
2182         {
2183             if ( c->u.iomem.low_iomem == low &&
2184                  c->u.iomem.high_iomem == high )
2185             {
2186                 if ( before_c == NULL )
2187                 {
2188                     policydb.ocontexts[OCON_IOMEM] = c->next;
2189                     xfree(c);
2190                     goto out;
2191                 }
2192                 else
2193                 {
2194                     before_c->next = c->next;
2195                     xfree(c);
2196                     goto out;
2197                 }
2198             }
2199         }
2200 
2201         printk("flask: ocontext not found: iomem %#lx - %#lx\n", low, high);
2202         ret = -ENOENT;
2203         break;
2204 
2205     case OCON_DEVICE:
2206         for ( before_c = NULL, c = policydb.ocontexts[OCON_DEVICE];
2207               c; before_c = c, c = c->next )
2208         {
2209             if ( c->u.device == low )
2210             {
2211                 if ( before_c == NULL )
2212                 {
2213                     policydb.ocontexts[OCON_DEVICE] = c->next;
2214                     xfree(c);
2215                     goto out;
2216                 }
2217                 else
2218                 {
2219                     before_c->next = c->next;
2220                     xfree(c);
2221                     goto out;
2222                 }
2223             }
2224         }
2225 
2226         printk("flask: ocontext not found: pcidevice %#lx\n", low);
2227         ret = -ENOENT;
2228         break;
2229 
2230     default:
2231         ret = -EINVAL;
2232     }
2233 
2234   out:
2235     POLICY_WRUNLOCK;
2236     return ret;
2237 }
2238 
security_devicetree_setlabel(char * path,u32 sid)2239 int security_devicetree_setlabel(char *path, u32 sid)
2240 {
2241     int ret = 0;
2242     struct ocontext *c;
2243     struct ocontext **pcurr;
2244     struct ocontext *add = NULL;
2245 
2246     if ( sid )
2247     {
2248         add = xzalloc(struct ocontext);
2249         if ( add == NULL )
2250         {
2251             xfree(path);
2252             return -ENOMEM;
2253         }
2254         add->sid = sid;
2255         add->u.name = path;
2256     }
2257     else
2258     {
2259         ret = -ENOENT;
2260     }
2261 
2262     POLICY_WRLOCK;
2263 
2264     pcurr = &policydb.ocontexts[OCON_DTREE];
2265     c = *pcurr;
2266     while ( c )
2267     {
2268         if ( strcmp(c->u.name, path) == 0 )
2269         {
2270             if ( sid )
2271             {
2272                 ret = -EEXIST;
2273                 break;
2274             }
2275             else
2276             {
2277                 *pcurr = c->next;
2278                 xfree(c->u.name);
2279                 xfree(c);
2280                 ret = 0;
2281                 break;
2282             }
2283         }
2284         pcurr = &c->next;
2285         c = *pcurr;
2286     }
2287 
2288     if ( add && ret == 0 )
2289     {
2290         add->next = policydb.ocontexts[OCON_DTREE];
2291         policydb.ocontexts[OCON_DTREE] = add;
2292         add = NULL;
2293         path = NULL;
2294     }
2295 
2296     POLICY_WRUNLOCK;
2297 
2298     xfree(add);
2299     xfree(path);
2300     return ret;
2301 }
2302