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