diff options
| -rw-r--r-- | net/netlabel/netlabel_kapi.c | 102 |
1 files changed, 54 insertions, 48 deletions
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index d9e10466b928..bc3883814890 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
| @@ -407,6 +407,7 @@ out_entry: | |||
| 407 | 407 | ||
| 408 | #define _CM_F_NONE 0x00000000 | 408 | #define _CM_F_NONE 0x00000000 |
| 409 | #define _CM_F_ALLOC 0x00000001 | 409 | #define _CM_F_ALLOC 0x00000001 |
| 410 | #define _CM_F_WALK 0x00000002 | ||
| 410 | 411 | ||
| 411 | /** | 412 | /** |
| 412 | * _netlbl_secattr_catmap_getnode - Get a individual node from a catmap | 413 | * _netlbl_secattr_catmap_getnode - Get a individual node from a catmap |
| @@ -416,10 +417,11 @@ out_entry: | |||
| 416 | * @gfp_flags: memory allocation flags | 417 | * @gfp_flags: memory allocation flags |
| 417 | * | 418 | * |
| 418 | * Description: | 419 | * Description: |
| 419 | * Iterate through the catmap looking for the node associated with @offset; if | 420 | * Iterate through the catmap looking for the node associated with @offset. |
| 420 | * the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node, | 421 | * If 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 | * one will be created and inserted into the catmap. If the _CM_F_WALK flag is |
| 422 | * node on success, NULL on failure. | 423 | * set in @cm_flags and there is no associated node, the next highest node will |
| 424 | * be returned. Returns a pointer to the node on success, NULL on failure. | ||
| 423 | * | 425 | * |
| 424 | */ | 426 | */ |
| 425 | static struct netlbl_lsm_secattr_catmap *_netlbl_secattr_catmap_getnode( | 427 | static struct netlbl_lsm_secattr_catmap *_netlbl_secattr_catmap_getnode( |
| @@ -431,17 +433,22 @@ static struct netlbl_lsm_secattr_catmap *_netlbl_secattr_catmap_getnode( | |||
| 431 | struct netlbl_lsm_secattr_catmap *iter = *catmap; | 433 | struct netlbl_lsm_secattr_catmap *iter = *catmap; |
| 432 | struct netlbl_lsm_secattr_catmap *prev = NULL; | 434 | struct netlbl_lsm_secattr_catmap *prev = NULL; |
| 433 | 435 | ||
| 434 | if (iter == NULL || offset < iter->startbit) | 436 | if (iter == NULL) |
| 435 | goto secattr_catmap_getnode_alloc; | 437 | goto secattr_catmap_getnode_alloc; |
| 438 | if (offset < iter->startbit) | ||
| 439 | goto secattr_catmap_getnode_walk; | ||
| 436 | while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { | 440 | while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { |
| 437 | prev = iter; | 441 | prev = iter; |
| 438 | iter = iter->next; | 442 | iter = iter->next; |
| 439 | } | 443 | } |
| 440 | if (iter == NULL || offset < iter->startbit) | 444 | if (iter == NULL || offset < iter->startbit) |
| 441 | goto secattr_catmap_getnode_alloc; | 445 | goto secattr_catmap_getnode_walk; |
| 442 | 446 | ||
| 443 | return iter; | 447 | return iter; |
| 444 | 448 | ||
| 449 | secattr_catmap_getnode_walk: | ||
| 450 | if (cm_flags & _CM_F_WALK) | ||
| 451 | return iter; | ||
| 445 | secattr_catmap_getnode_alloc: | 452 | secattr_catmap_getnode_alloc: |
| 446 | if (!(cm_flags & _CM_F_ALLOC)) | 453 | if (!(cm_flags & _CM_F_ALLOC)) |
| 447 | return NULL; | 454 | return NULL; |
| @@ -476,43 +483,41 @@ int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, | |||
| 476 | u32 offset) | 483 | u32 offset) |
| 477 | { | 484 | { |
| 478 | struct netlbl_lsm_secattr_catmap *iter = catmap; | 485 | struct netlbl_lsm_secattr_catmap *iter = catmap; |
| 479 | u32 node_idx; | 486 | u32 idx; |
| 480 | u32 node_bit; | 487 | u32 bit; |
| 481 | NETLBL_CATMAP_MAPTYPE bitmap; | 488 | NETLBL_CATMAP_MAPTYPE bitmap; |
| 482 | 489 | ||
| 490 | iter = _netlbl_secattr_catmap_getnode(&catmap, offset, _CM_F_WALK, 0); | ||
| 491 | if (iter == NULL) | ||
| 492 | return -ENOENT; | ||
| 483 | if (offset > iter->startbit) { | 493 | if (offset > iter->startbit) { |
| 484 | while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { | 494 | offset -= iter->startbit; |
| 485 | iter = iter->next; | 495 | idx = offset / NETLBL_CATMAP_MAPSIZE; |
| 486 | if (iter == NULL) | 496 | bit = offset % NETLBL_CATMAP_MAPSIZE; |
| 487 | return -ENOENT; | ||
| 488 | } | ||
| 489 | node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; | ||
| 490 | node_bit = offset - iter->startbit - | ||
| 491 | (NETLBL_CATMAP_MAPSIZE * node_idx); | ||
| 492 | } else { | 497 | } else { |
| 493 | node_idx = 0; | 498 | idx = 0; |
| 494 | node_bit = 0; | 499 | bit = 0; |
| 495 | } | 500 | } |
| 496 | bitmap = iter->bitmap[node_idx] >> node_bit; | 501 | bitmap = iter->bitmap[idx] >> bit; |
| 497 | 502 | ||
| 498 | for (;;) { | 503 | for (;;) { |
| 499 | if (bitmap != 0) { | 504 | if (bitmap != 0) { |
| 500 | while ((bitmap & NETLBL_CATMAP_BIT) == 0) { | 505 | while ((bitmap & NETLBL_CATMAP_BIT) == 0) { |
| 501 | bitmap >>= 1; | 506 | bitmap >>= 1; |
| 502 | node_bit++; | 507 | bit++; |
| 503 | } | 508 | } |
| 504 | return iter->startbit + | 509 | return iter->startbit + |
| 505 | (NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit; | 510 | (NETLBL_CATMAP_MAPSIZE * idx) + bit; |
| 506 | } | 511 | } |
| 507 | if (++node_idx >= NETLBL_CATMAP_MAPCNT) { | 512 | if (++idx >= NETLBL_CATMAP_MAPCNT) { |
| 508 | if (iter->next != NULL) { | 513 | if (iter->next != NULL) { |
| 509 | iter = iter->next; | 514 | iter = iter->next; |
| 510 | node_idx = 0; | 515 | idx = 0; |
| 511 | } else | 516 | } else |
| 512 | return -ENOENT; | 517 | return -ENOENT; |
| 513 | } | 518 | } |
| 514 | bitmap = iter->bitmap[node_idx]; | 519 | bitmap = iter->bitmap[idx]; |
| 515 | node_bit = 0; | 520 | bit = 0; |
| 516 | } | 521 | } |
| 517 | 522 | ||
| 518 | return -ENOENT; | 523 | return -ENOENT; |
| @@ -532,46 +537,47 @@ int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap, | |||
| 532 | int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, | 537 | int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, |
| 533 | u32 offset) | 538 | u32 offset) |
| 534 | { | 539 | { |
| 535 | struct netlbl_lsm_secattr_catmap *iter = catmap; | 540 | struct netlbl_lsm_secattr_catmap *iter; |
| 536 | u32 node_idx; | 541 | struct netlbl_lsm_secattr_catmap *prev = NULL; |
| 537 | u32 node_bit; | 542 | u32 idx; |
| 543 | u32 bit; | ||
| 538 | NETLBL_CATMAP_MAPTYPE bitmask; | 544 | NETLBL_CATMAP_MAPTYPE bitmask; |
| 539 | NETLBL_CATMAP_MAPTYPE bitmap; | 545 | NETLBL_CATMAP_MAPTYPE bitmap; |
| 540 | 546 | ||
| 547 | iter = _netlbl_secattr_catmap_getnode(&catmap, offset, _CM_F_WALK, 0); | ||
| 548 | if (iter == NULL) | ||
| 549 | return -ENOENT; | ||
| 541 | if (offset > iter->startbit) { | 550 | if (offset > iter->startbit) { |
| 542 | while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) { | 551 | offset -= iter->startbit; |
| 543 | iter = iter->next; | 552 | idx = offset / NETLBL_CATMAP_MAPSIZE; |
| 544 | if (iter == NULL) | 553 | bit = offset % NETLBL_CATMAP_MAPSIZE; |
| 545 | return -ENOENT; | ||
| 546 | } | ||
| 547 | node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE; | ||
| 548 | node_bit = offset - iter->startbit - | ||
| 549 | (NETLBL_CATMAP_MAPSIZE * node_idx); | ||
| 550 | } else { | 554 | } else { |
| 551 | node_idx = 0; | 555 | idx = 0; |
| 552 | node_bit = 0; | 556 | bit = 0; |
| 553 | } | 557 | } |
| 554 | bitmask = NETLBL_CATMAP_BIT << node_bit; | 558 | bitmask = NETLBL_CATMAP_BIT << bit; |
| 555 | 559 | ||
| 556 | for (;;) { | 560 | for (;;) { |
| 557 | bitmap = iter->bitmap[node_idx]; | 561 | bitmap = iter->bitmap[idx]; |
| 558 | while (bitmask != 0 && (bitmap & bitmask) != 0) { | 562 | while (bitmask != 0 && (bitmap & bitmask) != 0) { |
| 559 | bitmask <<= 1; | 563 | bitmask <<= 1; |
| 560 | node_bit++; | 564 | bit++; |
| 561 | } | 565 | } |
| 562 | 566 | ||
| 563 | if (bitmask != 0) | 567 | if (prev && idx == 0 && bit == 0) |
| 568 | return prev->startbit + NETLBL_CATMAP_SIZE - 1; | ||
| 569 | else if (bitmask != 0) | ||
| 564 | return iter->startbit + | 570 | return iter->startbit + |
| 565 | (NETLBL_CATMAP_MAPSIZE * node_idx) + | 571 | (NETLBL_CATMAP_MAPSIZE * idx) + bit - 1; |
| 566 | node_bit - 1; | 572 | else if (++idx >= NETLBL_CATMAP_MAPCNT) { |
| 567 | else if (++node_idx >= NETLBL_CATMAP_MAPCNT) { | ||
| 568 | if (iter->next == NULL) | 573 | if (iter->next == NULL) |
| 569 | return iter->startbit + NETLBL_CATMAP_SIZE - 1; | 574 | return iter->startbit + NETLBL_CATMAP_SIZE - 1; |
| 575 | prev = iter; | ||
| 570 | iter = iter->next; | 576 | iter = iter->next; |
| 571 | node_idx = 0; | 577 | idx = 0; |
| 572 | } | 578 | } |
| 573 | bitmask = NETLBL_CATMAP_BIT; | 579 | bitmask = NETLBL_CATMAP_BIT; |
| 574 | node_bit = 0; | 580 | bit = 0; |
| 575 | } | 581 | } |
| 576 | 582 | ||
| 577 | return -ENOENT; | 583 | return -ENOENT; |
