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