diff options
-rw-r--r-- | include/net/netlabel.h | 26 | ||||
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 12 | ||||
-rw-r--r-- | net/netlabel/netlabel_kapi.c | 216 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.c | 127 | ||||
-rw-r--r-- | security/smack/smack_access.c | 5 |
5 files changed, 240 insertions, 146 deletions
diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 1c40d658d008..bda7a121f31e 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h | |||
@@ -285,11 +285,11 @@ static inline void netlbl_secattr_catmap_free( | |||
285 | { | 285 | { |
286 | struct netlbl_lsm_secattr_catmap *iter; | 286 | struct netlbl_lsm_secattr_catmap *iter; |
287 | 287 | ||
288 | do { | 288 | while (catmap) { |
289 | iter = catmap; | 289 | iter = catmap; |
290 | catmap = catmap->next; | 290 | catmap = catmap->next; |
291 | kfree(iter); | 291 | kfree(iter); |
292 | } while (catmap); | 292 | } |
293 | } | 293 | } |
294 | 294 | ||
295 | /** | 295 | /** |
@@ -394,6 +394,9 @@ int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, | |||
394 | u32 offset); | 394 | u32 offset); |
395 | int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, | 395 | int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, |
396 | u32 offset); | 396 | u32 offset); |
397 | int netlbl_secattr_catmap_getlong(struct netlbl_lsm_secattr_catmap *catmap, | ||
398 | u32 *offset, | ||
399 | unsigned long *bitmap); | ||
397 | int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap, | 400 | int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap, |
398 | u32 bit, | 401 | u32 bit, |
399 | gfp_t flags); | 402 | gfp_t flags); |
@@ -401,6 +404,10 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap **catmap, | |||
401 | u32 start, | 404 | u32 start, |
402 | u32 end, | 405 | u32 end, |
403 | gfp_t flags); | 406 | gfp_t flags); |
407 | int netlbl_secattr_catmap_setlong(struct netlbl_lsm_secattr_catmap **catmap, | ||
408 | u32 offset, | ||
409 | unsigned long bitmap, | ||
410 | gfp_t flags); | ||
404 | 411 | ||
405 | /* | 412 | /* |
406 | * LSM protocol operations (NetLabel LSM/kernel API) | 413 | * LSM protocol operations (NetLabel LSM/kernel API) |
@@ -504,6 +511,13 @@ static inline int netlbl_secattr_catmap_walk_rng( | |||
504 | { | 511 | { |
505 | return -ENOENT; | 512 | return -ENOENT; |
506 | } | 513 | } |
514 | static inline int netlbl_secattr_catmap_getlong( | ||
515 | struct netlbl_lsm_secattr_catmap *catmap, | ||
516 | u32 *offset, | ||
517 | unsigned long *bitmap) | ||
518 | { | ||
519 | return 0; | ||
520 | } | ||
507 | static inline int netlbl_secattr_catmap_setbit( | 521 | static inline int netlbl_secattr_catmap_setbit( |
508 | struct netlbl_lsm_secattr_catmap **catmap, | 522 | struct netlbl_lsm_secattr_catmap **catmap, |
509 | u32 bit, | 523 | u32 bit, |
@@ -519,6 +533,14 @@ static inline int netlbl_secattr_catmap_setrng( | |||
519 | { | 533 | { |
520 | return 0; | 534 | return 0; |
521 | } | 535 | } |
536 | static int netlbl_secattr_catmap_setlong( | ||
537 | struct netlbl_lsm_secattr_catmap **catmap, | ||
538 | u32 offset, | ||
539 | unsigned long bitmap, | ||
540 | gfp_t flags) | ||
541 | { | ||
542 | return 0; | ||
543 | } | ||
522 | static inline int netlbl_enabled(void) | 544 | static inline int netlbl_enabled(void) |
523 | { | 545 | { |
524 | return 0; | 546 | return 0; |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index dd433c943537..8a0c7bd6eff4 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -1335,10 +1335,6 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, | |||
1335 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; | 1335 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; |
1336 | 1336 | ||
1337 | if (tag_len > 4) { | 1337 | if (tag_len > 4) { |
1338 | secattr->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | ||
1339 | if (secattr->attr.mls.cat == NULL) | ||
1340 | return -ENOMEM; | ||
1341 | |||
1342 | ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, | 1338 | ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, |
1343 | &tag[4], | 1339 | &tag[4], |
1344 | tag_len - 4, | 1340 | tag_len - 4, |
@@ -1430,10 +1426,6 @@ static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def, | |||
1430 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; | 1426 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; |
1431 | 1427 | ||
1432 | if (tag_len > 4) { | 1428 | if (tag_len > 4) { |
1433 | secattr->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | ||
1434 | if (secattr->attr.mls.cat == NULL) | ||
1435 | return -ENOMEM; | ||
1436 | |||
1437 | ret_val = cipso_v4_map_cat_enum_ntoh(doi_def, | 1429 | ret_val = cipso_v4_map_cat_enum_ntoh(doi_def, |
1438 | &tag[4], | 1430 | &tag[4], |
1439 | tag_len - 4, | 1431 | tag_len - 4, |
@@ -1524,10 +1516,6 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def, | |||
1524 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; | 1516 | secattr->flags |= NETLBL_SECATTR_MLS_LVL; |
1525 | 1517 | ||
1526 | if (tag_len > 4) { | 1518 | if (tag_len > 4) { |
1527 | secattr->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | ||
1528 | if (secattr->attr.mls.cat == NULL) | ||
1529 | return -ENOMEM; | ||
1530 | |||
1531 | ret_val = cipso_v4_map_cat_rng_ntoh(doi_def, | 1519 | ret_val = cipso_v4_map_cat_rng_ntoh(doi_def, |
1532 | &tag[4], | 1520 | &tag[4], |
1533 | tag_len - 4, | 1521 | tag_len - 4, |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 84e810bef39a..d9e10466b928 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -405,6 +405,63 @@ out_entry: | |||
405 | * Security Attribute Functions | 405 | * Security Attribute Functions |
406 | */ | 406 | */ |
407 | 407 | ||
408 | #define _CM_F_NONE 0x00000000 | ||
409 | #define _CM_F_ALLOC 0x00000001 | ||
410 | |||
411 | /** | ||
412 | * _netlbl_secattr_catmap_getnode - Get a individual node from a catmap | ||
413 | * @catmap: pointer to the category bitmap | ||
414 | * @offset: the requested offset | ||
415 | * @cm_flags: catmap flags, see _CM_F_* | ||
416 | * @gfp_flags: memory allocation flags | ||
417 | * | ||
418 | * Description: | ||
419 | * Iterate through the catmap looking for the node associated with @offset; if | ||
420 | * the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node, | ||
421 | * one will be created and inserted into the catmap. Returns a pointer to the | ||
422 | * node on success, NULL on failure. | ||
423 | * | ||
424 | */ | ||
425 | static struct netlbl_lsm_secattr_catmap *_netlbl_secattr_catmap_getnode( | ||
426 | struct netlbl_lsm_secattr_catmap **catmap, | ||
427 | u32 offset, | ||
428 | unsigned int cm_flags, | ||
429 | gfp_t gfp_flags) | ||
430 | { | ||
431 | struct netlbl_lsm_secattr_catmap *iter = *catmap; | ||
432 | struct netlbl_lsm_secattr_catmap *prev = NULL; | ||
433 | |||
434 | if (iter == NULL || offset < iter->startbit) | ||
435 | goto secattr_catmap_getnode_alloc; | ||
436 | while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { | ||
437 | prev = iter; | ||
438 | iter = iter->next; | ||
439 | } | ||
440 | if (iter == NULL || offset < iter->startbit) | ||
441 | goto secattr_catmap_getnode_alloc; | ||
442 | |||
443 | return iter; | ||
444 | |||
445 | secattr_catmap_getnode_alloc: | ||
446 | if (!(cm_flags & _CM_F_ALLOC)) | ||
447 | return NULL; | ||
448 | |||
449 | iter = netlbl_secattr_catmap_alloc(gfp_flags); | ||
450 | if (iter == NULL) | ||
451 | return NULL; | ||
452 | iter->startbit = offset & ~(NETLBL_CATMAP_SIZE - 1); | ||
453 | |||
454 | if (prev == NULL) { | ||
455 | iter->next = *catmap; | ||
456 | *catmap = iter; | ||
457 | } else { | ||
458 | iter->next = prev->next; | ||
459 | prev->next = iter; | ||
460 | } | ||
461 | |||
462 | return iter; | ||
463 | } | ||
464 | |||
408 | /** | 465 | /** |
409 | * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit | 466 | * netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit |
410 | * @catmap: the category bitmap | 467 | * @catmap: the category bitmap |
@@ -521,6 +578,54 @@ int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, | |||
521 | } | 578 | } |
522 | 579 | ||
523 | /** | 580 | /** |
581 | * netlbl_secattr_catmap_getlong - Export an unsigned long bitmap | ||
582 | * @catmap: pointer to the category bitmap | ||
583 | * @offset: pointer to the requested offset | ||
584 | * @bitmap: the exported bitmap | ||
585 | * | ||
586 | * Description: | ||
587 | * Export a bitmap with an offset greater than or equal to @offset and return | ||
588 | * it in @bitmap. The @offset must be aligned to an unsigned long and will be | ||
589 | * updated on return if different from what was requested; if the catmap is | ||
590 | * empty at the requested offset and beyond, the @offset is set to (u32)-1. | ||
591 | * Returns zero on sucess, negative values on failure. | ||
592 | * | ||
593 | */ | ||
594 | int netlbl_secattr_catmap_getlong(struct netlbl_lsm_secattr_catmap *catmap, | ||
595 | u32 *offset, | ||
596 | unsigned long *bitmap) | ||
597 | { | ||
598 | struct netlbl_lsm_secattr_catmap *iter; | ||
599 | u32 off = *offset; | ||
600 | u32 idx; | ||
601 | |||
602 | /* only allow aligned offsets */ | ||
603 | if ((off & (BITS_PER_LONG - 1)) != 0) | ||
604 | return -EINVAL; | ||
605 | |||
606 | if (off < catmap->startbit) { | ||
607 | off = catmap->startbit; | ||
608 | *offset = off; | ||
609 | } | ||
610 | iter = _netlbl_secattr_catmap_getnode(&catmap, off, _CM_F_NONE, 0); | ||
611 | if (iter == NULL) { | ||
612 | *offset = (u32)-1; | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | if (off < iter->startbit) { | ||
617 | off = iter->startbit; | ||
618 | *offset = off; | ||
619 | } else | ||
620 | off -= iter->startbit; | ||
621 | |||
622 | idx = off / NETLBL_CATMAP_MAPSIZE; | ||
623 | *bitmap = iter->bitmap[idx] >> (off % NETLBL_CATMAP_SIZE); | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | /** | ||
524 | * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap | 629 | * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap |
525 | * @catmap: pointer to the category bitmap | 630 | * @catmap: pointer to the category bitmap |
526 | * @bit: the bit to set | 631 | * @bit: the bit to set |
@@ -535,32 +640,16 @@ int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap, | |||
535 | u32 bit, | 640 | u32 bit, |
536 | gfp_t flags) | 641 | gfp_t flags) |
537 | { | 642 | { |
538 | struct netlbl_lsm_secattr_catmap *iter = *catmap; | 643 | struct netlbl_lsm_secattr_catmap *iter; |
539 | u32 node_bit; | 644 | u32 idx; |
540 | u32 node_idx; | ||
541 | 645 | ||
542 | while (iter->next != NULL && | 646 | iter = _netlbl_secattr_catmap_getnode(catmap, bit, _CM_F_ALLOC, flags); |
543 | bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) | 647 | if (iter == NULL) |
544 | iter = iter->next; | 648 | return -ENOMEM; |
545 | if (bit < iter->startbit) { | ||
546 | iter = netlbl_secattr_catmap_alloc(flags); | ||
547 | if (iter == NULL) | ||
548 | return -ENOMEM; | ||
549 | iter->next = *catmap; | ||
550 | iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1); | ||
551 | *catmap = iter; | ||
552 | } else if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) { | ||
553 | iter->next = netlbl_secattr_catmap_alloc(flags); | ||
554 | if (iter->next == NULL) | ||
555 | return -ENOMEM; | ||
556 | iter = iter->next; | ||
557 | iter->startbit = bit & ~(NETLBL_CATMAP_SIZE - 1); | ||
558 | } | ||
559 | 649 | ||
560 | /* gcc always rounds to zero when doing integer division */ | 650 | bit -= iter->startbit; |
561 | node_idx = (bit - iter->startbit) / NETLBL_CATMAP_MAPSIZE; | 651 | idx = bit / NETLBL_CATMAP_MAPSIZE; |
562 | node_bit = bit - iter->startbit - (NETLBL_CATMAP_MAPSIZE * node_idx); | 652 | iter->bitmap[idx] |= NETLBL_CATMAP_BIT << (bit % NETLBL_CATMAP_MAPSIZE); |
563 | iter->bitmap[node_idx] |= NETLBL_CATMAP_BIT << node_bit; | ||
564 | 653 | ||
565 | return 0; | 654 | return 0; |
566 | } | 655 | } |
@@ -582,34 +671,61 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap **catmap, | |||
582 | u32 end, | 671 | u32 end, |
583 | gfp_t flags) | 672 | gfp_t flags) |
584 | { | 673 | { |
585 | int ret_val = 0; | 674 | int rc = 0; |
586 | struct netlbl_lsm_secattr_catmap *iter = *catmap; | 675 | u32 spot = start; |
587 | u32 iter_max_spot; | 676 | |
588 | u32 spot; | 677 | while (rc == 0 && spot <= end) { |
589 | u32 orig_spot = iter->startbit; | 678 | if (((spot & (BITS_PER_LONG - 1)) != 0) && |
590 | 679 | ((end - spot) > BITS_PER_LONG)) { | |
591 | /* XXX - This could probably be made a bit faster by combining writes | 680 | rc = netlbl_secattr_catmap_setlong(catmap, |
592 | * to the catmap instead of setting a single bit each time, but for | 681 | spot, |
593 | * right now skipping to the start of the range in the catmap should | 682 | (unsigned long)-1, |
594 | * be a nice improvement over calling the individual setbit function | 683 | flags); |
595 | * repeatedly from a loop. */ | 684 | spot += BITS_PER_LONG; |
596 | 685 | } else | |
597 | while (iter->next != NULL && | 686 | rc = netlbl_secattr_catmap_setbit(catmap, |
598 | start >= (iter->startbit + NETLBL_CATMAP_SIZE)) | 687 | spot++, |
599 | iter = iter->next; | 688 | flags); |
600 | iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; | ||
601 | |||
602 | for (spot = start; spot <= end && ret_val == 0; spot++) { | ||
603 | if (spot >= iter_max_spot && iter->next != NULL) { | ||
604 | iter = iter->next; | ||
605 | iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; | ||
606 | } | ||
607 | ret_val = netlbl_secattr_catmap_setbit(&iter, spot, flags); | ||
608 | if (iter->startbit < orig_spot) | ||
609 | *catmap = iter; | ||
610 | } | 689 | } |
611 | 690 | ||
612 | return ret_val; | 691 | return rc; |
692 | } | ||
693 | |||
694 | /** | ||
695 | * netlbl_secattr_catmap_setlong - Import an unsigned long bitmap | ||
696 | * @catmap: pointer to the category bitmap | ||
697 | * @offset: offset to the start of the imported bitmap | ||
698 | * @bitmap: the bitmap to import | ||
699 | * @flags: memory allocation flags | ||
700 | * | ||
701 | * Description: | ||
702 | * Import the bitmap specified in @bitmap into @catmap, using the offset | ||
703 | * in @offset. The offset must be aligned to an unsigned long. Returns zero | ||
704 | * on success, negative values on failure. | ||
705 | * | ||
706 | */ | ||
707 | int netlbl_secattr_catmap_setlong(struct netlbl_lsm_secattr_catmap **catmap, | ||
708 | u32 offset, | ||
709 | unsigned long bitmap, | ||
710 | gfp_t flags) | ||
711 | { | ||
712 | struct netlbl_lsm_secattr_catmap *iter; | ||
713 | u32 idx; | ||
714 | |||
715 | /* only allow aligned offsets */ | ||
716 | if ((offset & (BITS_PER_LONG - 1)) != 0) | ||
717 | return -EINVAL; | ||
718 | |||
719 | iter = _netlbl_secattr_catmap_getnode(catmap, | ||
720 | offset, _CM_F_ALLOC, flags); | ||
721 | if (iter == NULL) | ||
722 | return -ENOMEM; | ||
723 | |||
724 | offset -= iter->startbit; | ||
725 | idx = offset / NETLBL_CATMAP_MAPSIZE; | ||
726 | iter->bitmap[idx] |= bitmap << (offset % NETLBL_CATMAP_MAPSIZE); | ||
727 | |||
728 | return 0; | ||
613 | } | 729 | } |
614 | 730 | ||
615 | /* | 731 | /* |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 820313a04d49..842deca9484d 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -89,48 +89,33 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, | |||
89 | struct netlbl_lsm_secattr_catmap **catmap) | 89 | struct netlbl_lsm_secattr_catmap **catmap) |
90 | { | 90 | { |
91 | struct ebitmap_node *e_iter = ebmap->node; | 91 | struct ebitmap_node *e_iter = ebmap->node; |
92 | struct netlbl_lsm_secattr_catmap *c_iter; | 92 | unsigned long e_map; |
93 | u32 cmap_idx, cmap_sft; | 93 | u32 offset; |
94 | int i; | 94 | unsigned int iter; |
95 | 95 | int rc; | |
96 | /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64, | ||
97 | * however, it is not always compatible with an array of unsigned long | ||
98 | * in ebitmap_node. | ||
99 | * In addition, you should pay attention the following implementation | ||
100 | * assumes unsigned long has a width equal with or less than 64-bit. | ||
101 | */ | ||
102 | 96 | ||
103 | if (e_iter == NULL) { | 97 | if (e_iter == NULL) { |
104 | *catmap = NULL; | 98 | *catmap = NULL; |
105 | return 0; | 99 | return 0; |
106 | } | 100 | } |
107 | 101 | ||
108 | c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | 102 | if (*catmap != NULL) |
109 | if (c_iter == NULL) | 103 | netlbl_secattr_catmap_free(*catmap); |
110 | return -ENOMEM; | 104 | *catmap = NULL; |
111 | *catmap = c_iter; | ||
112 | c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); | ||
113 | 105 | ||
114 | while (e_iter) { | 106 | while (e_iter) { |
115 | for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { | 107 | offset = e_iter->startbit; |
116 | unsigned int delta, e_startbit, c_endbit; | 108 | for (iter = 0; iter < EBITMAP_UNIT_NUMS; iter++) { |
117 | 109 | e_map = e_iter->maps[iter]; | |
118 | e_startbit = e_iter->startbit + i * EBITMAP_UNIT_SIZE; | 110 | if (e_map != 0) { |
119 | c_endbit = c_iter->startbit + NETLBL_CATMAP_SIZE; | 111 | rc = netlbl_secattr_catmap_setlong(catmap, |
120 | if (e_startbit >= c_endbit) { | 112 | offset, |
121 | c_iter->next | 113 | e_map, |
122 | = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | 114 | GFP_ATOMIC); |
123 | if (c_iter->next == NULL) | 115 | if (rc != 0) |
124 | goto netlbl_export_failure; | 116 | goto netlbl_export_failure; |
125 | c_iter = c_iter->next; | ||
126 | c_iter->startbit | ||
127 | = e_startbit & ~(NETLBL_CATMAP_SIZE - 1); | ||
128 | } | 117 | } |
129 | delta = e_startbit - c_iter->startbit; | 118 | offset += EBITMAP_UNIT_SIZE; |
130 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; | ||
131 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; | ||
132 | c_iter->bitmap[cmap_idx] | ||
133 | |= e_iter->maps[i] << cmap_sft; | ||
134 | } | 119 | } |
135 | e_iter = e_iter->next; | 120 | e_iter = e_iter->next; |
136 | } | 121 | } |
@@ -155,56 +140,42 @@ netlbl_export_failure: | |||
155 | int ebitmap_netlbl_import(struct ebitmap *ebmap, | 140 | int ebitmap_netlbl_import(struct ebitmap *ebmap, |
156 | struct netlbl_lsm_secattr_catmap *catmap) | 141 | struct netlbl_lsm_secattr_catmap *catmap) |
157 | { | 142 | { |
143 | int rc; | ||
158 | struct ebitmap_node *e_iter = NULL; | 144 | struct ebitmap_node *e_iter = NULL; |
159 | struct ebitmap_node *emap_prev = NULL; | 145 | struct ebitmap_node *e_prev = NULL; |
160 | struct netlbl_lsm_secattr_catmap *c_iter = catmap; | 146 | u32 offset = 0, idx; |
161 | u32 c_idx, c_pos, e_idx, e_sft; | 147 | unsigned long bitmap; |
162 | 148 | ||
163 | /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64, | 149 | for (;;) { |
164 | * however, it is not always compatible with an array of unsigned long | 150 | rc = netlbl_secattr_catmap_getlong(catmap, &offset, &bitmap); |
165 | * in ebitmap_node. | 151 | if (rc < 0) |
166 | * In addition, you should pay attention the following implementation | 152 | goto netlbl_import_failure; |
167 | * assumes unsigned long has a width equal with or less than 64-bit. | 153 | if (offset == (u32)-1) |
168 | */ | 154 | return 0; |
169 | |||
170 | do { | ||
171 | for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) { | ||
172 | unsigned int delta; | ||
173 | u64 map = c_iter->bitmap[c_idx]; | ||
174 | |||
175 | if (!map) | ||
176 | continue; | ||
177 | 155 | ||
178 | c_pos = c_iter->startbit | 156 | if (e_iter == NULL || |
179 | + c_idx * NETLBL_CATMAP_MAPSIZE; | 157 | offset >= e_iter->startbit + EBITMAP_SIZE) { |
180 | if (!e_iter | 158 | e_prev = e_iter; |
181 | || c_pos >= e_iter->startbit + EBITMAP_SIZE) { | 159 | e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC); |
182 | e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC); | 160 | if (e_iter == NULL) |
183 | if (!e_iter) | 161 | goto netlbl_import_failure; |
184 | goto netlbl_import_failure; | 162 | e_iter->startbit = offset & ~(EBITMAP_SIZE - 1); |
185 | e_iter->startbit | 163 | if (e_prev == NULL) |
186 | = c_pos - (c_pos % EBITMAP_SIZE); | 164 | ebmap->node = e_iter; |
187 | if (emap_prev == NULL) | 165 | else |
188 | ebmap->node = e_iter; | 166 | e_prev->next = e_iter; |
189 | else | 167 | ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; |
190 | emap_prev->next = e_iter; | ||
191 | emap_prev = e_iter; | ||
192 | } | ||
193 | delta = c_pos - e_iter->startbit; | ||
194 | e_idx = delta / EBITMAP_UNIT_SIZE; | ||
195 | e_sft = delta % EBITMAP_UNIT_SIZE; | ||
196 | while (map) { | ||
197 | e_iter->maps[e_idx++] |= map & (-1UL); | ||
198 | map = EBITMAP_SHIFT_UNIT_SIZE(map); | ||
199 | } | ||
200 | } | 168 | } |
201 | c_iter = c_iter->next; | ||
202 | } while (c_iter); | ||
203 | if (e_iter != NULL) | ||
204 | ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; | ||
205 | else | ||
206 | ebitmap_destroy(ebmap); | ||
207 | 169 | ||
170 | /* offset will always be aligned to an unsigned long */ | ||
171 | idx = EBITMAP_NODE_INDEX(e_iter, offset); | ||
172 | e_iter->maps[idx] = bitmap; | ||
173 | |||
174 | /* next */ | ||
175 | offset += EBITMAP_UNIT_SIZE; | ||
176 | } | ||
177 | |||
178 | /* NOTE: we should never reach this return */ | ||
208 | return 0; | 179 | return 0; |
209 | 180 | ||
210 | netlbl_import_failure: | 181 | netlbl_import_failure: |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 9ecf4f4b67a1..ea1bc5055792 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -435,10 +435,7 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, | |||
435 | 435 | ||
436 | sap->flags |= NETLBL_SECATTR_MLS_CAT; | 436 | sap->flags |= NETLBL_SECATTR_MLS_CAT; |
437 | sap->attr.mls.lvl = level; | 437 | sap->attr.mls.lvl = level; |
438 | sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | 438 | sap->attr.mls.cat = NULL; |
439 | if (!sap->attr.mls.cat) | ||
440 | return -ENOMEM; | ||
441 | sap->attr.mls.cat->startbit = 0; | ||
442 | 439 | ||
443 | for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++) | 440 | for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++) |
444 | for (m = 0x80; m != 0; m >>= 1, cat++) { | 441 | for (m = 0x80; m != 0; m >>= 1, cat++) { |