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)
407 buf = next_entry(fp, sizeof(u32));
410 perdatum->base_perms = le32_to_cpu(buf[0]);
415 * Read a MLS level structure from a policydb binary
416 * representation file.
418 struct mls_level *mls_read_level(void *fp)
423 l = kmalloc(sizeof(*l), GFP_ATOMIC);
425 printk(KERN_ERR "security: mls: out of memory\n");
428 memset(l, 0, sizeof(*l));
430 buf = next_entry(fp, sizeof(u32));
432 printk(KERN_ERR "security: mls: truncated level\n");
435 l->sens = cpu_to_le32(buf[0]);
437 if (ebitmap_read(&l->cat, fp)) {
438 printk(KERN_ERR "security: mls: error reading level "
451 * Read a MLS range structure from a policydb binary
452 * representation file.
454 static int mls_read_range_helper(struct mls_range *r, void *fp)
457 int items, rc = -EINVAL;
459 buf = next_entry(fp, sizeof(u32));
463 items = le32_to_cpu(buf[0]);
464 buf = next_entry(fp, sizeof(u32) * items);
466 printk(KERN_ERR "security: mls: truncated range\n");
469 r->level[0].sens = le32_to_cpu(buf[0]);
471 r->level[1].sens = le32_to_cpu(buf[1]);
473 r->level[1].sens = r->level[0].sens;
476 rc = ebitmap_read(&r->level[0].cat, fp);
478 printk(KERN_ERR "security: mls: error reading low "
483 rc = ebitmap_read(&r->level[1].cat, fp);
485 printk(KERN_ERR "security: mls: error reading high "
490 rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
492 printk(KERN_ERR "security: mls: out of memory\n");
501 ebitmap_destroy(&r->level[0].cat);
505 int mls_read_range(struct context *c, void *fp)
507 return mls_read_range_helper(&c->range, fp);
512 * Read a MLS perms structure from a policydb binary
513 * representation file.
515 int mls_read_class(struct class_datum *cladatum, void *fp)
517 struct mls_perms *p = &cladatum->mlsperms;
520 buf = next_entry(fp, sizeof(u32)*4);
522 printk(KERN_ERR "security: mls: truncated mls permissions\n");
525 p->read = le32_to_cpu(buf[0]);
526 p->readby = le32_to_cpu(buf[1]);
527 p->write = le32_to_cpu(buf[2]);
528 p->writeby = le32_to_cpu(buf[3]);
532 int mls_read_user(struct user_datum *usrdatum, void *fp)
534 struct mls_range_list *r, *l;
539 buf = next_entry(fp, sizeof(u32));
544 nel = le32_to_cpu(buf[0]);
546 for (i = 0; i < nel; i++) {
547 r = kmalloc(sizeof(*r), GFP_ATOMIC);
552 memset(r, 0, sizeof(*r));
554 rc = mls_read_range_helper(&r->range, fp);
563 usrdatum->ranges = r;
570 int mls_read_nlevels(struct policydb *p, void *fp)
574 buf = next_entry(fp, sizeof(u32));
577 p->nlevels = le32_to_cpu(buf[0]);
581 int mls_read_trusted(struct policydb *p, void *fp)
585 rc = ebitmap_read(&p->trustedreaders, fp);
588 rc = ebitmap_read(&p->trustedwriters, fp);
591 rc = ebitmap_read(&p->trustedobjects, fp);
597 ebitmap_destroy(&p->trustedwriters);
599 ebitmap_destroy(&p->trustedreaders);
603 int sens_index(void *key, void *datum, void *datap)
606 struct level_datum *levdatum;
612 if (!levdatum->isalias)
613 p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
618 int cat_index(void *key, void *datum, void *datap)
621 struct cat_datum *catdatum;
628 if (!catdatum->isalias)
629 p->p_cat_val_to_name[catdatum->value - 1] = key;
634 int sens_destroy(void *key, void *datum, void *p)
636 struct level_datum *levdatum;
640 if (!levdatum->isalias) {
641 ebitmap_destroy(&levdatum->level->cat);
642 kfree(levdatum->level);
648 int cat_destroy(void *key, void *datum, void *p)
655 int sens_read(struct policydb *p, struct hashtab *h, void *fp)
658 struct level_datum *levdatum;
662 levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
667 memset(levdatum, 0, sizeof(*levdatum));
669 buf = next_entry(fp, sizeof(u32)*2);
675 len = le32_to_cpu(buf[0]);
676 levdatum->isalias = le32_to_cpu(buf[1]);
678 buf = next_entry(fp, len);
683 key = kmalloc(len + 1,GFP_ATOMIC);
688 memcpy(key, buf, len);
691 levdatum->level = mls_read_level(fp);
692 if (!levdatum->level) {
697 rc = hashtab_insert(h, key, levdatum);
703 sens_destroy(key, levdatum, NULL);
708 int cat_read(struct policydb *p, struct hashtab *h, void *fp)
711 struct cat_datum *catdatum;
715 catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
720 memset(catdatum, 0, sizeof(*catdatum));
722 buf = next_entry(fp, sizeof(u32)*3);
728 len = le32_to_cpu(buf[0]);
729 catdatum->value = le32_to_cpu(buf[1]);
730 catdatum->isalias = le32_to_cpu(buf[2]);
732 buf = next_entry(fp, len);
737 key = kmalloc(len + 1,GFP_ATOMIC);
742 memcpy(key, buf, len);
745 rc = hashtab_insert(h, key, catdatum);
752 cat_destroy(key, catdatum, NULL);