s390/crc32-vx: Fix checksum calculation for small sizes
authorChristian Borntraeger <borntraeger@de.ibm.com>
Wed, 3 Aug 2016 15:55:00 +0000 (17:55 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 8 Aug 2016 13:41:31 +0000 (15:41 +0200)
The current prealign logic will fail for sizes < alignment,
as the new datalen passed to the vector function is smaller
than zero. Being a size_t this gets wrapped to a huge
number causing memory overruns and wrong data.

Let's add an early exit if the size is smaller than the minimal
size with alignment. This will also avoid calling the software
fallback twice for all sizes smaller than the minimum size
(prealign + remaining)

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Fixes: f848dbd3bc1a ("s390/crc32-vx: add crypto API module for optimized CRC-32 algorithms")
Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/crypto/crc32-vx.c

index 577ae1d4ae894e58c5e0c37cec32f77341e18735..2bad9d837029924b3e1955bce4da9c170192c0f0 100644 (file)
@@ -51,6 +51,9 @@ u32 crc32c_le_vgfm_16(u32 crc, unsigned char const *buf, size_t size);
                struct kernel_fpu vxstate;                                  \
                unsigned long prealign, aligned, remaining;                 \
                                                                            \
+               if (datalen < VX_MIN_LEN + VX_ALIGN_MASK)                   \
+                       return ___crc32_sw(crc, data, datalen);             \
+                                                                           \
                if ((unsigned long)data & VX_ALIGN_MASK) {                  \
                        prealign = VX_ALIGNMENT -                           \
                                  ((unsigned long)data & VX_ALIGN_MASK);    \
@@ -59,9 +62,6 @@ u32 crc32c_le_vgfm_16(u32 crc, unsigned char const *buf, size_t size);
                        data = (void *)((unsigned long)data + prealign);    \
                }                                                           \
                                                                            \
-               if (datalen < VX_MIN_LEN)                                   \
-                       return ___crc32_sw(crc, data, datalen);             \
-                                                                           \
                aligned = datalen & ~VX_ALIGN_MASK;                         \
                remaining = datalen & VX_ALIGN_MASK;                        \
                                                                            \