Skip to content

Commit 41c3bd2

Browse files
committed
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: [email protected] Reported-by: Christian Evans <[email protected]> Signed-off-by: Paul Moore <[email protected]> Tested-by: Casey Schaufler <[email protected]>
1 parent 615e51f commit 41c3bd2

File tree

4 files changed

+26
-16
lines changed

4 files changed

+26
-16
lines changed

include/net/netlabel.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,10 @@ int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
394394
u32 offset);
395395
int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
396396
u32 offset);
397-
int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
397+
int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap,
398398
u32 bit,
399399
gfp_t flags);
400-
int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
400+
int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap **catmap,
401401
u32 start,
402402
u32 end,
403403
gfp_t flags);
@@ -505,14 +505,14 @@ static inline int netlbl_secattr_catmap_walk_rng(
505505
return -ENOENT;
506506
}
507507
static inline int netlbl_secattr_catmap_setbit(
508-
struct netlbl_lsm_secattr_catmap *catmap,
508+
struct netlbl_lsm_secattr_catmap **catmap,
509509
u32 bit,
510510
gfp_t flags)
511511
{
512512
return 0;
513513
}
514514
static inline int netlbl_secattr_catmap_setrng(
515-
struct netlbl_lsm_secattr_catmap *catmap,
515+
struct netlbl_lsm_secattr_catmap **catmap,
516516
u32 start,
517517
u32 end,
518518
gfp_t flags)

net/ipv4/cipso_ipv4.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,7 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
973973
return -EPERM;
974974
break;
975975
}
976-
ret_val = netlbl_secattr_catmap_setbit(secattr->attr.mls.cat,
976+
ret_val = netlbl_secattr_catmap_setbit(&secattr->attr.mls.cat,
977977
host_spot,
978978
GFP_ATOMIC);
979979
if (ret_val != 0)
@@ -1075,7 +1075,7 @@ static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
10751075
u32 iter;
10761076

10771077
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,
10791079
get_unaligned_be16(&net_cat[iter]),
10801080
GFP_ATOMIC);
10811081
if (ret_val != 0)
@@ -1217,7 +1217,7 @@ static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
12171217
else
12181218
cat_low = 0;
12191219

1220-
ret_val = netlbl_secattr_catmap_setrng(secattr->attr.mls.cat,
1220+
ret_val = netlbl_secattr_catmap_setrng(&secattr->attr.mls.cat,
12211221
cat_low,
12221222
cat_high,
12231223
GFP_ATOMIC);

net/netlabel/netlabel_kapi.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
522522

523523
/**
524524
* netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
525-
* @catmap: the category bitmap
525+
* @catmap: pointer to the category bitmap
526526
* @bit: the bit to set
527527
* @flags: memory allocation flags
528528
*
@@ -531,18 +531,25 @@ int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
531531
* negative values on failure.
532532
*
533533
*/
534-
int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
534+
int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap,
535535
u32 bit,
536536
gfp_t flags)
537537
{
538-
struct netlbl_lsm_secattr_catmap *iter = catmap;
538+
struct netlbl_lsm_secattr_catmap *iter = *catmap;
539539
u32 node_bit;
540540
u32 node_idx;
541541

542542
while (iter->next != NULL &&
543543
bit >= (iter->startbit + NETLBL_CATMAP_SIZE))
544544
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)) {
546553
iter->next = netlbl_secattr_catmap_alloc(flags);
547554
if (iter->next == NULL)
548555
return -ENOMEM;
@@ -560,7 +567,7 @@ int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
560567

561568
/**
562569
* 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
564571
* @start: the starting bit
565572
* @end: the last bit in the string
566573
* @flags: memory allocation flags
@@ -570,15 +577,16 @@ int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap *catmap,
570577
* on success, negative values on failure.
571578
*
572579
*/
573-
int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
580+
int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap **catmap,
574581
u32 start,
575582
u32 end,
576583
gfp_t flags)
577584
{
578585
int ret_val = 0;
579-
struct netlbl_lsm_secattr_catmap *iter = catmap;
586+
struct netlbl_lsm_secattr_catmap *iter = *catmap;
580587
u32 iter_max_spot;
581588
u32 spot;
589+
u32 orig_spot = iter->startbit;
582590

583591
/* XXX - This could probably be made a bit faster by combining writes
584592
* 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,
596604
iter = iter->next;
597605
iter_max_spot = iter->startbit + NETLBL_CATMAP_SIZE;
598606
}
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;
600610
}
601611

602612
return ret_val;

security/smack/smack_access.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap,
444444
for (m = 0x80; m != 0; m >>= 1, cat++) {
445445
if ((m & *cp) == 0)
446446
continue;
447-
rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
447+
rc = netlbl_secattr_catmap_setbit(&sap->attr.mls.cat,
448448
cat, GFP_ATOMIC);
449449
if (rc < 0) {
450450
netlbl_secattr_catmap_free(sap->attr.mls.cat);

0 commit comments

Comments
 (0)