]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 LT |
2 | /* |
3 | * Implementation of the multi-level security (MLS) policy. | |
4 | * | |
7efbb60b | 5 | * Author : Stephen Smalley, <[email protected]> |
1da177e4 LT |
6 | */ |
7 | /* | |
8 | * Updated: Trusted Computer Solutions, Inc. <[email protected]> | |
9 | * | |
10 | * Support for enhanced MLS infrastructure. | |
11 | * | |
376bd9cb | 12 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
1da177e4 | 13 | */ |
7420ed23 | 14 | /* |
82c21bfa | 15 | * Updated: Hewlett-Packard <[email protected]> |
7420ed23 | 16 | * |
02752760 | 17 | * Added support to import/export the MLS label from NetLabel |
7420ed23 VY |
18 | * |
19 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | |
20 | */ | |
1da177e4 LT |
21 | |
22 | #include <linux/kernel.h> | |
23 | #include <linux/slab.h> | |
24 | #include <linux/string.h> | |
25 | #include <linux/errno.h> | |
02752760 | 26 | #include <net/netlabel.h> |
f5c1d5b2 | 27 | #include "sidtab.h" |
1da177e4 LT |
28 | #include "mls.h" |
29 | #include "policydb.h" | |
30 | #include "services.h" | |
31 | ||
32 | /* | |
33 | * Return the length in bytes for the MLS fields of the | |
34 | * security context string representation of `context'. | |
35 | */ | |
aa8e712c | 36 | int mls_compute_context_len(struct policydb *p, struct context *context) |
1da177e4 | 37 | { |
9fe79ad1 KK |
38 | int i, l, len, head, prev; |
39 | char *nm; | |
40 | struct ebitmap *e; | |
782ebb99 | 41 | struct ebitmap_node *node; |
1da177e4 | 42 | |
aa8e712c | 43 | if (!p->mls_enabled) |
1da177e4 LT |
44 | return 0; |
45 | ||
46 | len = 1; /* for the beginning ":" */ | |
47 | for (l = 0; l < 2; l++) { | |
9fe79ad1 | 48 | int index_sens = context->range.level[l].sens; |
aa8e712c | 49 | len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1)); |
1da177e4 | 50 | |
9fe79ad1 KK |
51 | /* categories */ |
52 | head = -2; | |
53 | prev = -2; | |
54 | e = &context->range.level[l].cat; | |
55 | ebitmap_for_each_positive_bit(e, node, i) { | |
56 | if (i - prev > 1) { | |
57 | /* one or more negative bits are skipped */ | |
58 | if (head != prev) { | |
aa8e712c | 59 | nm = sym_name(p, SYM_CATS, prev); |
9fe79ad1 KK |
60 | len += strlen(nm) + 1; |
61 | } | |
aa8e712c | 62 | nm = sym_name(p, SYM_CATS, i); |
9fe79ad1 KK |
63 | len += strlen(nm) + 1; |
64 | head = i; | |
1da177e4 | 65 | } |
9fe79ad1 KK |
66 | prev = i; |
67 | } | |
68 | if (prev != head) { | |
aa8e712c | 69 | nm = sym_name(p, SYM_CATS, prev); |
9fe79ad1 | 70 | len += strlen(nm) + 1; |
1da177e4 | 71 | } |
1da177e4 LT |
72 | if (l == 0) { |
73 | if (mls_level_eq(&context->range.level[0], | |
9fe79ad1 | 74 | &context->range.level[1])) |
1da177e4 LT |
75 | break; |
76 | else | |
77 | len++; | |
78 | } | |
79 | } | |
80 | ||
81 | return len; | |
82 | } | |
83 | ||
84 | /* | |
85 | * Write the security context string representation of | |
86 | * the MLS fields of `context' into the string `*scontext'. | |
87 | * Update `*scontext' to point to the end of the MLS fields. | |
88 | */ | |
aa8e712c SS |
89 | void mls_sid_to_context(struct policydb *p, |
90 | struct context *context, | |
1a5e6f87 | 91 | char **scontext) |
1da177e4 | 92 | { |
9fe79ad1 KK |
93 | char *scontextp, *nm; |
94 | int i, l, head, prev; | |
95 | struct ebitmap *e; | |
782ebb99 | 96 | struct ebitmap_node *node; |
1da177e4 | 97 | |
aa8e712c | 98 | if (!p->mls_enabled) |
1da177e4 LT |
99 | return; |
100 | ||
101 | scontextp = *scontext; | |
102 | ||
103 | *scontextp = ':'; | |
104 | scontextp++; | |
105 | ||
106 | for (l = 0; l < 2; l++) { | |
aa8e712c | 107 | strcpy(scontextp, sym_name(p, SYM_LEVELS, |
ac76c05b | 108 | context->range.level[l].sens - 1)); |
9fe79ad1 | 109 | scontextp += strlen(scontextp); |
1da177e4 LT |
110 | |
111 | /* categories */ | |
9fe79ad1 KK |
112 | head = -2; |
113 | prev = -2; | |
114 | e = &context->range.level[l].cat; | |
115 | ebitmap_for_each_positive_bit(e, node, i) { | |
116 | if (i - prev > 1) { | |
117 | /* one or more negative bits are skipped */ | |
118 | if (prev != head) { | |
119 | if (prev - head > 1) | |
1da177e4 LT |
120 | *scontextp++ = '.'; |
121 | else | |
122 | *scontextp++ = ','; | |
aa8e712c | 123 | nm = sym_name(p, SYM_CATS, prev); |
9fe79ad1 KK |
124 | strcpy(scontextp, nm); |
125 | scontextp += strlen(nm); | |
1da177e4 | 126 | } |
9fe79ad1 KK |
127 | if (prev < 0) |
128 | *scontextp++ = ':'; | |
129 | else | |
130 | *scontextp++ = ','; | |
aa8e712c | 131 | nm = sym_name(p, SYM_CATS, i); |
9fe79ad1 KK |
132 | strcpy(scontextp, nm); |
133 | scontextp += strlen(nm); | |
134 | head = i; | |
1da177e4 | 135 | } |
9fe79ad1 | 136 | prev = i; |
1da177e4 LT |
137 | } |
138 | ||
9fe79ad1 KK |
139 | if (prev != head) { |
140 | if (prev - head > 1) | |
1da177e4 LT |
141 | *scontextp++ = '.'; |
142 | else | |
143 | *scontextp++ = ','; | |
aa8e712c | 144 | nm = sym_name(p, SYM_CATS, prev); |
9fe79ad1 KK |
145 | strcpy(scontextp, nm); |
146 | scontextp += strlen(nm); | |
1da177e4 LT |
147 | } |
148 | ||
149 | if (l == 0) { | |
150 | if (mls_level_eq(&context->range.level[0], | |
1a5e6f87 | 151 | &context->range.level[1])) |
1da177e4 | 152 | break; |
9fe79ad1 KK |
153 | else |
154 | *scontextp++ = '-'; | |
1da177e4 LT |
155 | } |
156 | } | |
157 | ||
158 | *scontext = scontextp; | |
159 | return; | |
160 | } | |
161 | ||
45e5421e SS |
162 | int mls_level_isvalid(struct policydb *p, struct mls_level *l) |
163 | { | |
164 | struct level_datum *levdatum; | |
45e5421e SS |
165 | |
166 | if (!l->sens || l->sens > p->p_levels.nprim) | |
167 | return 0; | |
168 | levdatum = hashtab_search(p->p_levels.table, | |
ac76c05b | 169 | sym_name(p, SYM_LEVELS, l->sens - 1)); |
45e5421e SS |
170 | if (!levdatum) |
171 | return 0; | |
172 | ||
fee71142 WL |
173 | /* |
174 | * Return 1 iff all the bits set in l->cat are also be set in | |
175 | * levdatum->level->cat and no bit in l->cat is larger than | |
176 | * p->p_cats.nprim. | |
177 | */ | |
178 | return ebitmap_contains(&levdatum->level->cat, &l->cat, | |
179 | p->p_cats.nprim); | |
45e5421e SS |
180 | } |
181 | ||
182 | int mls_range_isvalid(struct policydb *p, struct mls_range *r) | |
183 | { | |
184 | return (mls_level_isvalid(p, &r->level[0]) && | |
185 | mls_level_isvalid(p, &r->level[1]) && | |
186 | mls_level_dom(&r->level[1], &r->level[0])); | |
187 | } | |
188 | ||
1da177e4 LT |
189 | /* |
190 | * Return 1 if the MLS fields in the security context | |
191 | * structure `c' are valid. Return 0 otherwise. | |
192 | */ | |
193 | int mls_context_isvalid(struct policydb *p, struct context *c) | |
194 | { | |
1da177e4 | 195 | struct user_datum *usrdatum; |
1da177e4 | 196 | |
0719aaf5 | 197 | if (!p->mls_enabled) |
1da177e4 LT |
198 | return 1; |
199 | ||
45e5421e | 200 | if (!mls_range_isvalid(p, &c->range)) |
1da177e4 LT |
201 | return 0; |
202 | ||
1da177e4 LT |
203 | if (c->role == OBJECT_R_VAL) |
204 | return 1; | |
205 | ||
206 | /* | |
207 | * User must be authorized for the MLS range. | |
208 | */ | |
209 | if (!c->user || c->user > p->p_users.nprim) | |
210 | return 0; | |
211 | usrdatum = p->user_val_to_struct[c->user - 1]; | |
212 | if (!mls_range_contains(usrdatum->range, c->range)) | |
213 | return 0; /* user may not be associated with range */ | |
214 | ||
215 | return 1; | |
216 | } | |
217 | ||
218 | /* | |
219 | * Set the MLS fields in the security context structure | |
220 | * `context' based on the string representation in | |
95ffe194 | 221 | * the string `scontext'. |
1da177e4 LT |
222 | * |
223 | * This function modifies the string in place, inserting | |
224 | * NULL characters to terminate the MLS fields. | |
f5c1d5b2 JM |
225 | * |
226 | * If a def_sid is provided and no MLS field is present, | |
227 | * copy the MLS field of the associated default context. | |
228 | * Used for upgraded to MLS systems where objects may lack | |
229 | * MLS fields. | |
230 | * | |
231 | * Policy read-lock must be held for sidtab lookup. | |
232 | * | |
1da177e4 | 233 | */ |
12b29f34 SS |
234 | int mls_context_to_sid(struct policydb *pol, |
235 | char oldc, | |
95ffe194 | 236 | char *scontext, |
f5c1d5b2 JM |
237 | struct context *context, |
238 | struct sidtab *s, | |
239 | u32 def_sid) | |
1da177e4 | 240 | { |
95ffe194 | 241 | char *sensitivity, *cur_cat, *next_cat, *rngptr; |
1da177e4 LT |
242 | struct level_datum *levdatum; |
243 | struct cat_datum *catdatum, *rngdatum; | |
95ffe194 JH |
244 | int l, rc, i; |
245 | char *rangep[2]; | |
1da177e4 | 246 | |
0719aaf5 | 247 | if (!pol->mls_enabled) { |
877181a8 PM |
248 | /* |
249 | * With no MLS, only return -EINVAL if there is a MLS field | |
250 | * and it did not come from an xattr. | |
251 | */ | |
252 | if (oldc && def_sid == SECSID_NULL) | |
253 | return -EINVAL; | |
254 | return 0; | |
e517a0cd | 255 | } |
1da177e4 | 256 | |
f5c1d5b2 JM |
257 | /* |
258 | * No MLS component to the security context, try and map to | |
259 | * default if provided. | |
260 | */ | |
261 | if (!oldc) { | |
262 | struct context *defcon; | |
263 | ||
264 | if (def_sid == SECSID_NULL) | |
95ffe194 | 265 | return -EINVAL; |
f5c1d5b2 JM |
266 | |
267 | defcon = sidtab_search(s, def_sid); | |
268 | if (!defcon) | |
95ffe194 | 269 | return -EINVAL; |
f5c1d5b2 | 270 | |
95ffe194 | 271 | return mls_context_cpy(context, defcon); |
f5c1d5b2 | 272 | } |
1da177e4 | 273 | |
95ffe194 JH |
274 | /* |
275 | * If we're dealing with a range, figure out where the two parts | |
276 | * of the range begin. | |
277 | */ | |
278 | rangep[0] = scontext; | |
279 | rangep[1] = strchr(scontext, '-'); | |
280 | if (rangep[1]) { | |
281 | rangep[1][0] = '\0'; | |
282 | rangep[1]++; | |
283 | } | |
1da177e4 | 284 | |
95ffe194 | 285 | /* For each part of the range: */ |
1da177e4 | 286 | for (l = 0; l < 2; l++) { |
95ffe194 JH |
287 | /* Split sensitivity and category set. */ |
288 | sensitivity = rangep[l]; | |
289 | if (sensitivity == NULL) | |
290 | break; | |
291 | next_cat = strchr(sensitivity, ':'); | |
292 | if (next_cat) | |
293 | *(next_cat++) = '\0'; | |
294 | ||
295 | /* Parse sensitivity. */ | |
296 | levdatum = hashtab_search(pol->p_levels.table, sensitivity); | |
297 | if (!levdatum) | |
298 | return -EINVAL; | |
1da177e4 LT |
299 | context->range.level[l].sens = levdatum->level->sens; |
300 | ||
95ffe194 JH |
301 | /* Extract category set. */ |
302 | while (next_cat != NULL) { | |
303 | cur_cat = next_cat; | |
304 | next_cat = strchr(next_cat, ','); | |
305 | if (next_cat != NULL) | |
306 | *(next_cat++) = '\0'; | |
307 | ||
308 | /* Separate into range if exists */ | |
309 | rngptr = strchr(cur_cat, '.'); | |
310 | if (rngptr != NULL) { | |
311 | /* Remove '.' */ | |
312 | *rngptr++ = '\0'; | |
313 | } | |
1da177e4 | 314 | |
95ffe194 JH |
315 | catdatum = hashtab_search(pol->p_cats.table, cur_cat); |
316 | if (!catdatum) | |
317 | return -EINVAL; | |
1da177e4 | 318 | |
95ffe194 JH |
319 | rc = ebitmap_set_bit(&context->range.level[l].cat, |
320 | catdatum->value - 1, 1); | |
321 | if (rc) | |
322 | return rc; | |
323 | ||
324 | /* If range, set all categories in range */ | |
325 | if (rngptr == NULL) | |
326 | continue; | |
327 | ||
328 | rngdatum = hashtab_search(pol->p_cats.table, rngptr); | |
329 | if (!rngdatum) | |
330 | return -EINVAL; | |
1da177e4 | 331 | |
95ffe194 JH |
332 | if (catdatum->value >= rngdatum->value) |
333 | return -EINVAL; | |
334 | ||
335 | for (i = catdatum->value; i < rngdatum->value; i++) { | |
336 | rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1); | |
337 | if (rc) | |
338 | return rc; | |
1da177e4 LT |
339 | } |
340 | } | |
1da177e4 LT |
341 | } |
342 | ||
95ffe194 JH |
343 | /* If we didn't see a '-', the range start is also the range end. */ |
344 | if (rangep[1] == NULL) { | |
1da177e4 LT |
345 | context->range.level[1].sens = context->range.level[0].sens; |
346 | rc = ebitmap_cpy(&context->range.level[1].cat, | |
347 | &context->range.level[0].cat); | |
348 | if (rc) | |
95ffe194 | 349 | return rc; |
1da177e4 | 350 | } |
95ffe194 JH |
351 | |
352 | return 0; | |
1da177e4 LT |
353 | } |
354 | ||
376bd9cb DG |
355 | /* |
356 | * Set the MLS fields in the security context structure | |
357 | * `context' based on the string representation in | |
358 | * the string `str'. This function will allocate temporary memory with the | |
359 | * given constraints of gfp_mask. | |
360 | */ | |
aa8e712c SS |
361 | int mls_from_string(struct policydb *p, char *str, struct context *context, |
362 | gfp_t gfp_mask) | |
376bd9cb | 363 | { |
95ffe194 | 364 | char *tmpstr; |
376bd9cb DG |
365 | int rc; |
366 | ||
aa8e712c | 367 | if (!p->mls_enabled) |
376bd9cb DG |
368 | return -EINVAL; |
369 | ||
95ffe194 | 370 | tmpstr = kstrdup(str, gfp_mask); |
376bd9cb DG |
371 | if (!tmpstr) { |
372 | rc = -ENOMEM; | |
373 | } else { | |
95ffe194 | 374 | rc = mls_context_to_sid(p, ':', tmpstr, context, |
1a5e6f87 | 375 | NULL, SECSID_NULL); |
95ffe194 | 376 | kfree(tmpstr); |
376bd9cb DG |
377 | } |
378 | ||
379 | return rc; | |
380 | } | |
381 | ||
1da177e4 LT |
382 | /* |
383 | * Copies the MLS range `range' into `context'. | |
384 | */ | |
0719aaf5 | 385 | int mls_range_set(struct context *context, |
1a5e6f87 | 386 | struct mls_range *range) |
1da177e4 LT |
387 | { |
388 | int l, rc = 0; | |
389 | ||
390 | /* Copy the MLS range into the context */ | |
391 | for (l = 0; l < 2; l++) { | |
392 | context->range.level[l].sens = range->level[l].sens; | |
393 | rc = ebitmap_cpy(&context->range.level[l].cat, | |
394 | &range->level[l].cat); | |
395 | if (rc) | |
396 | break; | |
397 | } | |
398 | ||
399 | return rc; | |
400 | } | |
401 | ||
aa8e712c SS |
402 | int mls_setup_user_range(struct policydb *p, |
403 | struct context *fromcon, struct user_datum *user, | |
1a5e6f87 | 404 | struct context *usercon) |
1da177e4 | 405 | { |
aa8e712c | 406 | if (p->mls_enabled) { |
1da177e4 LT |
407 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); |
408 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); | |
409 | struct mls_level *user_low = &(user->range.level[0]); | |
410 | struct mls_level *user_clr = &(user->range.level[1]); | |
411 | struct mls_level *user_def = &(user->dfltlevel); | |
412 | struct mls_level *usercon_sen = &(usercon->range.level[0]); | |
413 | struct mls_level *usercon_clr = &(usercon->range.level[1]); | |
414 | ||
415 | /* Honor the user's default level if we can */ | |
f5269710 | 416 | if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) |
1da177e4 | 417 | *usercon_sen = *user_def; |
f5269710 | 418 | else if (mls_level_between(fromcon_sen, user_def, user_clr)) |
1da177e4 | 419 | *usercon_sen = *fromcon_sen; |
f5269710 | 420 | else if (mls_level_between(fromcon_clr, user_low, user_def)) |
1da177e4 | 421 | *usercon_sen = *user_low; |
f5269710 | 422 | else |
1da177e4 LT |
423 | return -EINVAL; |
424 | ||
425 | /* Lower the clearance of available contexts | |
426 | if the clearance of "fromcon" is lower than | |
427 | that of the user's default clearance (but | |
428 | only if the "fromcon" clearance dominates | |
429 | the user's computed sensitivity level) */ | |
1a5e6f87 | 430 | if (mls_level_dom(user_clr, fromcon_clr)) |
1da177e4 | 431 | *usercon_clr = *fromcon_clr; |
1a5e6f87 | 432 | else if (mls_level_dom(fromcon_clr, user_clr)) |
1da177e4 | 433 | *usercon_clr = *user_clr; |
1a5e6f87 | 434 | else |
1da177e4 LT |
435 | return -EINVAL; |
436 | } | |
437 | ||
438 | return 0; | |
439 | } | |
440 | ||
441 | /* | |
442 | * Convert the MLS fields in the security context | |
443 | * structure `c' from the values specified in the | |
444 | * policy `oldp' to the values specified in the policy `newp'. | |
445 | */ | |
446 | int mls_convert_context(struct policydb *oldp, | |
447 | struct policydb *newp, | |
448 | struct context *c) | |
449 | { | |
450 | struct level_datum *levdatum; | |
451 | struct cat_datum *catdatum; | |
452 | struct ebitmap bitmap; | |
782ebb99 | 453 | struct ebitmap_node *node; |
1da177e4 LT |
454 | int l, i; |
455 | ||
aa8e712c | 456 | if (!oldp->mls_enabled || !newp->mls_enabled) |
1da177e4 LT |
457 | return 0; |
458 | ||
459 | for (l = 0; l < 2; l++) { | |
460 | levdatum = hashtab_search(newp->p_levels.table, | |
ac76c05b EP |
461 | sym_name(oldp, SYM_LEVELS, |
462 | c->range.level[l].sens - 1)); | |
1da177e4 LT |
463 | |
464 | if (!levdatum) | |
465 | return -EINVAL; | |
466 | c->range.level[l].sens = levdatum->level->sens; | |
467 | ||
468 | ebitmap_init(&bitmap); | |
9fe79ad1 KK |
469 | ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) { |
470 | int rc; | |
471 | ||
472 | catdatum = hashtab_search(newp->p_cats.table, | |
ac76c05b | 473 | sym_name(oldp, SYM_CATS, i)); |
9fe79ad1 KK |
474 | if (!catdatum) |
475 | return -EINVAL; | |
476 | rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); | |
477 | if (rc) | |
478 | return rc; | |
9a591f39 DJ |
479 | |
480 | cond_resched(); | |
1da177e4 LT |
481 | } |
482 | ebitmap_destroy(&c->range.level[l].cat); | |
483 | c->range.level[l].cat = bitmap; | |
484 | } | |
485 | ||
486 | return 0; | |
487 | } | |
488 | ||
aa8e712c SS |
489 | int mls_compute_sid(struct policydb *p, |
490 | struct context *scontext, | |
1da177e4 LT |
491 | struct context *tcontext, |
492 | u16 tclass, | |
493 | u32 specified, | |
6f5317e7 HC |
494 | struct context *newcontext, |
495 | bool sock) | |
1da177e4 | 496 | { |
2f3e82d6 SS |
497 | struct range_trans rtr; |
498 | struct mls_range *r; | |
aa893269 EP |
499 | struct class_datum *cladatum; |
500 | int default_range = 0; | |
f3f87714 | 501 | |
aa8e712c | 502 | if (!p->mls_enabled) |
1da177e4 LT |
503 | return 0; |
504 | ||
505 | switch (specified) { | |
506 | case AVTAB_TRANSITION: | |
f3f87714 | 507 | /* Look for a range transition rule. */ |
2f3e82d6 SS |
508 | rtr.source_type = scontext->type; |
509 | rtr.target_type = tcontext->type; | |
510 | rtr.target_class = tclass; | |
aa8e712c | 511 | r = hashtab_search(p->range_tr, &rtr); |
2f3e82d6 SS |
512 | if (r) |
513 | return mls_range_set(newcontext, r); | |
aa893269 | 514 | |
aa8e712c SS |
515 | if (tclass && tclass <= p->p_classes.nprim) { |
516 | cladatum = p->class_val_to_struct[tclass - 1]; | |
aa893269 EP |
517 | if (cladatum) |
518 | default_range = cladatum->default_range; | |
519 | } | |
520 | ||
521 | switch (default_range) { | |
522 | case DEFAULT_SOURCE_LOW: | |
523 | return mls_context_cpy_low(newcontext, scontext); | |
524 | case DEFAULT_SOURCE_HIGH: | |
525 | return mls_context_cpy_high(newcontext, scontext); | |
526 | case DEFAULT_SOURCE_LOW_HIGH: | |
527 | return mls_context_cpy(newcontext, scontext); | |
528 | case DEFAULT_TARGET_LOW: | |
529 | return mls_context_cpy_low(newcontext, tcontext); | |
530 | case DEFAULT_TARGET_HIGH: | |
531 | return mls_context_cpy_high(newcontext, tcontext); | |
532 | case DEFAULT_TARGET_LOW_HIGH: | |
533 | return mls_context_cpy(newcontext, tcontext); | |
534 | } | |
535 | ||
1da177e4 LT |
536 | /* Fallthrough */ |
537 | case AVTAB_CHANGE: | |
aa8e712c | 538 | if ((tclass == p->process_class) || (sock == true)) |
1da177e4 | 539 | /* Use the process MLS attributes. */ |
0efc61ea | 540 | return mls_context_cpy(newcontext, scontext); |
1da177e4 LT |
541 | else |
542 | /* Use the process effective MLS attributes. */ | |
0efc61ea | 543 | return mls_context_cpy_low(newcontext, scontext); |
1da177e4 | 544 | case AVTAB_MEMBER: |
2e08c0c1 EW |
545 | /* Use the process effective MLS attributes. */ |
546 | return mls_context_cpy_low(newcontext, scontext); | |
08e3daff AW |
547 | |
548 | /* fall through */ | |
1da177e4 LT |
549 | } |
550 | return -EINVAL; | |
551 | } | |
552 | ||
02752760 | 553 | #ifdef CONFIG_NETLABEL |
7420ed23 | 554 | /** |
02752760 | 555 | * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel |
7420ed23 | 556 | * @context: the security context |
02752760 | 557 | * @secattr: the NetLabel security attributes |
7420ed23 VY |
558 | * |
559 | * Description: | |
02752760 PM |
560 | * Given the security context copy the low MLS sensitivity level into the |
561 | * NetLabel MLS sensitivity level field. | |
7420ed23 VY |
562 | * |
563 | */ | |
aa8e712c SS |
564 | void mls_export_netlbl_lvl(struct policydb *p, |
565 | struct context *context, | |
02752760 | 566 | struct netlbl_lsm_secattr *secattr) |
7420ed23 | 567 | { |
aa8e712c | 568 | if (!p->mls_enabled) |
7420ed23 VY |
569 | return; |
570 | ||
16efd454 | 571 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; |
02752760 | 572 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; |
7420ed23 VY |
573 | } |
574 | ||
575 | /** | |
02752760 | 576 | * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels |
7420ed23 | 577 | * @context: the security context |
02752760 | 578 | * @secattr: the NetLabel security attributes |
7420ed23 VY |
579 | * |
580 | * Description: | |
02752760 PM |
581 | * Given the security context and the NetLabel security attributes, copy the |
582 | * NetLabel MLS sensitivity level into the context. | |
7420ed23 VY |
583 | * |
584 | */ | |
aa8e712c SS |
585 | void mls_import_netlbl_lvl(struct policydb *p, |
586 | struct context *context, | |
02752760 | 587 | struct netlbl_lsm_secattr *secattr) |
7420ed23 | 588 | { |
aa8e712c | 589 | if (!p->mls_enabled) |
7420ed23 VY |
590 | return; |
591 | ||
16efd454 | 592 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; |
02752760 | 593 | context->range.level[1].sens = context->range.level[0].sens; |
7420ed23 VY |
594 | } |
595 | ||
596 | /** | |
02752760 | 597 | * mls_export_netlbl_cat - Export the MLS categories to NetLabel |
7420ed23 | 598 | * @context: the security context |
02752760 | 599 | * @secattr: the NetLabel security attributes |
7420ed23 VY |
600 | * |
601 | * Description: | |
02752760 PM |
602 | * Given the security context copy the low MLS categories into the NetLabel |
603 | * MLS category field. Returns zero on success, negative values on failure. | |
7420ed23 VY |
604 | * |
605 | */ | |
aa8e712c SS |
606 | int mls_export_netlbl_cat(struct policydb *p, |
607 | struct context *context, | |
02752760 | 608 | struct netlbl_lsm_secattr *secattr) |
7420ed23 | 609 | { |
02752760 | 610 | int rc; |
7420ed23 | 611 | |
aa8e712c | 612 | if (!p->mls_enabled) |
7420ed23 VY |
613 | return 0; |
614 | ||
02752760 | 615 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, |
16efd454 PM |
616 | &secattr->attr.mls.cat); |
617 | if (rc == 0 && secattr->attr.mls.cat != NULL) | |
02752760 | 618 | secattr->flags |= NETLBL_SECATTR_MLS_CAT; |
7420ed23 | 619 | |
7420ed23 VY |
620 | return rc; |
621 | } | |
622 | ||
623 | /** | |
02752760 | 624 | * mls_import_netlbl_cat - Import the MLS categories from NetLabel |
7420ed23 | 625 | * @context: the security context |
02752760 | 626 | * @secattr: the NetLabel security attributes |
7420ed23 VY |
627 | * |
628 | * Description: | |
02752760 PM |
629 | * Copy the NetLabel security attributes into the SELinux context; since the |
630 | * NetLabel security attribute only contains a single MLS category use it for | |
631 | * both the low and high categories of the context. Returns zero on success, | |
632 | * negative values on failure. | |
7420ed23 VY |
633 | * |
634 | */ | |
aa8e712c SS |
635 | int mls_import_netlbl_cat(struct policydb *p, |
636 | struct context *context, | |
02752760 | 637 | struct netlbl_lsm_secattr *secattr) |
7420ed23 | 638 | { |
02752760 | 639 | int rc; |
7420ed23 | 640 | |
aa8e712c | 641 | if (!p->mls_enabled) |
7420ed23 VY |
642 | return 0; |
643 | ||
02752760 | 644 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, |
16efd454 | 645 | secattr->attr.mls.cat); |
da8026fa | 646 | if (rc) |
02752760 | 647 | goto import_netlbl_cat_failure; |
da8026fa PM |
648 | memcpy(&context->range.level[1].cat, &context->range.level[0].cat, |
649 | sizeof(context->range.level[0].cat)); | |
7420ed23 VY |
650 | |
651 | return 0; | |
652 | ||
02752760 | 653 | import_netlbl_cat_failure: |
7420ed23 | 654 | ebitmap_destroy(&context->range.level[0].cat); |
7420ed23 VY |
655 | return rc; |
656 | } | |
02752760 | 657 | #endif /* CONFIG_NETLABEL */ |