saner calling conventions for csum_and_copy_..._user()

All callers of these primitives will
	* discard anything we might've copied in case of error
	* ignore the csum value in case of error
	* always pass 0xffffffff as the initial sum, so the
resulting csum value (in case of success, that is) will never be 0.

That suggest the following calling conventions:
	* don't pass err_ptr - just return 0 on error.
	* don't bother with zeroing destination, etc. in case of error
	* don't pass the initial sum - just use 0xffffffff.

This commit does the minimal conversion in the instances of csum_and_copy_...();
the changes of actual asm code behind them are done later in the series.
Note that this asm code is often shared with csum_partial_copy_nocheck();
the difference is that csum_partial_copy_nocheck() passes 0 for initial
sum while csum_and_copy_..._user() pass 0xffffffff.  Fortunately, we are
free to pass 0xffffffff in all cases and subsequent patches will use that
freedom without any special comments.

A part that could be split off: parisc and uml/i386 claimed to have
csum_and_copy_to_user() instances of their own, but those were identical
to the generic one, so we simply drop them.  Not sure if it's worth
a separate commit...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2020-07-11 00:27:49 -04:00
Родитель 99a2c96d52
Коммит c693cc4676
19 изменённых файлов: 183 добавлений и 287 удалений

Просмотреть файл

@ -43,7 +43,7 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum);
*/
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
#define _HAVE_ARCH_CSUM_AND_COPY
__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *errp);
__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len);
__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len);

Просмотреть файл

@ -325,30 +325,27 @@ csum_partial_cfu_unaligned(const unsigned long __user * src,
}
__wsum
csum_and_copy_from_user(const void __user *src, void *dst, int len,
__wsum sum, int *errp)
csum_and_copy_from_user(const void __user *src, void *dst, int len)
{
unsigned long checksum = (__force u32) sum;
unsigned long checksum = ~0U;
unsigned long soff = 7 & (unsigned long) src;
unsigned long doff = 7 & (unsigned long) dst;
int err = 0;
if (len) {
if (!access_ok(src, len)) {
if (errp) *errp = -EFAULT;
memset(dst, 0, len);
return sum;
}
if (!access_ok(src, len))
return 0;
if (!doff) {
if (!soff)
checksum = csum_partial_cfu_aligned(
(const unsigned long __user *) src,
(unsigned long *) dst,
len-8, checksum, errp);
len-8, checksum, &err);
else
checksum = csum_partial_cfu_dest_aligned(
(const unsigned long __user *) src,
(unsigned long *) dst,
soff, len-8, checksum, errp);
soff, len-8, checksum, &err);
} else {
unsigned long partial_dest;
ldq_u(partial_dest, dst);
@ -357,15 +354,15 @@ csum_and_copy_from_user(const void __user *src, void *dst, int len,
(const unsigned long __user *) src,
(unsigned long *) dst,
doff, len-8, checksum,
partial_dest, errp);
partial_dest, &err);
else
checksum = csum_partial_cfu_unaligned(
(const unsigned long __user *) src,
(unsigned long *) dst,
soff, doff, len-8, checksum,
partial_dest, errp);
partial_dest, &err);
}
checksum = from64to16 (checksum);
checksum = err ? 0 : from64to16 (checksum);
}
return (__force __wsum)checksum;
}
@ -378,7 +375,7 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len)
mm_segment_t oldfs = get_fs();
set_fs(KERNEL_DS);
checksum = csum_and_copy_from_user((__force const void __user *)src,
dst, len, 0, NULL);
dst, len);
set_fs(oldfs);
return checksum;
}

Просмотреть файл

@ -43,16 +43,15 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum s
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
#define _HAVE_ARCH_CSUM_AND_COPY
static inline
__wsum csum_and_copy_from_user (const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr)
__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len)
{
if (access_ok(src, len))
return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
int err = 0;
if (len)
*err_ptr = -EFAULT;
if (!access_ok(src, len))
return 0;
return sum;
sum = csum_partial_copy_from_user(src, dst, len, ~0U, &err);
return err ? 0 : sum;
}
/*

Просмотреть файл

@ -34,8 +34,7 @@ __wsum csum_partial(const void *buff, int len, __wsum sum);
#define _HAVE_ARCH_CSUM_AND_COPY
extern __wsum csum_and_copy_from_user(const void __user *src,
void *dst,
int len, __wsum sum,
int *csum_err);
int len);
extern __wsum csum_partial_copy_nocheck(const void *src,
void *dst, int len);

Просмотреть файл

@ -129,8 +129,7 @@ EXPORT_SYMBOL(csum_partial);
*/
__wsum
csum_and_copy_from_user(const void __user *src, void *dst,
int len, __wsum sum, int *csum_err)
csum_and_copy_from_user(const void __user *src, void *dst, int len)
{
/*
* GCC doesn't like more than 10 operands for the asm
@ -138,6 +137,7 @@ csum_and_copy_from_user(const void __user *src, void *dst,
* code.
*/
unsigned long tmp1, tmp2;
__wsum sum = ~0U;
__asm__("movel %2,%4\n\t"
"btst #1,%4\n\t" /* Check alignment */
@ -311,9 +311,7 @@ csum_and_copy_from_user(const void __user *src, void *dst,
: "0" (sum), "1" (len), "2" (src), "3" (dst)
);
*csum_err = tmp2;
return(sum);
return tmp2 ? 0 : sum;
}
EXPORT_SYMBOL(csum_and_copy_from_user);

Просмотреть файл

@ -60,16 +60,15 @@ __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len,
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
static inline
__wsum csum_and_copy_from_user(const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr)
__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len)
{
if (access_ok(src, len))
return csum_partial_copy_from_user(src, dst, len, sum,
err_ptr);
if (len)
*err_ptr = -EFAULT;
__wsum sum = ~0U;
int err = 0;
return sum;
if (!access_ok(src, len))
return 0;
sum = csum_partial_copy_from_user(src, dst, len, sum, &err);
return err ? 0 : sum;
}
/*
@ -77,24 +76,23 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst,
*/
#define HAVE_CSUM_COPY_USER
static inline
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
__wsum sum, int *err_ptr)
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len)
{
might_fault();
if (access_ok(dst, len)) {
if (uaccess_kernel())
return __csum_partial_copy_kernel(src,
(__force void *)dst,
len, sum, err_ptr);
else
return __csum_partial_copy_to_user(src,
(__force void *)dst,
len, sum, err_ptr);
}
if (len)
*err_ptr = -EFAULT;
int err = 0;
__wsum sum = ~0U;
return (__force __wsum)-1; /* invalid checksum */
might_fault();
if (!access_ok(dst, len))
return 0;
if (uaccess_kernel())
sum = __csum_partial_copy_kernel(src,
(__force void *)dst,
len, sum, &err);
else
sum = __csum_partial_copy_to_user(src,
(__force void *)dst,
len, sum, &err);
return err ? 0 : sum;
}
/*

Просмотреть файл

@ -173,25 +173,5 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
return csum_fold(sum);
}
/*
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
static __inline__ __wsum csum_and_copy_to_user(const void *src,
void __user *dst,
int len, __wsum sum,
int *err_ptr)
{
/* code stolen from include/asm-mips64 */
sum = csum_partial(src, len, sum);
if (copy_to_user(dst, src, len)) {
*err_ptr = -EFAULT;
return (__force __wsum)-1;
}
return sum;
}
#endif

Просмотреть файл

@ -24,10 +24,10 @@ extern __wsum csum_partial_copy_generic(const void *src, void *dst,
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr);
int len);
#define HAVE_CSUM_COPY_USER
extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
int len, __wsum sum, int *err_ptr);
int len);
#define _HAVE_ARCH_CSUM_AND_COPY
#define csum_partial_copy_nocheck(src, dst, len) \

Просмотреть файл

@ -12,82 +12,56 @@
#include <linux/uaccess.h>
__wsum csum_and_copy_from_user(const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr)
int len)
{
unsigned int csum;
int err = 0;
might_sleep();
if (unlikely(!access_ok(src, len)))
return 0;
allow_read_from_user(src, len);
*err_ptr = 0;
if (!len) {
csum = 0;
goto out;
}
if (unlikely((len < 0) || !access_ok(src, len))) {
*err_ptr = -EFAULT;
csum = (__force unsigned int)sum;
goto out;
}
csum = csum_partial_copy_generic((void __force *)src, dst,
len, sum, err_ptr, NULL);
len, ~0U, &err, NULL);
if (unlikely(*err_ptr)) {
if (unlikely(err)) {
int missing = __copy_from_user(dst, src, len);
if (missing) {
memset(dst + len - missing, 0, missing);
*err_ptr = -EFAULT;
} else {
*err_ptr = 0;
}
csum = csum_partial(dst, len, sum);
if (missing)
csum = 0;
else
csum = csum_partial(dst, len, ~0U);
}
out:
prevent_read_from_user(src, len);
return (__force __wsum)csum;
}
EXPORT_SYMBOL(csum_and_copy_from_user);
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
__wsum sum, int *err_ptr)
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len)
{
unsigned int csum;
int err = 0;
might_sleep();
if (unlikely(!access_ok(dst, len)))
return 0;
allow_write_to_user(dst, len);
*err_ptr = 0;
if (!len) {
csum = 0;
goto out;
}
if (unlikely((len < 0) || !access_ok(dst, len))) {
*err_ptr = -EFAULT;
csum = -1; /* invalid checksum */
goto out;
}
csum = csum_partial_copy_generic(src, (void __force *)dst,
len, sum, NULL, err_ptr);
len, ~0U, NULL, &err);
if (unlikely(*err_ptr)) {
csum = csum_partial(src, len, sum);
if (unlikely(err)) {
csum = csum_partial(src, len, ~0U);
if (copy_to_user(dst, src, len)) {
*err_ptr = -EFAULT;
csum = -1; /* invalid checksum */
}
if (copy_to_user(dst, src, len))
csum = 0;
}
out:
prevent_write_to_user(dst, len);
return (__force __wsum)csum;
}

Просмотреть файл

@ -50,15 +50,16 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len)
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
static inline
__wsum csum_and_copy_from_user(const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr)
__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len)
{
if (access_ok(src, len))
return csum_partial_copy_generic((__force const void *)src, dst,
len, sum, err_ptr, NULL);
if (len)
*err_ptr = -EFAULT;
return sum;
int err = 0;
__wsum sum = ~0U;
if (!access_ok(src, len))
return 0;
sum = csum_partial_copy_generic((__force const void *)src, dst,
len, sum, &err, NULL);
return err ? 0 : sum;
}
/*
@ -199,16 +200,15 @@ static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
#define HAVE_CSUM_COPY_USER
static inline __wsum csum_and_copy_to_user(const void *src,
void __user *dst,
int len, __wsum sum,
int *err_ptr)
int len)
{
if (access_ok(dst, len))
return csum_partial_copy_generic((__force const void *)src,
dst, len, sum, NULL, err_ptr);
int err = 0;
__wsum sum = ~0U;
if (len)
*err_ptr = -EFAULT;
return (__force __wsum)-1; /* invalid checksum */
if (!access_ok(dst, len))
return 0;
sum = csum_partial_copy_generic((__force const void *)src,
dst, len, sum, NULL, &err);
return err ? 0 : sum;
}
#endif /* __ASM_SH_CHECKSUM_H */

Просмотреть файл

@ -60,19 +60,16 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len)
}
static inline __wsum
csum_and_copy_from_user(const void __user *src, void *dst, int len,
__wsum sum, int *err)
csum_and_copy_from_user(const void __user *src, void *dst, int len)
{
register unsigned long ret asm("o0") = (unsigned long)src;
register char *d asm("o1") = dst;
register int l asm("g1") = len;
register __wsum s asm("g7") = sum;
register __wsum s asm("g7") = ~0U;
int err = 0;
if (unlikely(!access_ok(src, len))) {
if (len)
*err = -EFAULT;
return sum;
}
if (unlikely(!access_ok(src, len)))
return 0;
__asm__ __volatile__ (
".section __ex_table,#alloc\n\t"
@ -83,42 +80,40 @@ csum_and_copy_from_user(const void __user *src, void *dst, int len,
"call __csum_partial_copy_sparc_generic\n\t"
" st %8, [%%sp + 64]\n"
: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (&err)
: "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5",
"cc", "memory");
return (__force __wsum)ret;
return err ? 0 : (__force __wsum)ret;
}
#define HAVE_CSUM_COPY_USER
static inline __wsum
csum_and_copy_to_user(const void *src, void __user *dst, int len,
__wsum sum, int *err)
csum_and_copy_to_user(const void *src, void __user *dst, int len)
{
if (!access_ok(dst, len)) {
*err = -EFAULT;
return sum;
} else {
register unsigned long ret asm("o0") = (unsigned long)src;
register char __user *d asm("o1") = dst;
register int l asm("g1") = len;
register __wsum s asm("g7") = sum;
register unsigned long ret asm("o0") = (unsigned long)src;
register char __user *d asm("o1") = dst;
register int l asm("g1") = len;
register __wsum s asm("g7") = ~0U;
int err = 0;
__asm__ __volatile__ (
".section __ex_table,#alloc\n\t"
".align 4\n\t"
".word 1f,1\n\t"
".previous\n"
"1:\n\t"
"call __csum_partial_copy_sparc_generic\n\t"
" st %8, [%%sp + 64]\n"
: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
: "o2", "o3", "o4", "o5", "o7",
"g2", "g3", "g4", "g5",
"cc", "memory");
return (__force __wsum)ret;
}
if (!access_ok(dst, len))
return 0;
__asm__ __volatile__ (
".section __ex_table,#alloc\n\t"
".align 4\n\t"
".word 1f,1\n\t"
".previous\n"
"1:\n\t"
"call __csum_partial_copy_sparc_generic\n\t"
" st %8, [%%sp + 64]\n"
: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (&err)
: "o2", "o3", "o4", "o5", "o7",
"g2", "g3", "g4", "g5",
"cc", "memory");
return err ? 0 : (__force __wsum)ret;
}
/* ihl is always 5 or greater, almost always is 5, and iph is word aligned

Просмотреть файл

@ -51,12 +51,11 @@ long __csum_partial_copy_from_user(const void __user *src,
static inline __wsum
csum_and_copy_from_user(const void __user *src,
void *dst, int len,
__wsum sum, int *err)
void *dst, int len)
{
long ret = __csum_partial_copy_from_user(src, dst, len, sum);
long ret = __csum_partial_copy_from_user(src, dst, len, ~0U);
if (ret < 0)
*err = -EFAULT;
return 0;
return (__force __wsum) ret;
}
@ -70,12 +69,11 @@ long __csum_partial_copy_to_user(const void *src,
static inline __wsum
csum_and_copy_to_user(const void *src,
void __user *dst, int len,
__wsum sum, int *err)
void __user *dst, int len)
{
long ret = __csum_partial_copy_to_user(src, dst, len, sum);
long ret = __csum_partial_copy_to_user(src, dst, len, ~0U);
if (ret < 0)
*err = -EFAULT;
return 0;
return (__force __wsum) ret;
}

Просмотреть файл

@ -44,22 +44,19 @@ static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst, int l
}
static inline __wsum csum_and_copy_from_user(const void __user *src,
void *dst, int len,
__wsum sum, int *err_ptr)
void *dst, int len)
{
__wsum ret;
int err = 0;
might_sleep();
if (!user_access_begin(src, len)) {
if (len)
*err_ptr = -EFAULT;
return sum;
}
if (!user_access_begin(src, len))
return 0;
ret = csum_partial_copy_generic((__force void *)src, dst,
len, sum, err_ptr, NULL);
len, ~0U, &err, NULL);
user_access_end();
return ret;
return err ? 0 : ret;
}
/*
@ -177,23 +174,19 @@ static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
*/
static inline __wsum csum_and_copy_to_user(const void *src,
void __user *dst,
int len, __wsum sum,
int *err_ptr)
int len)
{
__wsum ret;
int err = 0;
might_sleep();
if (user_access_begin(dst, len)) {
ret = csum_partial_copy_generic(src, (__force void *)dst,
len, sum, NULL, err_ptr);
user_access_end();
return ret;
}
if (!user_access_begin(dst, len))
return 0;
if (len)
*err_ptr = -EFAULT;
return (__force __wsum)-1; /* invalid checksum */
ret = csum_partial_copy_generic(src, (__force void *)dst,
len, ~0U, NULL, &err);
user_access_end();
return err ? 0 : ret;
}
#endif /* _ASM_X86_CHECKSUM_32_H */

Просмотреть файл

@ -135,10 +135,8 @@ extern __visible __wsum csum_partial_copy_generic(const void *src, const void *d
int *src_err_ptr, int *dst_err_ptr);
extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
int len, __wsum isum, int *errp);
extern __wsum csum_and_copy_to_user(const void *src, void __user *dst,
int len, __wsum isum, int *errp);
extern __wsum csum_and_copy_from_user(const void __user *src, void *dst, int len);
extern __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len);
extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len);
/**

Просмотреть файл

@ -22,13 +22,15 @@
*/
__wsum
csum_and_copy_from_user(const void __user *src, void *dst,
int len, __wsum isum, int *errp)
int len)
{
int err = 0;
__wsum isum = ~0U;
might_sleep();
*errp = 0;
if (!user_access_begin(src, len))
goto out_err;
return 0;
/*
* Why 6, not 7? To handle odd addresses aligned we
@ -53,20 +55,15 @@ csum_and_copy_from_user(const void __user *src, void *dst,
}
}
isum = csum_partial_copy_generic((__force const void *)src,
dst, len, isum, errp, NULL);
dst, len, isum, &err, NULL);
user_access_end();
if (unlikely(*errp))
goto out_err;
if (unlikely(err))
isum = 0;
return isum;
out:
user_access_end();
out_err:
*errp = -EFAULT;
memset(dst, 0, len);
return isum;
return 0;
}
EXPORT_SYMBOL(csum_and_copy_from_user);
@ -83,16 +80,15 @@ EXPORT_SYMBOL(csum_and_copy_from_user);
*/
__wsum
csum_and_copy_to_user(const void *src, void __user *dst,
int len, __wsum isum, int *errp)
int len)
{
__wsum ret;
__wsum ret, isum = ~0U;
int err = 0;
might_sleep();
if (!user_access_begin(dst, len)) {
*errp = -EFAULT;
if (!user_access_begin(dst, len))
return 0;
}
if (unlikely((unsigned long)dst & 6)) {
while (((unsigned long)dst & 6) && len >= 2) {
@ -107,15 +103,13 @@ csum_and_copy_to_user(const void *src, void __user *dst,
}
}
*errp = 0;
ret = csum_partial_copy_generic(src, (void __force *)dst,
len, isum, NULL, errp);
len, isum, NULL, &err);
user_access_end();
return ret;
return err ? 0 : ret;
out:
user_access_end();
*errp = -EFAULT;
return isum;
return 0;
}
EXPORT_SYMBOL(csum_and_copy_to_user);

Просмотреть файл

@ -35,27 +35,4 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
return csum_fold(sum);
}
/*
* Copy and checksum to user
*/
#define HAVE_CSUM_COPY_USER
static __inline__ __wsum csum_and_copy_to_user(const void *src,
void __user *dst,
int len, __wsum sum, int *err_ptr)
{
if (access_ok(dst, len)) {
if (copy_to_user(dst, src, len)) {
*err_ptr = -EFAULT;
return (__force __wsum)-1;
}
return csum_partial(src, len, sum);
}
if (len)
*err_ptr = -EFAULT;
return (__force __wsum)-1; /* invalid checksum */
}
#endif

Просмотреть файл

@ -55,14 +55,16 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len)
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
static inline
__wsum csum_and_copy_from_user(const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr)
int len)
{
if (access_ok(src, len))
return csum_partial_copy_generic((__force const void *)src, dst,
len, sum, err_ptr, NULL);
if (len)
*err_ptr = -EFAULT;
return sum;
int err = 0;
if (!access_ok(src, len))
return 0;
sum = csum_partial_copy_generic((__force const void *)src, dst,
len, ~0U, &err, NULL);
return err ? 0 : sum;
}
/*
@ -243,15 +245,15 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
*/
#define HAVE_CSUM_COPY_USER
static __inline__ __wsum csum_and_copy_to_user(const void *src,
void __user *dst, int len,
__wsum sum, int *err_ptr)
void __user *dst, int len)
{
if (access_ok(dst, len))
return csum_partial_copy_generic(src,dst,len,sum,NULL,err_ptr);
int err = 0;
__wsum sum = ~0U;
if (len)
*err_ptr = -EFAULT;
if (!access_ok(dst, len))
return 0;
return (__force __wsum)-1; /* invalid checksum */
sum = csum_partial_copy_generic(src,dst,len,sum,NULL,&err);
return err ? 0 : sum;
}
#endif

Просмотреть файл

@ -24,26 +24,23 @@
#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
static inline
__wsum csum_and_copy_from_user (const void __user *src, void *dst,
int len, __wsum sum, int *err_ptr)
int len)
{
if (copy_from_user(dst, src, len))
*err_ptr = -EFAULT;
return csum_partial(dst, len, sum);
return 0;
return csum_partial(dst, len, ~0U);
}
#endif
#ifndef HAVE_CSUM_COPY_USER
static __inline__ __wsum csum_and_copy_to_user
(const void *src, void __user *dst, int len, __wsum sum, int *err_ptr)
(const void *src, void __user *dst, int len)
{
sum = csum_partial(src, len, sum);
__wsum sum = csum_partial(src, len, ~0U);
if (copy_to_user(dst, src, len) == 0)
return sum;
if (len)
*err_ptr = -EFAULT;
return (__force __wsum)-1; /* invalid checksum */
return 0;
}
#endif

Просмотреть файл

@ -1449,15 +1449,14 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
return 0;
}
iterate_and_advance(i, bytes, v, ({
int err = 0;
next = csum_and_copy_from_user(v.iov_base,
(to += v.iov_len) - v.iov_len,
v.iov_len, ~0U, &err);
if (!err) {
v.iov_len);
if (next) {
sum = csum_block_add(sum, next, off);
off += v.iov_len;
}
err ? v.iov_len : 0;
next ? 0 : v.iov_len;
}), ({
char *p = kmap_atomic(v.bv_page);
sum = csum_and_memcpy((to += v.bv_len) - v.bv_len,
@ -1491,11 +1490,10 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum,
if (unlikely(i->count < bytes))
return false;
iterate_all_kinds(i, bytes, v, ({
int err = 0;
next = csum_and_copy_from_user(v.iov_base,
(to += v.iov_len) - v.iov_len,
v.iov_len, ~0U, &err);
if (err)
v.iov_len);
if (!next)
return false;
sum = csum_block_add(sum, next, off);
off += v.iov_len;
@ -1537,15 +1535,14 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *csump,
return 0;
}
iterate_and_advance(i, bytes, v, ({
int err = 0;
next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len,
v.iov_base,
v.iov_len, ~0U, &err);
if (!err) {
v.iov_len);
if (next) {
sum = csum_block_add(sum, next, off);
off += v.iov_len;
}
err ? v.iov_len : 0;
next ? 0 : v.iov_len;
}), ({
char *p = kmap_atomic(v.bv_page);
sum = csum_and_memcpy(p + v.bv_offset,