Skip to content

Commit 3449213

Browse files
committed
pnv/xive: Fix possible undefined shift error in group size calculation
Coverity discovered a potential shift overflow in group size calculation in the case of a guest error. Add checks and logs to ensure a issues are caught. Make the group and crowd error checking code more similar to one another while here. Resolves: Coverity CID 1593724 Fixes: 9cb7f6e ("ppc/xive2: Support group-matching when looking for target") Reviewed-by: Cédric Le Goater <[email protected]> Signed-off-by: Nicholas Piggin <[email protected]>
1 parent 033a564 commit 3449213

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

hw/intc/xive.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,25 +1662,46 @@ uint32_t xive_get_vpgroup_size(uint32_t nvp_index)
16621662
* (starting with the least significant bits) in the NVP index
16631663
* gives the size of the group.
16641664
*/
1665-
return 1 << (ctz32(~nvp_index) + 1);
1665+
int first_zero = cto32(nvp_index);
1666+
if (first_zero >= 31) {
1667+
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid group index 0x%08x",
1668+
nvp_index);
1669+
return 0;
1670+
}
1671+
1672+
return 1U << (first_zero + 1);
16661673
}
16671674

16681675
static uint8_t xive_get_group_level(bool crowd, bool ignore,
16691676
uint32_t nvp_blk, uint32_t nvp_index)
16701677
{
1678+
int first_zero;
16711679
uint8_t level;
16721680

16731681
if (!ignore) {
16741682
g_assert(!crowd);
16751683
return 0;
16761684
}
16771685

1678-
level = (ctz32(~nvp_index) + 1) & 0b1111;
1686+
first_zero = cto32(nvp_index);
1687+
if (first_zero >= 31) {
1688+
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid group index 0x%08x",
1689+
nvp_index);
1690+
return 0;
1691+
}
1692+
1693+
level = (first_zero + 1) & 0b1111;
16791694
if (crowd) {
16801695
uint32_t blk;
16811696

16821697
/* crowd level is bit position of first 0 from the right in nvp_blk */
1683-
blk = ctz32(~nvp_blk) + 1;
1698+
first_zero = cto32(nvp_blk);
1699+
if (first_zero >= 31) {
1700+
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid crowd block 0x%08x",
1701+
nvp_blk);
1702+
return 0;
1703+
}
1704+
blk = first_zero + 1;
16841705

16851706
/*
16861707
* Supported crowd sizes are 2^1, 2^2, and 2^4. 2^3 is not supported.

hw/intc/xive2.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,13 +1153,15 @@ static bool xive2_vp_match_mask(uint32_t cam1, uint32_t cam2,
11531153

11541154
static uint8_t xive2_get_vp_block_mask(uint32_t nvt_blk, bool crowd)
11551155
{
1156-
uint8_t size, block_mask = 0b1111;
1156+
uint8_t block_mask = 0b1111;
11571157

11581158
/* 3 supported crowd sizes: 2, 4, 16 */
11591159
if (crowd) {
1160-
size = xive_get_vpgroup_size(nvt_blk);
1161-
if (size == 8) {
1162-
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid crowd size of 8n");
1160+
uint32_t size = xive_get_vpgroup_size(nvt_blk);
1161+
1162+
if (size != 2 && size != 4 && size != 16) {
1163+
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid crowd size of %d",
1164+
size);
11631165
return block_mask;
11641166
}
11651167
block_mask &= ~(size - 1);
@@ -1172,7 +1174,14 @@ static uint32_t xive2_get_vp_index_mask(uint32_t nvt_index, bool cam_ignore)
11721174
uint32_t index_mask = 0xFFFFFF; /* 24 bits */
11731175

11741176
if (cam_ignore) {
1175-
index_mask &= ~(xive_get_vpgroup_size(nvt_index) - 1);
1177+
uint32_t size = xive_get_vpgroup_size(nvt_index);
1178+
1179+
if (size < 2) {
1180+
qemu_log_mask(LOG_GUEST_ERROR, "XIVE: Invalid group size of %d",
1181+
size);
1182+
return index_mask;
1183+
}
1184+
index_mask &= ~(size - 1);
11761185
}
11771186
return index_mask;
11781187
}

0 commit comments

Comments
 (0)