aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netlabel.h26
-rw-r--r--net/ipv4/cipso_ipv4.c12
-rw-r--r--net/netlabel/netlabel_kapi.c216
-rw-r--r--security/selinux/ss/ebitmap.c127
-rw-r--r--security/smack/smack_access.c5
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);
395int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, 395int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
396 u32 offset); 396 u32 offset);
397int netlbl_secattr_catmap_getlong(struct netlbl_lsm_secattr_catmap *catmap,
398 u32 *offset,
399 unsigned long *bitmap);
397int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap, 400int 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);
407int 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}
514static 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}
507static inline int netlbl_secattr_catmap_setbit( 521static 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}
536static 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}
522static inline int netlbl_enabled(void) 544static 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 */
425static 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
445secattr_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 */
594int 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 */
707int 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:
155int ebitmap_netlbl_import(struct ebitmap *ebmap, 140int 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
210netlbl_import_failure: 181netlbl_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++) {