Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86: __memcpy_flushcache: fix wrong alignment if size > 2^32

The first "if" condition in __memcpy_flushcache is supposed to align the
"dest" variable to 8 bytes and copy data up to this alignment. However,
this condition may misbehave if "size" is greater than 4GiB.

The statement min_t(unsigned, size, ALIGN(dest, 8) - dest); casts both
arguments to unsigned int and selects the smaller one. However, the
cast truncates high bits in "size" and it results in misbehavior.

For example:

suppose that size == 0x100000001, dest == 0x200000002
min_t(unsigned, size, ALIGN(dest, 8) - dest) == min_t(0x1, 0xe) == 0x1;
...
dest += 0x1;

so we copy just one byte "and" dest remains unaligned.

This patch fixes the bug by replacing unsigned with size_t.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Mikulas Patocka and committed by
Linus Torvalds
a6823e4e 559089e0

+1 -1
+1 -1
arch/x86/lib/usercopy_64.c
··· 119 119 120 120 /* cache copy and flush to align dest */ 121 121 if (!IS_ALIGNED(dest, 8)) { 122 - unsigned len = min_t(unsigned, size, ALIGN(dest, 8) - dest); 122 + size_t len = min_t(size_t, size, ALIGN(dest, 8) - dest); 123 123 124 124 memcpy((void *) dest, (void *) source, len); 125 125 clean_cache_range((void *) dest, len);