ARM: PL08x: ensure pl08x_pre_boundary() works for any value of addr
pl08x_pre_boundary() was unsafe with addresses towards the top of memory space: boundary = ((addr >> PL08X_BOUNDARY_SHIFT) + 1) << PL08X_BOUNDARY_SHIFT; This can overflow a 32-bit number, producing zero. When it does: if (boundary < addr + len) return boundary - addr; else return len; results in (boundary - addr) returning either a large positive value. Also if addr + len overflows, this calculation also fails. We can fix this trivially as the only thing we're actually interested in is the value of the least significant PL08X_BOUNDARY_SHIFT bits: boundary_len = PL08X_BOUNDARY_SIZE - (addr & (PL08X_BOUNDARY_SIZE - 1)); gives us the number of bytes before 'addr' becomes a multiple of PL08X_BOUNDARY_SIZE. We can then just take the min() of the two calculated lengths. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Linus Walleij <linus.walleij@stericsson.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
parent
0059005f2c
commit
b61be8d728
@ -547,19 +547,15 @@ static void pl08x_fill_lli_for_desc(struct pl08x_driver_data *pl08x,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return number of bytes to fill to boundary, or len
|
* Return number of bytes to fill to boundary, or len.
|
||||||
|
* This calculation works for any value of addr.
|
||||||
*/
|
*/
|
||||||
static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
|
static inline size_t pl08x_pre_boundary(u32 addr, size_t len)
|
||||||
{
|
{
|
||||||
u32 boundary;
|
size_t boundary_len = PL08X_BOUNDARY_SIZE -
|
||||||
|
(addr & (PL08X_BOUNDARY_SIZE - 1));
|
||||||
|
|
||||||
boundary = ((addr >> PL08X_BOUNDARY_SHIFT) + 1)
|
return min(boundary_len, len);
|
||||||
<< PL08X_BOUNDARY_SHIFT;
|
|
||||||
|
|
||||||
if (boundary < addr + len)
|
|
||||||
return boundary - addr;
|
|
||||||
else
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user