mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
4b8feff251
commit
d960a6184a
|
@ -407,6 +407,7 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
|
||||||
|
|
||||||
#define _CM_F_NONE 0x00000000
|
#define _CM_F_NONE 0x00000000
|
||||||
#define _CM_F_ALLOC 0x00000001
|
#define _CM_F_ALLOC 0x00000001
|
||||||
|
#define _CM_F_WALK 0x00000002
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _netlbl_secattr_catmap_getnode - Get a individual node from a catmap
|
* _netlbl_secattr_catmap_getnode - Get a individual node from a catmap
|
||||||
|
@ -416,10 +417,11 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
|
||||||
* @gfp_flags: memory allocation flags
|
* @gfp_flags: memory allocation flags
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Iterate through the catmap looking for the node associated with @offset; if
|
* Iterate through the catmap looking for the node associated with @offset.
|
||||||
* the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node,
|
* If the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node,
|
||||||
* one will be created and inserted into the catmap. Returns a pointer to the
|
* one will be created and inserted into the catmap. If the _CM_F_WALK flag is
|
||||||
* node on success, NULL on failure.
|
* set in @cm_flags and there is no associated node, the next highest node will
|
||||||
|
* be returned. Returns a pointer to the node on success, NULL on failure.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static struct netlbl_lsm_secattr_catmap *_netlbl_secattr_catmap_getnode(
|
static struct netlbl_lsm_secattr_catmap *_netlbl_secattr_catmap_getnode(
|
||||||
|
@ -431,17 +433,22 @@ static struct netlbl_lsm_secattr_catmap *_netlbl_secattr_catmap_getnode(
|
||||||
struct netlbl_lsm_secattr_catmap *iter = *catmap;
|
struct netlbl_lsm_secattr_catmap *iter = *catmap;
|
||||||
struct netlbl_lsm_secattr_catmap *prev = NULL;
|
struct netlbl_lsm_secattr_catmap *prev = NULL;
|
||||||
|
|
||||||
if (iter == NULL || offset < iter->startbit)
|
if (iter == NULL)
|
||||||
goto secattr_catmap_getnode_alloc;
|
goto secattr_catmap_getnode_alloc;
|
||||||
|
if (offset < iter->startbit)
|
||||||
|
goto secattr_catmap_getnode_walk;
|
||||||
while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
|
while (iter && offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
|
||||||
prev = iter;
|
prev = iter;
|
||||||
iter = iter->next;
|
iter = iter->next;
|
||||||
}
|
}
|
||||||
if (iter == NULL || offset < iter->startbit)
|
if (iter == NULL || offset < iter->startbit)
|
||||||
goto secattr_catmap_getnode_alloc;
|
goto secattr_catmap_getnode_walk;
|
||||||
|
|
||||||
return iter;
|
return iter;
|
||||||
|
|
||||||
|
secattr_catmap_getnode_walk:
|
||||||
|
if (cm_flags & _CM_F_WALK)
|
||||||
|
return iter;
|
||||||
secattr_catmap_getnode_alloc:
|
secattr_catmap_getnode_alloc:
|
||||||
if (!(cm_flags & _CM_F_ALLOC))
|
if (!(cm_flags & _CM_F_ALLOC))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -476,43 +483,41 @@ int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
|
||||||
u32 offset)
|
u32 offset)
|
||||||
{
|
{
|
||||||
struct netlbl_lsm_secattr_catmap *iter = catmap;
|
struct netlbl_lsm_secattr_catmap *iter = catmap;
|
||||||
u32 node_idx;
|
u32 idx;
|
||||||
u32 node_bit;
|
u32 bit;
|
||||||
NETLBL_CATMAP_MAPTYPE bitmap;
|
NETLBL_CATMAP_MAPTYPE bitmap;
|
||||||
|
|
||||||
|
iter = _netlbl_secattr_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
|
||||||
|
if (iter == NULL)
|
||||||
|
return -ENOENT;
|
||||||
if (offset > iter->startbit) {
|
if (offset > iter->startbit) {
|
||||||
while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
|
offset -= iter->startbit;
|
||||||
iter = iter->next;
|
idx = offset / NETLBL_CATMAP_MAPSIZE;
|
||||||
if (iter == NULL)
|
bit = offset % NETLBL_CATMAP_MAPSIZE;
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
|
|
||||||
node_bit = offset - iter->startbit -
|
|
||||||
(NETLBL_CATMAP_MAPSIZE * node_idx);
|
|
||||||
} else {
|
} else {
|
||||||
node_idx = 0;
|
idx = 0;
|
||||||
node_bit = 0;
|
bit = 0;
|
||||||
}
|
}
|
||||||
bitmap = iter->bitmap[node_idx] >> node_bit;
|
bitmap = iter->bitmap[idx] >> bit;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (bitmap != 0) {
|
if (bitmap != 0) {
|
||||||
while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
|
while ((bitmap & NETLBL_CATMAP_BIT) == 0) {
|
||||||
bitmap >>= 1;
|
bitmap >>= 1;
|
||||||
node_bit++;
|
bit++;
|
||||||
}
|
}
|
||||||
return iter->startbit +
|
return iter->startbit +
|
||||||
(NETLBL_CATMAP_MAPSIZE * node_idx) + node_bit;
|
(NETLBL_CATMAP_MAPSIZE * idx) + bit;
|
||||||
}
|
}
|
||||||
if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
|
if (++idx >= NETLBL_CATMAP_MAPCNT) {
|
||||||
if (iter->next != NULL) {
|
if (iter->next != NULL) {
|
||||||
iter = iter->next;
|
iter = iter->next;
|
||||||
node_idx = 0;
|
idx = 0;
|
||||||
} else
|
} else
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
bitmap = iter->bitmap[node_idx];
|
bitmap = iter->bitmap[idx];
|
||||||
node_bit = 0;
|
bit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -532,46 +537,47 @@ int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
|
||||||
int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
|
int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
|
||||||
u32 offset)
|
u32 offset)
|
||||||
{
|
{
|
||||||
struct netlbl_lsm_secattr_catmap *iter = catmap;
|
struct netlbl_lsm_secattr_catmap *iter;
|
||||||
u32 node_idx;
|
struct netlbl_lsm_secattr_catmap *prev = NULL;
|
||||||
u32 node_bit;
|
u32 idx;
|
||||||
|
u32 bit;
|
||||||
NETLBL_CATMAP_MAPTYPE bitmask;
|
NETLBL_CATMAP_MAPTYPE bitmask;
|
||||||
NETLBL_CATMAP_MAPTYPE bitmap;
|
NETLBL_CATMAP_MAPTYPE bitmap;
|
||||||
|
|
||||||
|
iter = _netlbl_secattr_catmap_getnode(&catmap, offset, _CM_F_WALK, 0);
|
||||||
|
if (iter == NULL)
|
||||||
|
return -ENOENT;
|
||||||
if (offset > iter->startbit) {
|
if (offset > iter->startbit) {
|
||||||
while (offset >= (iter->startbit + NETLBL_CATMAP_SIZE)) {
|
offset -= iter->startbit;
|
||||||
iter = iter->next;
|
idx = offset / NETLBL_CATMAP_MAPSIZE;
|
||||||
if (iter == NULL)
|
bit = offset % NETLBL_CATMAP_MAPSIZE;
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
node_idx = (offset - iter->startbit) / NETLBL_CATMAP_MAPSIZE;
|
|
||||||
node_bit = offset - iter->startbit -
|
|
||||||
(NETLBL_CATMAP_MAPSIZE * node_idx);
|
|
||||||
} else {
|
} else {
|
||||||
node_idx = 0;
|
idx = 0;
|
||||||
node_bit = 0;
|
bit = 0;
|
||||||
}
|
}
|
||||||
bitmask = NETLBL_CATMAP_BIT << node_bit;
|
bitmask = NETLBL_CATMAP_BIT << bit;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bitmap = iter->bitmap[node_idx];
|
bitmap = iter->bitmap[idx];
|
||||||
while (bitmask != 0 && (bitmap & bitmask) != 0) {
|
while (bitmask != 0 && (bitmap & bitmask) != 0) {
|
||||||
bitmask <<= 1;
|
bitmask <<= 1;
|
||||||
node_bit++;
|
bit++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitmask != 0)
|
if (prev && idx == 0 && bit == 0)
|
||||||
|
return prev->startbit + NETLBL_CATMAP_SIZE - 1;
|
||||||
|
else if (bitmask != 0)
|
||||||
return iter->startbit +
|
return iter->startbit +
|
||||||
(NETLBL_CATMAP_MAPSIZE * node_idx) +
|
(NETLBL_CATMAP_MAPSIZE * idx) + bit - 1;
|
||||||
node_bit - 1;
|
else if (++idx >= NETLBL_CATMAP_MAPCNT) {
|
||||||
else if (++node_idx >= NETLBL_CATMAP_MAPCNT) {
|
|
||||||
if (iter->next == NULL)
|
if (iter->next == NULL)
|
||||||
return iter->startbit + NETLBL_CATMAP_SIZE - 1;
|
return iter->startbit + NETLBL_CATMAP_SIZE - 1;
|
||||||
|
prev = iter;
|
||||||
iter = iter->next;
|
iter = iter->next;
|
||||||
node_idx = 0;
|
idx = 0;
|
||||||
}
|
}
|
||||||
bitmask = NETLBL_CATMAP_BIT;
|
bitmask = NETLBL_CATMAP_BIT;
|
||||||
node_bit = 0;
|
bit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
Loading…
Reference in New Issue