aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/net/netlabel.h8
-rw-r--r--net/ipv4/cipso_ipv4.c6
-rw-r--r--net/netlabel/netlabel_kapi.c26
-rw-r--r--security/smack/smack_access.c2
4 files changed, 26 insertions, 16 deletions
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 4fe018c48ed9..1c40d658d008 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -394,10 +394,10 @@ 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_setbit(struct netlbl_lsm_secattr_catmap *catmap, 397int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap,
398 u32 bit, 398 u32 bit,
399 gfp_t flags); 399 gfp_t flags);
400int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, 400int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap **catmap,
401 u32 start, 401 u32 start,
402 u32 end, 402 u32 end,
403 gfp_t flags); 403 gfp_t flags);
@@ -505,14 +505,14 @@ static inline int netlbl_secattr_catmap_walk_rng(
505 return -ENOENT; 505 return -ENOENT;
506} 506}
507static inline int netlbl_secattr_catmap_setbit( 507static inline int netlbl_secattr_catmap_setbit(
508 struct netlbl_lsm_secattr_catmap *catmap, 508 struct netlbl_lsm_secattr_catmap **catmap,
509 u32 bit, 509 u32 bit,
510 gfp_t flags) 510 gfp_t flags)
511{ 511{
512 return 0; 512 return 0;
513} 513}
514static inline int netlbl_secattr_catmap_setrng( 514static inline int netlbl_secattr_catmap_setrng(
515 struct netlbl_lsm_secattr_catmap *catmap, 515 struct netlbl_lsm_secattr_catmap **catmap,
516 u32 start, 516 u32 start,
517 u32 end, 517 u32 end,
518 gfp_t flags) 518 gfp_t flags)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 69e77c8ff285..dd433c943537 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -973,7 +973,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
973 return -EPERM; 973 return -EPERM;
974 break; 974 break;
975 } 975 }
976 ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat, 976 ret_val = netlbl_secattr_catmap_setbit(&secattr->attr.mls.cat,
977 host_spot, 977 host_spot,
978 GFP_ATOMIC); 978 GFP_ATOMIC);
979 if (ret_val != 0) 979 if (ret_val != 0)
@@ -1075,7 +1075,7 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
1075 u32 iter; 1075 u32 iter;
1076 1076
1077 for (iter = 0; iter < net_cat_len; iter += 2) { 1077 for (iter = 0; iter < net_cat_len; iter += 2) {
1078 ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat, 1078 ret_val = netlbl_secattr_catmap_setbit(&secattr->attr.mls.cat,
1079 get_unaligned_be16(&net_cat[iter]), 1079 get_unaligned_be16(&net_cat[iter]),
1080 GFP_ATOMIC); 1080 GFP_ATOMIC);
1081 if (ret_val != 0) 1081 if (ret_val != 0)
@@ -1217,7 +1217,7 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
1217 else 1217 else
1218 cat_low = 0; 1218 cat_low = 0;
1219 1219
1220 ret_val = netlbl_secattr_catmap_setrng(secattr->attr.mls.cat, 1220 ret_val = netlbl_secattr_catmap_setrng(&secattr->attr.mls.cat,
1221 cat_low, 1221 cat_low,
1222 cat_high, 1222 cat_high,
1223 GFP_ATOMIC); 1223 GFP_ATOMIC);
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;
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 14293cd9b1e5..9ecf4f4b67a1 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -444,7 +444,7 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
444 for (m = 0x80; m != 0; m >>= 1, cat++) { 444 for (m = 0x80; m != 0; m >>= 1, cat++) {
445 if ((m & *cp) == 0) 445 if ((m & *cp) == 0)
446 continue; 446 continue;
447 rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat, 447 rc = netlbl_secattr_catmap_setbit(&sap->attr.mls.cat,
448 cat, GFP_ATOMIC); 448 cat, GFP_ATOMIC);
449 if (rc < 0) { 449 if (rc < 0) {
450 netlbl_secattr_catmap_free(sap->attr.mls.cat); 450 netlbl_secattr_catmap_free(sap->attr.mls.cat);