From: Zhou Xuemei zhouxuemei@wxiat.com
Sunway inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I5GFS3
--------------------------------
When csum_partial_copy_from_user is called in an interrupt, __copy_from_user will modify floating point register f10-f15 without restore register value. This will cause the value of the userspace register to be corrupted. Use memcpy() instead when called from kernel space.
Signed-off-by: Zhou Xuemei zhouxuemei@wxiat.com
Signed-off-by: Gu Zitao guzitao@wxiat.com --- arch/sw_64/lib/csum_partial_copy.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/sw_64/lib/csum_partial_copy.c b/arch/sw_64/lib/csum_partial_copy.c index 5e5274e82b2b..742dd63cdb70 100644 --- a/arch/sw_64/lib/csum_partial_copy.c +++ b/arch/sw_64/lib/csum_partial_copy.c @@ -61,7 +61,11 @@ csum_partial_cfu_dest_aligned(const unsigned long __user *src, unsigned long checksum = ~0U; int err = 0;
- err = __copy_from_user(dst, src, len+8); + if (likely(!uaccess_kernel())) + err = __copy_from_user(dst, src, len + 8); + else + memcpy(dst, src, len + 8); + while (len > 0) { word = *dst; checksum += word; @@ -89,7 +93,10 @@ csum_partial_cfu_dest_unaligned(const unsigned long __user *src, unsigned long checksum = ~0U; int err = 0;
- err = __copy_from_user(dst, src, len+8); + if (likely(!uaccess_kernel())) + err = __copy_from_user(dst, src, len + 8); + else + memcpy(dst, src, len + 8);
dst = (unsigned long *)((unsigned long)dst & (~7UL)); word = *dst;