From: Russell King - ARM Linux Date: Mon, 3 Jan 2011 22:42:14 +0000 (+0000) Subject: ARM: PL08x: ensure pl08x_pre_boundary() works for any value of addr X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=b61be8d728abad7fd98e62e98f22325f8f254b51;p=linux-beck.git 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 Acked-by: Linus Walleij Signed-off-by: Dan Williams --- diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index f61940434669..7c327c315878 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -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) { - u32 boundary; + size_t boundary_len = PL08X_BOUNDARY_SIZE - + (addr & (PL08X_BOUNDARY_SIZE - 1)); - boundary = ((addr >> PL08X_BOUNDARY_SHIFT) + 1) - << PL08X_BOUNDARY_SHIFT; - - if (boundary < addr + len) - return boundary - addr; - else - return len; + return min(boundary_len, len); } /*