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             strlcpy(scontextp, initial_sid_to_string[sid], *scontext_len);
779             *scontext = scontextp;
780             goto out;
781         }
782         printk(KERN_ERR "security_sid_to_context:  called before initial "
783                "load_policy on unknown SID %d\n", sid);
784         rc = -EINVAL;
785         goto out;
786     }
787     POLICY_RDLOCK;
788     context = sidtab_search(&sidtab, sid);
789     if ( !context )
790     {
791         printk(KERN_ERR "security_sid_to_context:  unrecognized SID "
792                "%d\n", sid);
793         rc = -EINVAL;
794         goto out_unlock;
795     }
796     rc = context_struct_to_string(context, scontext, scontext_len);
797 out_unlock:
798     POLICY_RDUNLOCK;
799 out:
800     return rc;
801 
802 }
803 
804 /**
805  * security_context_to_sid - Obtain a SID for a given security context.
806  * @scontext: security context
807  * @scontext_len: length in bytes
808  * @sid: security identifier, SID
809  *
810  * Obtains a SID associated with the security context that
811  * has the string representation specified by @scontext.
812  * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
813  * memory is available, or 0 on success.
814  */
security_context_to_sid(char * scontext,u32 scontext_len,u32 * sid)815 int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
816 {
817     char *scontext2;
818     struct context context;
819     struct role_datum *role;
820     struct type_datum *typdatum;
821     struct user_datum *usrdatum;
822     char *scontextp, *p, oldc;
823     int rc = 0;
824 
825     if ( !ss_initialized )
826     {
827         int i;
828 
829         for ( i = 1; i < SECINITSID_NUM; i++ )
830         {
831             if ( !strcmp(initial_sid_to_string[i], scontext) )
832             {
833                 *sid = i;
834                 goto out;
835             }
836         }
837         *sid = SECINITSID_XEN;
838         goto out;
839     }
840     *sid = SECSID_NULL;
841 
842     /* Copy the string so that we can modify the copy as we parse it.
843        The string should already by null terminated, but we append a
844        null suffix to the copy to avoid problems with the existing
845        attr package, which doesn't view the null terminator as part
846        of the attribute value. */
847     scontext2 = xmalloc_array(char, scontext_len+1);
848     if ( !scontext2 )
849     {
850         rc = -ENOMEM;
851         goto out;
852     }
853     memcpy(scontext2, scontext, scontext_len);
854     scontext2[scontext_len] = 0;
855 
856     context_init(&context);
857     *sid = SECSID_NULL;
858 
859     POLICY_RDLOCK;
860 
861     /* Parse the security context. */
862 
863     rc = -EINVAL;
864     scontextp = (char *) scontext2;
865 
866     /* Extract the user. */
867     p = scontextp;
868     while ( *p && *p != ':' )
869         p++;
870 
871     if (*p == 0)
872         goto out_unlock;
873 
874     *p++ = 0;
875 
876     usrdatum = hashtab_search(policydb.p_users.table, scontextp);
877     if ( !usrdatum )
878         goto out_unlock;
879 
880     context.user = usrdatum->value;
881 
882     /* Extract role. */
883     scontextp = p;
884     while ( *p && *p != ':' )
885         p++;
886 
887     if ( *p == 0 )
888         goto out_unlock;
889 
890     *p++ = 0;
891 
892     role = hashtab_search(policydb.p_roles.table, scontextp);
893     if ( !role )
894         goto out_unlock;
895     context.role = role->value;
896 
897     /* Extract type. */
898     scontextp = p;
899     while ( *p && *p != ':' )
900         p++;
901     oldc = *p;
902     *p++ = 0;
903 
904     typdatum = hashtab_search(policydb.p_types.table, scontextp);
905     if ( !typdatum || typdatum->attribute )
906         goto out_unlock;
907 
908     context.type = typdatum->value;
909 
910     rc = mls_context_to_sid(oldc, &p, &context, &sidtab);
911     if ( rc )
912         goto out_unlock;
913 
914     if ( (p - scontext2) < scontext_len )
915     {
916         rc = -EINVAL;
917         goto out_unlock;
918     }
919 
920     /* Check the validity of the new context. */
921     if ( !policydb_context_isvalid(&policydb, &context) )
922     {
923         rc = -EINVAL;
924         goto out_unlock;
925     }
926     /* Obtain the new sid. */
927     rc = sidtab_context_to_sid(&sidtab, &context, sid);
928 out_unlock:
929     POLICY_RDUNLOCK;
930     context_destroy(&context);
931     xfree(scontext2);
932 out:
933     return rc;
934 }
935 
compute_sid_handle_invalid_context(struct context * scontext,struct context * tcontext,u16 tclass,struct context * newcontext)936 static int compute_sid_handle_invalid_context(
937                 struct context *scontext, struct context *tcontext, u16 tclass,
938                                                     struct context *newcontext)
939 {
940     char *s = NULL, *t = NULL, *n = NULL;
941     u32 slen, tlen, nlen;
942 
943     if ( context_struct_to_string(scontext, &s, &slen) < 0 )
944         goto out;
945     if ( context_struct_to_string(tcontext, &t, &tlen) < 0 )
946         goto out;
947     if ( context_struct_to_string(newcontext, &n, &nlen) < 0 )
948         goto out;
949     printk("security_compute_sid:  invalid context %s"
950           " for scontext=%s"
951           " tcontext=%s"
952           " tclass=%s",
953           n, s, t, policydb.p_class_val_to_name[tclass-1]);
954 out:
955     xfree(s);
956     xfree(t);
957     xfree(n);
958     if ( !flask_enforcing )
959         return 0;
960     return -EACCES;
961 }
962 
security_compute_sid(u32 ssid,u32 tsid,u16 tclass,u32 specified,u32 * out_sid)963 static int security_compute_sid(u32 ssid,
964                 u32 tsid,
965                 u16 tclass,
966                 u32 specified,
967                 u32 *out_sid)
968 {
969     struct context *scontext = NULL, *tcontext = NULL, newcontext;
970     struct role_trans *roletr = NULL;
971     struct avtab_key avkey;
972     struct avtab_datum *avdatum;
973     struct avtab_node *node;
974     int rc = 0;
975 
976     if ( !ss_initialized )
977     {
978         switch ( tclass )
979         {
980             case SECCLASS_DOMAIN:
981                 *out_sid = ssid;
982             break;
983             default:
984                 *out_sid = tsid;
985             break;
986         }
987         goto out;
988     }
989 
990     POLICY_RDLOCK;
991 
992     scontext = sidtab_search(&sidtab, ssid);
993     if ( !scontext )
994     {
995         printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n", ssid);
996         rc = -EINVAL;
997         goto out_unlock;
998     }
999     tcontext = sidtab_search(&sidtab, tsid);
1000     if ( !tcontext )
1001     {
1002         printk(KERN_ERR "security_compute_sid:  unrecognized SID %d\n", tsid);
1003         rc = -EINVAL;
1004         goto out_unlock;
1005     }
1006 
1007     context_init(&newcontext);
1008 
1009     /* Set the user identity. */
1010     switch ( specified )
1011     {
1012         case AVTAB_TRANSITION:
1013         case AVTAB_CHANGE:
1014             /* Use the process user identity. */
1015             newcontext.user = scontext->user;
1016         break;
1017         case AVTAB_MEMBER:
1018             /* Use the related object owner. */
1019             newcontext.user = tcontext->user;
1020         break;
1021     }
1022 
1023     /* Set the role and type to default values. */
1024     switch ( tclass )
1025     {
1026         case SECCLASS_DOMAIN:
1027             /* Use the current role and type of process. */
1028             newcontext.role = scontext->role;
1029             newcontext.type = scontext->type;
1030         break;
1031         default:
1032             /* Use the well-defined object role. */
1033             newcontext.role = OBJECT_R_VAL;
1034             /* Use the type of the related object. */
1035             newcontext.type = tcontext->type;
1036     }
1037 
1038     /* Look for a type transition/member/change rule. */
1039     avkey.source_type = scontext->type;
1040     avkey.target_type = tcontext->type;
1041     avkey.target_class = tclass;
1042     avkey.specified = specified;
1043     avdatum = avtab_search(&policydb.te_avtab, &avkey);
1044 
1045     /* If no permanent rule, also check for enabled conditional rules */
1046     if ( !avdatum )
1047     {
1048         node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
1049         for ( ; node != NULL; node = avtab_search_node_next(node, specified) )
1050         {
1051             if ( node->key.specified & AVTAB_ENABLED )
1052             {
1053                 avdatum = &node->datum;
1054                 break;
1055             }
1056         }
1057     }
1058 
1059     if ( avdatum )
1060     {
1061         /* Use the type from the type transition/member/change rule. */
1062         newcontext.type = avdatum->data;
1063     }
1064 
1065     /* Check for class-specific changes. */
1066     switch ( tclass )
1067     {
1068         case SECCLASS_DOMAIN:
1069             if ( specified & AVTAB_TRANSITION )
1070             {
1071                 /* Look for a role transition rule. */
1072                 for ( roletr = policydb.role_tr; roletr; roletr = roletr->next )
1073                 {
1074                     if ( roletr->role == scontext->role &&
1075                                             roletr->type == tcontext->type )
1076                     {
1077                         /* Use the role transition rule. */
1078                         newcontext.role = roletr->new_role;
1079                         break;
1080                     }
1081                 }
1082             }
1083         break;
1084         default:
1085         break;
1086     }
1087 
1088     /* Set the MLS attributes.
1089        This is done last because it may allocate memory. */
1090     rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
1091     if ( rc )
1092         goto out_unlock;
1093 
1094     /* Check the validity of the context. */
1095     if ( !policydb_context_isvalid(&policydb, &newcontext) )
1096     {
1097         rc = compute_sid_handle_invalid_context(scontext, tcontext, tclass,
1098                                                                 &newcontext);
1099         if ( rc )
1100             goto out_unlock;
1101     }
1102     /* Obtain the sid for the context. */
1103     rc = sidtab_context_to_sid(&sidtab, &newcontext, out_sid);
1104 out_unlock:
1105     POLICY_RDUNLOCK;
1106     context_destroy(&newcontext);
1107 out:
1108     return rc;
1109 }
1110 
1111 /**
1112  * security_transition_sid - Compute the SID for a new subject/object.
1113  * @ssid: source security identifier
1114  * @tsid: target security identifier
1115  * @tclass: target security class
1116  * @out_sid: security identifier for new subject/object
1117  *
1118  * Compute a SID to use for labeling a new subject or object in the
1119  * class @tclass based on a SID pair (@ssid, @tsid).
1120  * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1121  * if insufficient memory is available, or %0 if the new SID was
1122  * computed successfully.
1123  */
security_transition_sid(u32 ssid,u32 tsid,u16 tclass,u32 * out_sid)1124 int security_transition_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
1125 {
1126     return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid);
1127 }
1128 
1129 /**
1130  * security_member_sid - Compute the SID for member selection.
1131  * @ssid: source security identifier
1132  * @tsid: target security identifier
1133  * @tclass: target security class
1134  * @out_sid: security identifier for selected member
1135  *
1136  * Compute a SID to use when selecting a member of a polyinstantiated
1137  * object of class @tclass based on a SID pair (@ssid, @tsid).
1138  * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1139  * if insufficient memory is available, or %0 if the SID was
1140  * computed successfully.
1141  */
security_member_sid(u32 ssid,u32 tsid,u16 tclass,u32 * out_sid)1142 int security_member_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
1143 {
1144     return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid);
1145 }
1146 
1147 /**
1148  * security_change_sid - Compute the SID for object relabeling.
1149  * @ssid: source security identifier
1150  * @tsid: target security identifier
1151  * @tclass: target security class
1152  * @out_sid: security identifier for selected member
1153  *
1154  * Compute a SID to use for relabeling an object of class @tclass
1155  * based on a SID pair (@ssid, @tsid).
1156  * Return -%EINVAL if any of the parameters are invalid, -%ENOMEM
1157  * if insufficient memory is available, or %0 if the SID was
1158  * computed successfully.
1159  */
security_change_sid(u32 ssid,u32 tsid,u16 tclass,u32 * out_sid)1160 int security_change_sid(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
1161 {
1162     return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid);
1163 }
1164 
1165 /*
1166  * Verify that each kernel class that is defined in the
1167  * policy is correct
1168  */
validate_classes(struct policydb * p)1169 static int validate_classes(struct policydb *p)
1170 {
1171     int i;
1172     struct class_datum *cladatum;
1173     struct perm_datum *perdatum;
1174     u32 nprim, perm_val, pol_val;
1175     u16 class_val;
1176     const struct selinux_class_perm *kdefs = &selinux_class_perm;
1177     const char *def_class, *def_perm, *pol_class;
1178     struct symtab *perms;
1179 
1180     for ( i = 1; i < kdefs->cts_len; i++ )
1181     {
1182         def_class = kdefs->class_to_string[i];
1183         if ( !def_class )
1184             continue;
1185         if ( i > p->p_classes.nprim )
1186         {
1187             printk(KERN_INFO
1188                    "Flask:  class %s not defined in policy\n",
1189                    def_class);
1190             return -EINVAL;
1191         }
1192         pol_class = p->p_class_val_to_name[i-1];
1193         if ( strcmp(pol_class, def_class) )
1194         {
1195             printk(KERN_ERR
1196                    "Flask:  class %d is incorrect, found %s but should be %s\n",
1197                    i, pol_class, def_class);
1198             return -EINVAL;
1199         }
1200     }
1201     for ( i = 0; i < kdefs->av_pts_len; i++ )
1202     {
1203         class_val = kdefs->av_perm_to_string[i].tclass;
1204         perm_val = kdefs->av_perm_to_string[i].value;
1205         def_perm = kdefs->av_perm_to_string[i].name;
1206         if ( class_val > p->p_classes.nprim )
1207             continue;
1208         pol_class = p->p_class_val_to_name[class_val-1];
1209         cladatum = hashtab_search(p->p_classes.table, pol_class);
1210         BUG_ON( !cladatum );
1211         perms = &cladatum->permissions;
1212         nprim = 1 << (perms->nprim - 1);
1213         if ( perm_val > nprim )
1214         {
1215             printk(KERN_INFO
1216                    "Flask:  permission %s in class %s not defined in policy\n",
1217                    def_perm, pol_class);
1218             return -EINVAL;
1219         }
1220         perdatum = hashtab_search(perms->table, def_perm);
1221         if ( perdatum == NULL )
1222         {
1223             printk(KERN_ERR
1224                    "Flask:  permission %s in class %s not found in policy\n",
1225                    def_perm, pol_class);
1226             return -EINVAL;
1227         }
1228         pol_val = 1 << (perdatum->value - 1);
1229         if ( pol_val != perm_val )
1230         {
1231             printk(KERN_ERR
1232                    "Flask:  permission %s in class %s has incorrect value\n",
1233                    def_perm, pol_class);
1234             return -EINVAL;
1235         }
1236     }
1237     return 0;
1238 }
1239 
1240 /* Clone the SID into the new SID table. */
clone_sid(u32 sid,struct context * context,void * arg)1241 static int clone_sid(u32 sid, struct context *context, void *arg)
1242 {
1243     struct sidtab *s = arg;
1244 
1245     return sidtab_insert(s, sid, context);
1246 }
1247 
convert_context_handle_invalid_context(struct context * context)1248 static inline int convert_context_handle_invalid_context(struct context *context)
1249 {
1250     int rc = 0;
1251 
1252     if ( flask_enforcing )
1253         rc = -EINVAL;
1254     else
1255     {
1256         char *s;
1257         u32 len;
1258 
1259         context_struct_to_string(context, &s, &len);
1260         printk(KERN_ERR "Flask:  context %s is invalid\n", s);
1261         xfree(s);
1262     }
1263     return rc;
1264 }
1265 
1266 struct convert_context_args {
1267     struct policydb *oldp;
1268     struct policydb *newp;
1269 };
1270 
1271 /*
1272  * Convert the values in the security context
1273  * structure `c' from the values specified
1274  * in the policy `p->oldp' to the values specified
1275  * in the policy `p->newp'.  Verify that the
1276  * context is valid under the new policy.
1277  */
convert_context(u32 key,struct context * c,void * p)1278 static int convert_context(u32 key, struct context *c, void *p)
1279 {
1280     struct convert_context_args *args;
1281     struct context oldc;
1282     struct role_datum *role;
1283     struct type_datum *typdatum;
1284     struct user_datum *usrdatum;
1285     char *s;
1286     u32 len;
1287     int rc;
1288 
1289     args = p;
1290 
1291     rc = context_cpy(&oldc, c);
1292     if ( rc )
1293         goto out;
1294 
1295     rc = -EINVAL;
1296 
1297     /* Convert the user. */
1298     usrdatum = hashtab_search(args->newp->p_users.table,
1299                               args->oldp->p_user_val_to_name[c->user - 1]);
1300     if ( !usrdatum )
1301         goto bad;
1302 
1303     c->user = usrdatum->value;
1304 
1305     /* Convert the role. */
1306     role = hashtab_search(args->newp->p_roles.table,
1307                           args->oldp->p_role_val_to_name[c->role - 1]);
1308     if ( !role )
1309         goto bad;
1310 
1311     c->role = role->value;
1312 
1313     /* Convert the type. */
1314     typdatum = hashtab_search(args->newp->p_types.table,
1315                               args->oldp->p_type_val_to_name[c->type - 1]);
1316     if ( !typdatum )
1317         goto bad;
1318 
1319     c->type = typdatum->value;
1320 
1321     rc = mls_convert_context(args->oldp, args->newp, c);
1322     if ( rc )
1323         goto bad;
1324 
1325     /* Check the validity of the new context. */
1326     if ( !policydb_context_isvalid(args->newp, c) )
1327     {
1328         rc = convert_context_handle_invalid_context(&oldc);
1329         if ( rc )
1330             goto bad;
1331     }
1332 
1333     context_destroy(&oldc);
1334 out:
1335     return rc;
1336 bad:
1337     context_struct_to_string(&oldc, &s, &len);
1338     context_destroy(&oldc);
1339     printk(KERN_ERR "Flask:  invalidating context %s\n", s);
1340     xfree(s);
1341     goto out;
1342 }
1343 
1344 static int security_preserve_bools(struct policydb *p);
1345 
1346 /**
1347  * security_load_policy - Load a security policy configuration.
1348  * @data: binary policy data
1349  * @len: length of data in bytes
1350  *
1351  * Load a new set of security policy configuration data,
1352  * validate it and convert the SID table as necessary.
1353  * This function will flush the access vector cache after
1354  * loading the new policy.
1355  */
security_load_policy(const void * data,size_t len)1356 int security_load_policy(const void *data, size_t len)
1357 {
1358     struct policydb oldpolicydb, newpolicydb;
1359     struct sidtab oldsidtab, newsidtab;
1360     struct convert_context_args args;
1361     u32 seqno;
1362     int rc = 0;
1363     struct policy_file file = { data, len }, *fp = &file;
1364 
1365     LOAD_LOCK;
1366 
1367     if ( !ss_initialized )
1368     {
1369         if ( policydb_read(&policydb, fp) )
1370         {
1371             LOAD_UNLOCK;
1372             return -EINVAL;
1373         }
1374         if ( policydb_load_isids(&policydb, &sidtab) )
1375         {
1376             LOAD_UNLOCK;
1377             policydb_destroy(&policydb);
1378             return -EINVAL;
1379         }
1380         if ( validate_classes(&policydb) )
1381         {
1382             LOAD_UNLOCK;
1383             printk(KERN_ERR
1384                    "Flask:  the definition of a class is incorrect\n");
1385             sidtab_destroy(&sidtab);
1386             policydb_destroy(&policydb);
1387             return -EINVAL;
1388         }
1389         policydb_loaded_version = policydb.policyvers;
1390         ss_initialized = 1;
1391         seqno = ++latest_granting;
1392         LOAD_UNLOCK;
1393         avc_ss_reset(seqno);
1394         return 0;
1395     }
1396 
1397 #if 0
1398     sidtab_hash_eval(&sidtab, "sids");
1399 #endif
1400 
1401     if ( policydb_read(&newpolicydb, fp) )
1402     {
1403         LOAD_UNLOCK;
1404         return -EINVAL;
1405     }
1406 
1407     sidtab_init(&newsidtab);
1408 
1409     /* Verify that the kernel defined classes are correct. */
1410     if ( validate_classes(&newpolicydb) )
1411     {
1412         printk(KERN_ERR
1413                "Flask:  the definition of a class is incorrect\n");
1414         rc = -EINVAL;
1415         goto err;
1416     }
1417 
1418     rc = security_preserve_bools(&newpolicydb);
1419     if ( rc )
1420     {
1421         printk(KERN_ERR "Flask:  unable to preserve booleans\n");
1422         goto err;
1423     }
1424 
1425     /* Clone the SID table. */
1426     sidtab_shutdown(&sidtab);
1427     if ( sidtab_map(&sidtab, clone_sid, &newsidtab) )
1428     {
1429         rc = -ENOMEM;
1430         goto err;
1431     }
1432 
1433     /* Convert the internal representations of contexts
1434        in the new SID table and remove invalid SIDs. */
1435     args.oldp = &policydb;
1436     args.newp = &newpolicydb;
1437     sidtab_map_remove_on_error(&newsidtab, convert_context, &args);
1438 
1439     /* Save the old policydb and SID table to free later. */
1440     memcpy(&oldpolicydb, &policydb, sizeof policydb);
1441     sidtab_set(&oldsidtab, &sidtab);
1442 
1443     /* Install the new policydb and SID table. */
1444     POLICY_WRLOCK;
1445     memcpy(&policydb, &newpolicydb, sizeof policydb);
1446     sidtab_set(&sidtab, &newsidtab);
1447     seqno = ++latest_granting;
1448     policydb_loaded_version = policydb.policyvers;
1449     POLICY_WRUNLOCK;
1450     LOAD_UNLOCK;
1451 
1452     /* Free the old policydb and SID table. */
1453     policydb_destroy(&oldpolicydb);
1454     sidtab_destroy(&oldsidtab);
1455 
1456     avc_ss_reset(seqno);
1457 
1458     return 0;
1459 
1460 err:
1461     LOAD_UNLOCK;
1462     sidtab_destroy(&newsidtab);
1463     policydb_destroy(&newpolicydb);
1464     return rc;
1465 
1466 }
1467 
security_get_allow_unknown(void)1468 int security_get_allow_unknown(void)
1469 {
1470     return policydb.allow_unknown;
1471 }
1472 
1473 /**
1474  * security_irq_sid - Obtain the SID for a physical irq.
1475  * @pirq: physical irq
1476  * @out_sid: security identifier
1477  */
security_irq_sid(int pirq,u32 * out_sid)1478 int security_irq_sid(int pirq, u32 *out_sid)
1479 {
1480     int rc = 0;
1481     struct ocontext *c;
1482 
1483     POLICY_RDLOCK;
1484 
1485     c = policydb.ocontexts[OCON_PIRQ];
1486 
1487     while ( c )
1488     {
1489         if ( c->u.pirq == pirq )
1490             break;
1491         c = c->next;
1492     }
1493 
1494     if ( c )
1495     {
1496         if ( !c->sid )
1497         {
1498             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1499             if ( rc )
1500                 goto out;
1501         }
1502         *out_sid = c->sid;
1503     }
1504     else
1505     {
1506         *out_sid = SECINITSID_IRQ;
1507     }
1508 
1509 out:
1510     POLICY_RDUNLOCK;
1511     return rc;
1512 }
1513 
1514 /**
1515  * security_iomem_sid - Obtain the SID for a page of iomem.
1516  * @mfn: iomem mfn
1517  * @out_sid: security identifier
1518  */
security_iomem_sid(unsigned long mfn,u32 * out_sid)1519 int security_iomem_sid(unsigned long mfn, u32 *out_sid)
1520 {
1521     struct ocontext *c;
1522     int rc = 0;
1523 
1524     POLICY_RDLOCK;
1525 
1526     c = policydb.ocontexts[OCON_IOMEM];
1527     while ( c )
1528     {
1529         if ( c->u.iomem.low_iomem <= mfn  && c->u.iomem.high_iomem >= mfn )
1530             break;
1531         c = c->next;
1532     }
1533 
1534     if ( c )
1535     {
1536         if ( !c->sid )
1537         {
1538             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1539             if ( rc )
1540                 goto out;
1541         }
1542         *out_sid = c->sid;
1543     }
1544     else
1545     {
1546         *out_sid = SECINITSID_IOMEM;
1547     }
1548 
1549 out:
1550     POLICY_RDUNLOCK;
1551     return rc;
1552 }
1553 
security_iterate_iomem_sids(unsigned long start,unsigned long end,security_iterate_fn fn,void * data)1554 int security_iterate_iomem_sids(unsigned long start, unsigned long end,
1555                                 security_iterate_fn fn, void *data)
1556 {
1557     struct ocontext *c;
1558     int rc = 0;
1559 
1560     POLICY_RDLOCK;
1561 
1562     c = policydb.ocontexts[OCON_IOMEM];
1563     while (c && c->u.iomem.high_iomem < start)
1564         c = c->next;
1565 
1566     while (c && c->u.iomem.low_iomem <= end) {
1567         if (!c->sid)
1568         {
1569             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1570             if ( rc )
1571                 goto out;
1572         }
1573         if (start < c->u.iomem.low_iomem) {
1574             /* found a gap */
1575             rc = fn(data, SECINITSID_IOMEM, start, c->u.iomem.low_iomem - 1);
1576             if (rc)
1577                 goto out;
1578             start = c->u.iomem.low_iomem;
1579         }
1580         if (end <= c->u.iomem.high_iomem) {
1581             /* iteration ends in the middle of this range */
1582             rc = fn(data, c->sid, start, end);
1583             goto out;
1584         }
1585 
1586         rc = fn(data, c->sid, start, c->u.iomem.high_iomem);
1587         if (rc)
1588             goto out;
1589         start = c->u.iomem.high_iomem + 1;
1590 
1591         c = c->next;
1592     }
1593 
1594     rc = fn(data, SECINITSID_IOMEM, start, end);
1595 
1596 out:
1597     POLICY_RDUNLOCK;
1598     return rc;
1599 }
1600 
1601 /**
1602  * security_ioport_sid - Obtain the SID for an ioport.
1603  * @ioport: ioport
1604  * @out_sid: security identifier
1605  */
security_ioport_sid(u32 ioport,u32 * out_sid)1606 int security_ioport_sid(u32 ioport, u32 *out_sid)
1607 {
1608     struct ocontext *c;
1609     int rc = 0;
1610 
1611     POLICY_RDLOCK;
1612 
1613     c = policydb.ocontexts[OCON_IOPORT];
1614     while ( c )
1615     {
1616         if ( c->u.ioport.low_ioport <= ioport &&
1617              c->u.ioport.high_ioport >= ioport )
1618             break;
1619         c = c->next;
1620     }
1621 
1622     if ( c )
1623     {
1624         if ( !c->sid )
1625         {
1626             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1627             if ( rc )
1628                 goto out;
1629         }
1630         *out_sid = c->sid;
1631     }
1632     else
1633     {
1634         *out_sid = SECINITSID_IOPORT;
1635     }
1636 
1637 out:
1638     POLICY_RDUNLOCK;
1639     return rc;
1640 }
1641 
security_iterate_ioport_sids(u32 start,u32 end,security_iterate_fn fn,void * data)1642 int security_iterate_ioport_sids(u32 start, u32 end,
1643                                 security_iterate_fn fn, void *data)
1644 {
1645     struct ocontext *c;
1646     int rc = 0;
1647 
1648     POLICY_RDLOCK;
1649 
1650     c = policydb.ocontexts[OCON_IOPORT];
1651     while (c && c->u.ioport.high_ioport < start)
1652         c = c->next;
1653 
1654     while (c && c->u.ioport.low_ioport <= end) {
1655         if (!c->sid)
1656         {
1657             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1658             if ( rc )
1659                 goto out;
1660         }
1661         if (start < c->u.ioport.low_ioport) {
1662             /* found a gap */
1663             rc = fn(data, SECINITSID_IOPORT, start, c->u.ioport.low_ioport - 1);
1664             if (rc)
1665                 goto out;
1666             start = c->u.ioport.low_ioport;
1667         }
1668         if (end <= c->u.ioport.high_ioport) {
1669             /* iteration ends in the middle of this range */
1670             rc = fn(data, c->sid, start, end);
1671             goto out;
1672         }
1673 
1674         rc = fn(data, c->sid, start, c->u.ioport.high_ioport);
1675         if (rc)
1676             goto out;
1677         start = c->u.ioport.high_ioport + 1;
1678 
1679         c = c->next;
1680     }
1681 
1682     rc = fn(data, SECINITSID_IOPORT, start, end);
1683 
1684 out:
1685     POLICY_RDUNLOCK;
1686     return rc;
1687 }
1688 
1689 /**
1690  * security_device_sid - Obtain the SID for a PCI device.
1691  * @ioport: device
1692  * @out_sid: security identifier
1693  */
security_device_sid(u32 device,u32 * out_sid)1694 int security_device_sid(u32 device, u32 *out_sid)
1695 {
1696     struct ocontext *c;
1697     int rc = 0;
1698 
1699     POLICY_RDLOCK;
1700 
1701     c = policydb.ocontexts[OCON_DEVICE];
1702     while ( c )
1703     {
1704         if ( c->u.device == device )
1705             break;
1706         c = c->next;
1707     }
1708 
1709     if ( c )
1710     {
1711         if ( !c->sid )
1712         {
1713             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1714             if ( rc )
1715                 goto out;
1716         }
1717         *out_sid = c->sid;
1718     }
1719     else
1720     {
1721         *out_sid = SECINITSID_DEVICE;
1722     }
1723 
1724 out:
1725     POLICY_RDUNLOCK;
1726     return rc;
1727 }
1728 
security_devicetree_sid(const char * path,u32 * out_sid)1729 int security_devicetree_sid(const char *path, u32 *out_sid)
1730 {
1731     struct ocontext *c;
1732     int rc = 0;
1733 
1734     POLICY_RDLOCK;
1735 
1736     c = policydb.ocontexts[OCON_DTREE];
1737     while ( c )
1738     {
1739         if ( strcmp(c->u.name, path) == 0 )
1740             break;
1741         c = c->next;
1742     }
1743 
1744     if ( c )
1745     {
1746         if ( !c->sid )
1747         {
1748             rc = sidtab_context_to_sid(&sidtab, &c->context, &c->sid);
1749             if ( rc )
1750                 goto out;
1751         }
1752         *out_sid = c->sid;
1753     }
1754     else
1755     {
1756         *out_sid = SECINITSID_DEVICE;
1757     }
1758 
1759 out:
1760     POLICY_RDUNLOCK;
1761     return rc;
1762 }
1763 
security_find_bool(const char * name)1764 int security_find_bool(const char *name)
1765 {
1766     int i, rv = -ENOENT;
1767     POLICY_RDLOCK;
1768     for ( i = 0; i < policydb.p_bools.nprim; i++ )
1769     {
1770         if (!strcmp(name, policydb.p_bool_val_to_name[i]))
1771         {
1772             rv = i;
1773             break;
1774         }
1775     }
1776 
1777     POLICY_RDUNLOCK;
1778     return rv;
1779 }
1780 
security_get_bools(int * len,char *** names,int ** values,size_t * maxstr)1781 int security_get_bools(int *len, char ***names, int **values, size_t *maxstr)
1782 {
1783     int i, rc = -ENOMEM;
1784 
1785     POLICY_RDLOCK;
1786     if ( names )
1787         *names = NULL;
1788     *values = NULL;
1789     if ( maxstr )
1790         *maxstr = 0;
1791 
1792     *len = policydb.p_bools.nprim;
1793     if ( !*len )
1794     {
1795         rc = 0;
1796         goto out;
1797     }
1798 
1799     if ( names )
1800     {
1801         *names = xzalloc_array(char *, *len);
1802         if ( !*names )
1803             goto err;
1804     }
1805 
1806     *values = xmalloc_array(int, *len);
1807     if ( !*values )
1808         goto err;
1809 
1810     for ( i = 0; i < *len; i++ )
1811     {
1812         size_t name_len = strlen(policydb.p_bool_val_to_name[i]);
1813 
1814         (*values)[i] = policydb.bool_val_to_struct[i]->state;
1815         if ( names ) {
1816             (*names)[i] = xmalloc_array(char, name_len + 1);
1817             if ( !(*names)[i] )
1818                 goto err;
1819             strlcpy((*names)[i], policydb.p_bool_val_to_name[i], name_len + 1);
1820         }
1821         if ( maxstr && name_len > *maxstr )
1822             *maxstr = name_len;
1823     }
1824     rc = 0;
1825 out:
1826     POLICY_RDUNLOCK;
1827     return rc;
1828 err:
1829     if ( names && *names )
1830     {
1831         for ( i = 0; i < *len; i++ )
1832             xfree((*names)[i]);
1833         xfree(*names);
1834     }
1835     xfree(*values);
1836     goto out;
1837 }
1838 
1839 
security_set_bools(int len,int * values)1840 int security_set_bools(int len, int *values)
1841 {
1842     int i, rc = 0;
1843     int lenp, seqno = 0;
1844     struct cond_node *cur;
1845 
1846     POLICY_WRLOCK;
1847 
1848     lenp = policydb.p_bools.nprim;
1849     if ( len != lenp )
1850     {
1851         rc = -EFAULT;
1852         goto out;
1853     }
1854 
1855     printk(KERN_INFO "Flask: committed booleans { ");
1856     for ( i = 0; i < len; i++ )
1857     {
1858         if ( values[i] )
1859         {
1860             policydb.bool_val_to_struct[i]->state = 1;
1861         }
1862         else
1863         {
1864             policydb.bool_val_to_struct[i]->state = 0;
1865         }
1866         if ( i != 0 )
1867             printk(", ");
1868         printk("%s:%d", policydb.p_bool_val_to_name[i],
1869                policydb.bool_val_to_struct[i]->state);
1870     }
1871     printk(" }\n");
1872 
1873     for ( cur = policydb.cond_list; cur != NULL; cur = cur->next )
1874     {
1875         rc = evaluate_cond_node(&policydb, cur);
1876         if ( rc )
1877             goto out;
1878     }
1879 
1880     seqno = ++latest_granting;
1881 
1882 out:
1883     POLICY_WRUNLOCK;
1884     if ( !rc )
1885     {
1886         avc_ss_reset(seqno);
1887     }
1888     return rc;
1889 }
1890 
security_get_bool_value(unsigned int b)1891 int security_get_bool_value(unsigned int b)
1892 {
1893     int rc = 0;
1894     unsigned int len;
1895 
1896     POLICY_RDLOCK;
1897 
1898     len = policydb.p_bools.nprim;
1899     if ( b >= len )
1900     {
1901         rc = -ENOENT;
1902         goto out;
1903     }
1904 
1905     rc = policydb.bool_val_to_struct[b]->state;
1906 out:
1907     POLICY_RDUNLOCK;
1908     return rc;
1909 }
1910 
security_get_bool_name(unsigned int b)1911 char *security_get_bool_name(unsigned int b)
1912 {
1913     unsigned int len;
1914     char *rv = NULL;
1915 
1916     POLICY_RDLOCK;
1917 
1918     len = policydb.p_bools.nprim;
1919     if ( b >= len )
1920     {
1921         goto out;
1922     }
1923 
1924     len = strlen(policydb.p_bool_val_to_name[b]) + 1;
1925     rv = xmalloc_array(char, len);
1926     if ( !rv )
1927         goto out;
1928     memcpy(rv, policydb.p_bool_val_to_name[b], len);
1929 out:
1930     POLICY_RDUNLOCK;
1931     return rv;
1932 }
1933 
security_preserve_bools(struct policydb * p)1934 static int security_preserve_bools(struct policydb *p)
1935 {
1936     int rc, nbools = 0, *bvalues = NULL, i;
1937     char **bnames = NULL;
1938     struct cond_bool_datum *booldatum;
1939     struct cond_node *cur;
1940 
1941     rc = security_get_bools(&nbools, &bnames, &bvalues, NULL);
1942     if ( rc )
1943         return rc;
1944     for ( i = 0; i < nbools; i++ )
1945     {
1946         booldatum = hashtab_search(p->p_bools.table, bnames[i]);
1947         if ( booldatum )
1948             booldatum->state = bvalues[i];
1949     }
1950     for ( cur = p->cond_list; cur; cur = cur->next )
1951     {
1952         rc = evaluate_cond_node(p, cur);
1953         if ( rc )
1954             goto out;
1955     }
1956 
1957 out:
1958     if ( bnames )
1959     {
1960         for ( i = 0; i < nbools; i++ )
1961             xfree(bnames[i]);
1962     }
1963     xfree(bnames);
1964     xfree(bvalues);
1965     return rc;
1966 }
1967 
security_ocontext_add(u32 ocon,unsigned long low,unsigned long high,u32 sid)1968 int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high
1969                             ,u32 sid )
1970 {
1971     int ret = 0;
1972     struct ocontext *c;
1973     struct ocontext *prev;
1974     struct ocontext *add;
1975 
1976     if ( (add = xzalloc(struct ocontext)) == NULL )
1977         return -ENOMEM;
1978     add->sid = sid;
1979 
1980     POLICY_WRLOCK;
1981     switch( ocon )
1982     {
1983     case OCON_PIRQ:
1984         add->u.pirq = (u16)low;
1985         if ( high != low )
1986         {
1987             ret = -EINVAL;
1988             break;
1989         }
1990 
1991         c = policydb.ocontexts[OCON_PIRQ];
1992         while ( c )
1993         {
1994             if ( c->u.pirq == add->u.pirq )
1995             {
1996                 if ( c->sid == sid )
1997                     break;
1998                 printk("flask: Duplicate pirq %d\n", add->u.pirq);
1999                 ret = -EEXIST;
2000                 break;
2001             }
2002             c = c->next;
2003         }
2004 
2005         if ( ret == 0 )
2006         {
2007             add->next = policydb.ocontexts[OCON_PIRQ];
2008             policydb.ocontexts[OCON_PIRQ] = add;
2009         }
2010         break;
2011 
2012     case OCON_IOPORT:
2013         add->u.ioport.low_ioport = low;
2014         add->u.ioport.high_ioport = high;
2015 
2016         prev = NULL;
2017         c = policydb.ocontexts[OCON_IOPORT];
2018 
2019         while ( c && c->u.ioport.high_ioport < low ) {
2020             prev = c;
2021             c = c->next;
2022         }
2023 
2024         if (c && c->u.ioport.low_ioport <= high)
2025         {
2026             if (c->u.ioport.low_ioport == low &&
2027                 c->u.ioport.high_ioport == high && c->sid == sid)
2028                 break;
2029 
2030             printk("flask: IO Port overlap with entry %#x - %#x\n",
2031                    c->u.ioport.low_ioport, c->u.ioport.high_ioport);
2032             ret = -EEXIST;
2033             break;
2034         }
2035 
2036         if (prev) {
2037             add->next = prev->next;
2038             prev->next = add;
2039         } else {
2040             add->next = policydb.ocontexts[OCON_IOPORT];
2041             policydb.ocontexts[OCON_IOPORT] = add;
2042         }
2043         break;
2044 
2045     case OCON_IOMEM:
2046         add->u.iomem.low_iomem = low;
2047         add->u.iomem.high_iomem = high;
2048 
2049         prev = NULL;
2050         c = policydb.ocontexts[OCON_IOMEM];
2051 
2052         while ( c && c->u.iomem.high_iomem < low ) {
2053             prev = c;
2054             c = c->next;
2055         }
2056 
2057         if (c && c->u.iomem.low_iomem <= high)
2058         {
2059             if (c->u.iomem.low_iomem == low &&
2060                 c->u.iomem.high_iomem == high && c->sid == sid)
2061                 break;
2062 
2063             printk("flask: IO Memory overlap with entry %#"PRIx64" - %#"PRIx64"\n",
2064                    c->u.iomem.low_iomem, c->u.iomem.high_iomem);
2065             ret = -EEXIST;
2066             break;
2067         }
2068 
2069         if (prev) {
2070             add->next = prev->next;
2071             prev->next = add;
2072         } else {
2073             add->next = policydb.ocontexts[OCON_IOMEM];
2074             policydb.ocontexts[OCON_IOMEM] = add;
2075         }
2076         break;
2077 
2078      case OCON_DEVICE:
2079         add->u.device = low;
2080         if ( high != low )
2081         {
2082             ret = -EINVAL;
2083             break;
2084         }
2085 
2086         c = policydb.ocontexts[OCON_DEVICE];
2087         while ( c )
2088         {
2089             if ( c->u.device == add->u.device )
2090             {
2091                 if ( c->sid == sid )
2092                     break;
2093 
2094                 printk("flask: Duplicate PCI Device %#x\n", add->u.device);
2095                 ret = -EEXIST;
2096                 break;
2097             }
2098             c = c->next;
2099         }
2100 
2101         if ( ret == 0 )
2102         {
2103             add->next = policydb.ocontexts[OCON_DEVICE];
2104             policydb.ocontexts[OCON_DEVICE] = add;
2105         }
2106         break;
2107 
2108      default:
2109          ret = -EINVAL;
2110     }
2111     POLICY_WRUNLOCK;
2112 
2113     if ( ret != 0 )
2114         xfree(add);
2115     return ret;
2116 }
2117 
security_ocontext_del(u32 ocon,unsigned long low,unsigned long high)2118 int security_ocontext_del( u32 ocon, unsigned long low, unsigned long high )
2119 {
2120     int ret = 0;
2121     struct ocontext *c, *before_c;
2122 
2123     POLICY_WRLOCK;
2124     switch( ocon )
2125     {
2126     case OCON_PIRQ:
2127         for ( before_c = NULL, c = policydb.ocontexts[OCON_PIRQ];
2128               c; before_c = c, c = c->next )
2129         {
2130             if ( c->u.pirq == low )
2131             {
2132                 if ( before_c == NULL )
2133                 {
2134                     policydb.ocontexts[OCON_PIRQ] = c->next;
2135                     xfree(c);
2136                     goto out;
2137                 }
2138                 else
2139                 {
2140                     before_c->next = c->next;
2141                     xfree(c);
2142                     goto out;
2143                 }
2144             }
2145         }
2146 
2147         printk("flask: ocontext not found: pirq %ld\n", low);
2148         ret = -ENOENT;
2149         break;
2150 
2151     case OCON_IOPORT:
2152         for ( before_c = NULL, c = policydb.ocontexts[OCON_IOPORT];
2153               c; before_c = c, c = c->next )
2154         {
2155             if ( c->u.ioport.low_ioport == low &&
2156                  c->u.ioport.high_ioport == high )
2157             {
2158                 if ( before_c == NULL )
2159                 {
2160                     policydb.ocontexts[OCON_IOPORT] = c->next;
2161                     xfree(c);
2162                     goto out;
2163                 }
2164                 else
2165                 {
2166                     before_c->next = c->next;
2167                     xfree(c);
2168                     goto out;
2169                 }
2170             }
2171         }
2172 
2173         printk("flask: ocontext not found: ioport %#lx - %#lx\n", low, high);
2174         ret = -ENOENT;
2175         break;
2176 
2177     case OCON_IOMEM:
2178         for ( before_c = NULL, c = policydb.ocontexts[OCON_IOMEM];
2179               c; before_c = c, c = c->next )
2180         {
2181             if ( c->u.iomem.low_iomem == low &&
2182                  c->u.iomem.high_iomem == high )
2183             {
2184                 if ( before_c == NULL )
2185                 {
2186                     policydb.ocontexts[OCON_IOMEM] = c->next;
2187                     xfree(c);
2188                     goto out;
2189                 }
2190                 else
2191                 {
2192                     before_c->next = c->next;
2193                     xfree(c);
2194                     goto out;
2195                 }
2196             }
2197         }
2198 
2199         printk("flask: ocontext not found: iomem %#lx - %#lx\n", low, high);
2200         ret = -ENOENT;
2201         break;
2202 
2203     case OCON_DEVICE:
2204         for ( before_c = NULL, c = policydb.ocontexts[OCON_DEVICE];
2205               c; before_c = c, c = c->next )
2206         {
2207             if ( c->u.device == low )
2208             {
2209                 if ( before_c == NULL )
2210                 {
2211                     policydb.ocontexts[OCON_DEVICE] = c->next;
2212                     xfree(c);
2213                     goto out;
2214                 }
2215                 else
2216                 {
2217                     before_c->next = c->next;
2218                     xfree(c);
2219                     goto out;
2220                 }
2221             }
2222         }
2223 
2224         printk("flask: ocontext not found: pcidevice %#lx\n", low);
2225         ret = -ENOENT;
2226         break;
2227 
2228     default:
2229         ret = -EINVAL;
2230     }
2231 
2232   out:
2233     POLICY_WRUNLOCK;
2234     return ret;
2235 }
2236 
security_devicetree_setlabel(char * path,u32 sid)2237 int security_devicetree_setlabel(char *path, u32 sid)
2238 {
2239     int ret = 0;
2240     struct ocontext *c;
2241     struct ocontext **pcurr;
2242     struct ocontext *add = NULL;
2243 
2244     if ( sid )
2245     {
2246         add = xzalloc(struct ocontext);
2247         if ( add == NULL )
2248         {
2249             xfree(path);
2250             return -ENOMEM;
2251         }
2252         add->sid = sid;
2253         add->u.name = path;
2254     }
2255     else
2256     {
2257         ret = -ENOENT;
2258     }
2259 
2260     POLICY_WRLOCK;
2261 
2262     pcurr = &policydb.ocontexts[OCON_DTREE];
2263     c = *pcurr;
2264     while ( c )
2265     {
2266         if ( strcmp(c->u.name, path) == 0 )
2267         {
2268             if ( sid )
2269             {
2270                 ret = -EEXIST;
2271                 break;
2272             }
2273             else
2274             {
2275                 *pcurr = c->next;
2276                 xfree(c->u.name);
2277                 xfree(c);
2278                 ret = 0;
2279                 break;
2280             }
2281         }
2282         pcurr = &c->next;
2283         c = *pcurr;
2284     }
2285 
2286     if ( add && ret == 0 )
2287     {
2288         add->next = policydb.ocontexts[OCON_DTREE];
2289         policydb.ocontexts[OCON_DTREE] = add;
2290         add = NULL;
2291         path = NULL;
2292     }
2293 
2294     POLICY_WRUNLOCK;
2295 
2296     xfree(add);
2297     xfree(path);
2298     return ret;
2299 }
2300