aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2014-08-01 11:17:29 -0400
committerPaul Moore <pmoore@redhat.com>2014-08-01 11:17:29 -0400
commitd960a6184a92c8da70d26355bfcb5bd8ad637743 (patch)
tree119b2fd2674484a3228278d140f62d6d58f4aa13
parent4b8feff251da3d7058b5779e21b33a85c686b974 (diff)
netlabel: fix the catmap walking functions
The two NetLabel LSM secattr catmap walk functions didn't handle certain edge conditions correctly, causing incorrect security labels to be generated in some cases. This patch corrects these problems and converts the functions to use the new _netlbl_secattr_catmap_getnode() function in order to reduce the amount of repeated code. Cc: stable@vger.kernel.org Signed-off-by: Paul Moore <pmoore@redhat.com> Tested-by: Casey Schaufler <casey@schaufler-ca.com>
-rw-r--r--net/netlabel/netlabel_kapi.c102
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 */
425static struct netlbl_lsm_secattr_catmap *_netlbl_secattr_catmap_getnode( 427static 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
449secattr_catmap_getnode_walk:
450 if (cm_flags & _CM_F_WALK)
451 return iter;
445secattr_catmap_getnode_alloc: 452secattr_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,
532int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap, 537int 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;