Skip to content

Commit 0f3604c

Browse files
Raphael Zimmergregkh
authored andcommitted
libceph: Fix potential out-of-bounds access in crush_decode()
commit 4c79fc2d598694bda845b46229c9d48b65042970 upstream. A message of type CEPH_MSG_OSD_MAP containing a crush map with at least one bucket has two fields holding the bucket algorithm. If the values in these two fields differ, an out-of-bounds access can occur. This is the case because the first algorithm field (alg) is used to allocate the correct amount of memory for a bucket of this type, while the second algorithm field inside the bucket (b->alg) is used in the subsequent processing. This patch fixes the issue by adding a check that compares alg and b->alg and aborts the processing in case they differ. Furthermore, b->alg is set to 0 in this case, because the destruction of the crush map also uses this field to determine the bucket type, which can again result in an out-of-bounds access when trying to free the memory pointed to by the fields of the bucket. To correctly free the memory allocated for the bucket in such a case, the corresponding call to kfree is moved from the algorithm-specific crush_destroy_bucket functions to the generic crush_destroy_bucket(). Cc: stable@vger.kernel.org Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de> Reviewed-by: Ilya Dryomov <idryomov@gmail.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f2f95e6 commit 0f3604c

2 files changed

Lines changed: 5 additions & 5 deletions

File tree

net/ceph/crush/crush.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,37 +47,32 @@ int crush_get_bucket_item_weight(const struct crush_bucket *b, int p)
4747
void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b)
4848
{
4949
kfree(b->h.items);
50-
kfree(b);
5150
}
5251

5352
void crush_destroy_bucket_list(struct crush_bucket_list *b)
5453
{
5554
kfree(b->item_weights);
5655
kfree(b->sum_weights);
5756
kfree(b->h.items);
58-
kfree(b);
5957
}
6058

6159
void crush_destroy_bucket_tree(struct crush_bucket_tree *b)
6260
{
6361
kfree(b->h.items);
6462
kfree(b->node_weights);
65-
kfree(b);
6663
}
6764

6865
void crush_destroy_bucket_straw(struct crush_bucket_straw *b)
6966
{
7067
kfree(b->straws);
7168
kfree(b->item_weights);
7269
kfree(b->h.items);
73-
kfree(b);
7470
}
7571

7672
void crush_destroy_bucket_straw2(struct crush_bucket_straw2 *b)
7773
{
7874
kfree(b->item_weights);
7975
kfree(b->h.items);
80-
kfree(b);
8176
}
8277

8378
void crush_destroy_bucket(struct crush_bucket *b)
@@ -99,6 +94,7 @@ void crush_destroy_bucket(struct crush_bucket *b)
9994
crush_destroy_bucket_straw2((struct crush_bucket_straw2 *)b);
10095
break;
10196
}
97+
kfree(b);
10298
}
10399

104100
/**

net/ceph/osdmap.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,10 @@ static struct crush_map *crush_decode(void *pbyval, void *end)
518518
b->id = ceph_decode_32(p);
519519
b->type = ceph_decode_16(p);
520520
b->alg = ceph_decode_8(p);
521+
if (b->alg != alg) {
522+
b->alg = 0;
523+
goto bad;
524+
}
521525
b->hash = ceph_decode_8(p);
522526
b->weight = ceph_decode_32(p);
523527
b->size = ceph_decode_32(p);

0 commit comments

Comments
 (0)