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
);