2 * Implementation of the multi-level security (MLS) policy.
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
6 #include <linux/kernel.h>
7 #include <linux/slab.h>
8 #include <linux/string.h>
9 #include <linux/errno.h>
15 * Remove any permissions from `allowed' that are
16 * denied by the MLS policy.
18 void mls_compute_av(struct context *scontext,
19 struct context *tcontext,
20 struct class_datum *tclass,
26 for (l = 0; l < 2; l++)
27 rel[l] = mls_level_relation(scontext->range.level[l],
28 tcontext->range.level[l]);
30 if (rel[1] != MLS_RELATION_EQ) {
31 if (rel[1] != MLS_RELATION_DOM &&
32 !ebitmap_get_bit(&policydb.trustedreaders, scontext->type - 1) &&
33 !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
34 /* read(s,t) = (s.high >= t.high) = False */
35 *allowed = (*allowed) & ~(tclass->mlsperms.read);
37 if (rel[1] != MLS_RELATION_DOMBY &&
38 !ebitmap_get_bit(&policydb.trustedreaders, tcontext->type - 1) &&
39 !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
40 /* readby(s,t) = read(t,s) = False */
41 *allowed = (*allowed) & ~(tclass->mlsperms.readby);
44 if (((rel[0] != MLS_RELATION_DOMBY && rel[0] != MLS_RELATION_EQ) ||
45 ((!mls_level_eq(tcontext->range.level[0],
46 tcontext->range.level[1])) &&
47 (rel[1] != MLS_RELATION_DOM && rel[1] != MLS_RELATION_EQ))) &&
48 !ebitmap_get_bit(&policydb.trustedwriters, scontext->type - 1) &&
49 !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
51 * write(s,t) = ((s.low <= t.low = t.high) or (s.low
52 * <= t.low <= t.high <= s.high)) = False
54 *allowed = (*allowed) & ~(tclass->mlsperms.write);
57 if (((rel[0] != MLS_RELATION_DOM && rel[0] != MLS_RELATION_EQ) ||
58 ((!mls_level_eq(scontext->range.level[0],
59 scontext->range.level[1])) &&
60 (rel[1] != MLS_RELATION_DOMBY && rel[1] != MLS_RELATION_EQ))) &&
61 !ebitmap_get_bit(&policydb.trustedwriters, tcontext->type - 1) &&
62 !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
63 /* writeby(s,t) = write(t,s) = False */
64 *allowed = (*allowed) & ~(tclass->mlsperms.writeby);
69 * Return the length in bytes for the MLS fields of the
70 * security context string representation of `context'.
72 int mls_compute_context_len(struct context * context)
78 for (l = 0; l < 2; l++) {
79 len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]) + 1;
81 for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
82 if (ebitmap_get_bit(&context->range.level[l].cat, i - 1))
83 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
85 if (mls_level_relation(context->range.level[0], context->range.level[1])
94 * Write the security context string representation of
95 * the MLS fields of `context' into the string `*scontext'.
96 * Update `*scontext' to point to the end of the MLS fields.
98 int mls_sid_to_context(struct context *context,
104 scontextp = *scontext;
106 for (l = 0; l < 2; l++) {
108 policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
109 scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
112 for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
113 if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
114 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
115 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
119 if (mls_level_relation(context->range.level[0], context->range.level[1])
120 != MLS_RELATION_EQ) {
122 sprintf(scontextp, "-");
130 *scontext = scontextp;
135 * Return 1 if the MLS fields in the security context
136 * structure `c' are valid. Return 0 otherwise.
138 int mls_context_isvalid(struct policydb *p, struct context *c)
140 unsigned int relation;
141 struct level_datum *levdatum;
142 struct user_datum *usrdatum;
143 struct mls_range_list *rnode;
147 * MLS range validity checks: high must dominate low, low level must
148 * be valid (category set <-> sensitivity check), and high level must
149 * be valid (category set <-> sensitivity check)
151 relation = mls_level_relation(c->range.level[1],
153 if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ)))
154 /* High does not dominate low. */
157 for (l = 0; l < 2; l++) {
158 if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim)
160 levdatum = hashtab_search(p->p_levels.table,
161 p->p_sens_val_to_name[c->range.level[l].sens - 1]);
165 for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
166 if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
167 if (i > p->p_cats.nprim)
169 if (!ebitmap_get_bit(&levdatum->level->cat, i - 1))
171 * Category may not be associated with
172 * sensitivity in low level.
179 if (c->role == OBJECT_R_VAL)
183 * User must be authorized for the MLS range.
185 if (!c->user || c->user > p->p_users.nprim)
187 usrdatum = p->user_val_to_struct[c->user - 1];
188 for (rnode = usrdatum->ranges; rnode; rnode = rnode->next) {
189 if (mls_range_contains(rnode->range, c->range))
193 /* user may not be associated with range */
201 * Set the MLS fields in the security context structure
202 * `context' based on the string representation in
203 * the string `*scontext'. Update `*scontext' to
204 * point to the end of the string representation of
207 * This function modifies the string in place, inserting
208 * NULL characters to terminate the MLS fields.
210 int mls_context_to_sid(char oldc,
212 struct context *context)
217 struct level_datum *levdatum;
218 struct cat_datum *catdatum;
222 /* No MLS component to the security context. Try
223 to use a default 'unclassified' value. */
224 levdatum = hashtab_search(policydb.p_levels.table,
228 context->range.level[0].sens = levdatum->level->sens;
229 context->range.level[1].sens = context->range.level[0].sens;
234 /* Extract low sensitivity. */
235 scontextp = p = *scontext;
236 while (*p && *p != ':' && *p != '-')
243 for (l = 0; l < 2; l++) {
244 levdatum = hashtab_search(policydb.p_levels.table, scontextp);
248 context->range.level[l].sens = levdatum->level->sens;
251 /* Extract low category set. */
254 while (*p && *p != ',' && *p != '-')
260 catdatum = hashtab_search(policydb.p_cats.table,
265 rc = ebitmap_set_bit(&context->range.level[l].cat,
266 catdatum->value - 1, 1);
274 /* Extract high sensitivity. */
276 while (*p && *p != ':')
287 context->range.level[1].sens = context->range.level[0].sens;
288 rc = ebitmap_cpy(&context->range.level[1].cat,
289 &context->range.level[0].cat);
300 * Copies the MLS range from `src' into `dst'.
302 static inline int mls_copy_context(struct context *dst,
307 /* Copy the MLS range from the source context */
308 for (l = 0; l < 2; l++) {
310 dst->range.level[l].sens = src->range.level[l].sens;
311 rc = ebitmap_cpy(&dst->range.level[l].cat,
312 &src->range.level[l].cat);
321 * Convert the MLS fields in the security context
322 * structure `c' from the values specified in the
323 * policy `oldp' to the values specified in the policy `newp'.
325 int mls_convert_context(struct policydb *oldp,
326 struct policydb *newp,
329 struct level_datum *levdatum;
330 struct cat_datum *catdatum;
331 struct ebitmap bitmap;
334 for (l = 0; l < 2; l++) {
335 levdatum = hashtab_search(newp->p_levels.table,
336 oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
340 c->range.level[l].sens = levdatum->level->sens;
342 ebitmap_init(&bitmap);
343 for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) {
344 if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) {
347 catdatum = hashtab_search(newp->p_cats.table,
348 oldp->p_cat_val_to_name[i - 1]);
351 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
356 ebitmap_destroy(&c->range.level[l].cat);
357 c->range.level[l].cat = bitmap;
363 int mls_compute_sid(struct context *scontext,
364 struct context *tcontext,
367 struct context *newcontext)
370 case AVTAB_TRANSITION:
372 /* Use the process MLS attributes. */
373 return mls_copy_context(newcontext, scontext);
375 /* Only polyinstantiate the MLS attributes if
376 the type is being polyinstantiated */
377 if (newcontext->type != tcontext->type) {
378 /* Use the process MLS attributes. */
379 return mls_copy_context(newcontext, scontext);
381 /* Use the related object MLS attributes. */
382 return mls_copy_context(newcontext, tcontext);
390 void mls_user_destroy(struct user_datum *usrdatum)
392 struct mls_range_list *rnode, *rtmp;
393 rnode = usrdatum->ranges;
397 ebitmap_destroy(&rtmp->range.level[0].cat);
398 ebitmap_destroy(&rtmp->range.level[1].cat);
403 int mls_read_perm(struct perm_datum *perdatum, void *fp)
408 rc = next_entry(buf, fp, sizeof buf);
411 perdatum->base_perms = le32_to_cpu(buf[0]);
416 * Read a MLS level structure from a policydb binary
417 * representation file.
419 struct mls_level *mls_read_level(void *fp)
425 l = kmalloc(sizeof(*l), GFP_ATOMIC);
427 printk(KERN_ERR "security: mls: out of memory\n");
430 memset(l, 0, sizeof(*l));
432 rc = next_entry(buf, fp, sizeof buf);
434 printk(KERN_ERR "security: mls: truncated level\n");
437 l->sens = cpu_to_le32(buf[0]);
439 if (ebitmap_read(&l->cat, fp)) {
440 printk(KERN_ERR "security: mls: error reading level "
453 * Read a MLS range structure from a policydb binary
454 * representation file.
456 static int mls_read_range_helper(struct mls_range *r, void *fp)
461 rc = next_entry(buf, fp, sizeof(u32));
465 items = le32_to_cpu(buf[0]);
466 if (items > ARRAY_SIZE(buf)) {
467 printk(KERN_ERR "security: mls: range overflow\n");
471 rc = next_entry(buf, fp, sizeof(u32) * items);
473 printk(KERN_ERR "security: mls: truncated range\n");
476 r->level[0].sens = le32_to_cpu(buf[0]);
478 r->level[1].sens = le32_to_cpu(buf[1]);
480 r->level[1].sens = r->level[0].sens;
483 rc = ebitmap_read(&r->level[0].cat, fp);
485 printk(KERN_ERR "security: mls: error reading low "
490 rc = ebitmap_read(&r->level[1].cat, fp);
492 printk(KERN_ERR "security: mls: error reading high "
497 rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
499 printk(KERN_ERR "security: mls: out of memory\n");
508 ebitmap_destroy(&r->level[0].cat);
512 int mls_read_range(struct context *c, void *fp)
514 return mls_read_range_helper(&c->range, fp);
519 * Read a MLS perms structure from a policydb binary
520 * representation file.
522 int mls_read_class(struct class_datum *cladatum, void *fp)
524 struct mls_perms *p = &cladatum->mlsperms;
528 rc = next_entry(buf, fp, sizeof buf);
530 printk(KERN_ERR "security: mls: truncated mls permissions\n");
533 p->read = le32_to_cpu(buf[0]);
534 p->readby = le32_to_cpu(buf[1]);
535 p->write = le32_to_cpu(buf[2]);
536 p->writeby = le32_to_cpu(buf[3]);
540 int mls_read_user(struct user_datum *usrdatum, void *fp)
542 struct mls_range_list *r, *l;
547 rc = next_entry(buf, fp, sizeof buf);
550 nel = le32_to_cpu(buf[0]);
552 for (i = 0; i < nel; i++) {
553 r = kmalloc(sizeof(*r), GFP_ATOMIC);
558 memset(r, 0, sizeof(*r));
560 rc = mls_read_range_helper(&r->range, fp);
569 usrdatum->ranges = r;
576 int mls_read_nlevels(struct policydb *p, void *fp)
581 rc = next_entry(buf, fp, sizeof buf);
584 p->nlevels = le32_to_cpu(buf[0]);
588 int mls_read_trusted(struct policydb *p, void *fp)
592 rc = ebitmap_read(&p->trustedreaders, fp);
595 rc = ebitmap_read(&p->trustedwriters, fp);
598 rc = ebitmap_read(&p->trustedobjects, fp);
604 ebitmap_destroy(&p->trustedwriters);
606 ebitmap_destroy(&p->trustedreaders);
610 int sens_index(void *key, void *datum, void *datap)
613 struct level_datum *levdatum;
619 if (!levdatum->isalias)
620 p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
625 int cat_index(void *key, void *datum, void *datap)
628 struct cat_datum *catdatum;
635 if (!catdatum->isalias)
636 p->p_cat_val_to_name[catdatum->value - 1] = key;
641 int sens_destroy(void *key, void *datum, void *p)
643 struct level_datum *levdatum;
647 if (!levdatum->isalias) {
648 ebitmap_destroy(&levdatum->level->cat);
649 kfree(levdatum->level);
655 int cat_destroy(void *key, void *datum, void *p)
662 int sens_read(struct policydb *p, struct hashtab *h, void *fp)
665 struct level_datum *levdatum;
669 levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
674 memset(levdatum, 0, sizeof(*levdatum));
676 rc = next_entry(buf, fp, sizeof buf);
680 len = le32_to_cpu(buf[0]);
681 levdatum->isalias = le32_to_cpu(buf[1]);
683 key = kmalloc(len + 1,GFP_ATOMIC);
688 rc = next_entry(key, fp, len);
693 levdatum->level = mls_read_level(fp);
694 if (!levdatum->level) {
699 rc = hashtab_insert(h, key, levdatum);
705 sens_destroy(key, levdatum, NULL);
710 int cat_read(struct policydb *p, struct hashtab *h, void *fp)
713 struct cat_datum *catdatum;
717 catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
722 memset(catdatum, 0, sizeof(*catdatum));
724 rc = next_entry(buf, fp, sizeof buf);
728 len = le32_to_cpu(buf[0]);
729 catdatum->value = le32_to_cpu(buf[1]);
730 catdatum->isalias = le32_to_cpu(buf[2]);
732 key = kmalloc(len + 1,GFP_ATOMIC);
737 rc = next_entry(key, fp, len);
742 rc = hashtab_insert(h, key, catdatum);
749 cat_destroy(key, catdatum, NULL);