aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2014-08-01 11:17:03 -0400
committerPaul Moore <pmoore@redhat.com>2014-08-01 11:17:03 -0400
commit41c3bd2039e0d7b3dc32313141773f20716ec524 (patch)
treeb47057cfbaeded529570a91b39f14007594203fc /net/netlabel
parent615e51fdda6f274e94b1e905fcaf6111e0d9aa20 (diff)
netlabel: fix a problem when setting bits below the previously lowest bit
The NetLabel category (catmap) functions have a problem in that they assume categories will be set in an increasing manner, e.g. the next category set will always be larger than the last. Unfortunately, this is not a valid assumption and could result in problems when attempting to set categories less than the startbit in the lowest catmap node. In some cases kernel panics and other nasties can result. This patch corrects the problem by checking for this and allocating a new catmap node instance and placing it at the front of the list. Cc: stable@vger.kernel.org Reported-by: Christian Evans <frodox@zoho.com> Signed-off-by: Paul Moore <pmoore@redhat.com> Tested-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'net/netlabel')
-rw-r--r--net/netlabel/netlabel_kapi.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 3045a964f39c..84e810bef39a 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -522,7 +522,7 @@ int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
522 522
523/** 523/**
524 * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap 524 * netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
525 * @catmap: the category bitmap 525 * @catmap: pointer to the category bitmap
526 * @bit: the bit to set 526 * @bit: the bit to set
527 * @flags: memory allocation flags 527 * @flags: memory allocation flags
528 * 528 *
@@ -531,18 +531,25 @@ int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
531 * negative values on failure. 531 * negative values on failure.
532 * 532 *
533 */ 533 */
534int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap, 534int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap,
535 u32 bit, 535 u32 bit,
536 gfp_t flags) 536 gfp_t flags)
537{ 537{
538 struct netlbl_lsm_secattr_catmap *iter = catmap; 538 struct netlbl_lsm_secattr_catmap *iter = *catmap;
539 u32 node_bit; 539 u32 node_bit;
540 u32 node_idx; 540 u32 node_idx;
541 541
542 while (iter->next != NULL && 542 while (iter->next != NULL &&
543 bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) 543 bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
544 iter = iter->next; 544 iter = iter->next;
545 if (bit >= (iter->startbit + NETLBL_CATMAP_SIZE)) { 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)) {
546 iter->next = netlbl_secattr_catmap_alloc(flags); 553 iter->next = netlbl_secattr_catmap_alloc(flags);
547 if (iter->next == NULL) 554 if (iter->next == NULL)
548 return -ENOMEM; 555 return -ENOMEM;
@@ -560,7 +567,7 @@ int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
560 567
561/** 568/**
562 * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap 569 * netlbl_secattr_catmap_setrng - Set a range of bits in a LSM secattr catmap
563 * @catmap: the category bitmap 570 * @catmap: pointer to the category bitmap
564 * @start: the starting bit 571 * @start: the starting bit
565 * @end: the last bit in the string 572 * @end: the last bit in the string
566 * @flags: memory allocation flags 573 * @flags: memory allocation flags
@@ -570,15 +577,16 @@ int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
570 * on success, negative values on failure. 577 * on success, negative values on failure.
571 * 578 *
572 */ 579 */
573int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, 580int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap **catmap,
574 u32 start, 581 u32 start,
575 u32 end, 582 u32 end,
576 gfp_t flags) 583 gfp_t flags)
577{ 584{
578 int ret_val = 0; 585 int ret_val = 0;
579 struct netlbl_lsm_secattr_catmap *iter = catmap; 586 struct netlbl_lsm_secattr_catmap *iter = *catmap;
580 u32 iter_max_spot; 587 u32 iter_max_spot;
581 u32 spot; 588 u32 spot;
589 u32 orig_spot = iter->startbit;
582 590
583 /* XXX - This could probably be made a bit faster by combining writes 591 /* XXX - This could probably be made a bit faster by combining writes
584 * to the catmap instead of setting a single bit each time, but for 592 * to the catmap instead of setting a single bit each time, but for
@@ -596,7 +604,9 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
596 iter = iter->next; 604 iter = iter->next;
597 iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE; 605 iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
598 } 606 }
599 ret_val = netlbl_secattr_catmap_setbit(iter, spot, flags); 607 ret_val = netlbl_secattr_catmap_setbit(&iter, spot, flags);
608 if (iter->startbit < orig_spot)
609 *catmap = iter;
600 } 610 }
601 611
602 return ret_val; 612 return ret_val;