From 6e41c585e38ff696de3a11509a0ad0a11150b0c3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 22 Jul 2020 22:14:36 -0400 Subject: unify generic instances of csum_partial_copy_nocheck() quite a few architectures have the same csum_partial_copy_nocheck() - simply memcpy() the data and then return the csum of the copy. hexagon, parisc, ia64, s390, um: explicitly spelled out that way. arc, arm64, csky, h8300, m68k/nommu, microblaze, mips/GENERIC_CSUM, nds32, nios2, openrisc, riscv, unicore32: end up picking the same thing spelled out in lib/checksum.h (with varying amounts of perversions along the way). everybody else (alpha, arm, c6x, m68k/mmu, mips/!GENERIC_CSUM, powerpc, sh, sparc, x86, xtensa) have non-generic variants. For all except c6x the declaration is in their asm/checksum.h. c6x uses the wrapper from asm-generic/checksum.h that would normally lead to the lib/checksum.h instance, but in case of c6x we end up using an asm function from arch/c6x instead. Screw that mess - have architectures with private instances define _HAVE_ARCH_CSUM_AND_COPY in their asm/checksum.h and have the default one right in net/checksum.h conditional on _HAVE_ARCH_CSUM_AND_COPY *not* defined. Signed-off-by: Al Viro --- arch/alpha/include/asm/checksum.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/alpha') diff --git a/arch/alpha/include/asm/checksum.h b/arch/alpha/include/asm/checksum.h index 0eac81624d01..7e8e4fa4362d 100644 --- a/arch/alpha/include/asm/checksum.h +++ b/arch/alpha/include/asm/checksum.h @@ -42,6 +42,7 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum); * better 64-bit) boundary */ #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_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); -- cgit v1.2.3-59-g8ed1b From cc44c17baf7f3f833d36b2f2a1edb1cc0b6f2cc4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 11 Jul 2020 00:12:07 -0400 Subject: csum_partial_copy_nocheck(): drop the last argument It's always 0. Note that we theoretically could use ~0U as well - result will be the same modulo 0xffff, _if_ the damn thing did the right thing for any value of initial sum; later we'll make use of that when convenient. However, unlike csum_and_copy_..._user(), there are instances that did not work for arbitrary initial sums; c6x is one such. Signed-off-by: Al Viro --- arch/alpha/include/asm/checksum.h | 2 +- arch/alpha/lib/csum_partial_copy.c | 4 ++-- arch/arm/include/asm/checksum.h | 2 +- arch/arm/lib/csumpartialcopy.S | 5 +++-- arch/c6x/include/asm/checksum.h | 2 +- arch/c6x/lib/csum_64plus.S | 4 +--- arch/m68k/include/asm/checksum.h | 3 +-- arch/m68k/lib/checksum.c | 3 ++- arch/mips/include/asm/checksum.h | 7 +++++-- arch/mips/lib/csum_partial.S | 4 ++-- arch/powerpc/include/asm/checksum.h | 4 ++-- arch/sh/include/asm/checksum_32.h | 5 ++--- arch/sparc/include/asm/checksum_32.h | 4 ++-- arch/sparc/include/asm/checksum_64.h | 8 ++++++-- arch/sparc/lib/csum_copy.S | 2 +- arch/x86/include/asm/checksum_32.h | 5 ++--- arch/x86/include/asm/checksum_64.h | 3 +-- arch/x86/lib/csum-wrappers_64.c | 4 ++-- arch/xtensa/include/asm/checksum.h | 5 ++--- drivers/net/ethernet/3com/typhoon.c | 3 +-- include/net/checksum.h | 4 ++-- lib/iov_iter.c | 2 +- net/core/skbuff.c | 4 ++-- net/ipv4/icmp.c | 2 +- net/ipv4/ip_output.c | 2 +- net/ipv4/raw.c | 2 +- net/ipv6/raw.c | 2 +- 27 files changed, 49 insertions(+), 48 deletions(-) (limited to 'arch/alpha') diff --git a/arch/alpha/include/asm/checksum.h b/arch/alpha/include/asm/checksum.h index 7e8e4fa4362d..84f9faea864a 100644 --- a/arch/alpha/include/asm/checksum.h +++ b/arch/alpha/include/asm/checksum.h @@ -45,7 +45,7 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum); #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_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); +__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len); /* diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index af1dad74e933..f363dc89fcbe 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c @@ -372,13 +372,13 @@ csum_and_copy_from_user(const void __user *src, void *dst, int len, EXPORT_SYMBOL(csum_and_copy_from_user); __wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) +csum_partial_copy_nocheck(const void *src, void *dst, int len) { __wsum checksum; mm_segment_t oldfs = get_fs(); set_fs(KERNEL_DS); checksum = csum_and_copy_from_user((__force const void __user *)src, - dst, len, sum, NULL); + dst, len, 0, NULL); set_fs(oldfs); return checksum; } diff --git a/arch/arm/include/asm/checksum.h b/arch/arm/include/asm/checksum.h index 53f769508540..7612b2bd4e9b 100644 --- a/arch/arm/include/asm/checksum.h +++ b/arch/arm/include/asm/checksum.h @@ -35,7 +35,7 @@ __wsum csum_partial(const void *buff, int len, __wsum sum); */ __wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); +csum_partial_copy_nocheck(const void *src, void *dst, int len); __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr); diff --git a/arch/arm/lib/csumpartialcopy.S b/arch/arm/lib/csumpartialcopy.S index 184d97254a7a..aab914fbc86b 100644 --- a/arch/arm/lib/csumpartialcopy.S +++ b/arch/arm/lib/csumpartialcopy.S @@ -9,13 +9,14 @@ .text -/* Function: __u32 csum_partial_copy_nocheck(const char *src, char *dst, int len, __u32 sum) - * Params : r0 = src, r1 = dst, r2 = len, r3 = checksum +/* Function: __u32 csum_partial_copy_nocheck(const char *src, char *dst, int len) + * Params : r0 = src, r1 = dst, r2 = len * Returns : r0 = new checksum */ .macro save_regs stmfd sp!, {r1, r4 - r8, lr} + mov r3, #0 .endm .macro load_regs diff --git a/arch/c6x/include/asm/checksum.h b/arch/c6x/include/asm/checksum.h index fa31bdc186b2..934918def632 100644 --- a/arch/c6x/include/asm/checksum.h +++ b/arch/c6x/include/asm/checksum.h @@ -27,7 +27,7 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, #define csum_tcpudp_nofold csum_tcpudp_nofold #define _HAVE_ARCH_CSUM_AND_COPY -extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); +extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len); #include diff --git a/arch/c6x/lib/csum_64plus.S b/arch/c6x/lib/csum_64plus.S index 9c07127485d1..57148866d8d3 100644 --- a/arch/c6x/lib/csum_64plus.S +++ b/arch/c6x/lib/csum_64plus.S @@ -24,7 +24,6 @@ ENTRY(csum_partial_copy_nocheck) MVC .S2 ILC,B30 - MV .D1X B6,A31 ; given csum ZERO .D1 A9 ; csum (a side) || ZERO .D2 B9 ; csum (b side) || SHRU .S2X A6,2,B5 ; len / 4 @@ -144,8 +143,7 @@ L91: SHRU .S2X A9,16,B4 SHRU .S1 A9,16,A0 [A0] BNOP .S1 L91,5 -L10: ADD .D1 A31,A9,A9 - MV .D1 A9,A4 +L10: MV .D1 A9,A4 BNOP .S2 B3,4 MVC .S2 B30,ILC diff --git a/arch/m68k/include/asm/checksum.h b/arch/m68k/include/asm/checksum.h index ab16881d84cb..d5e74c64b6cd 100644 --- a/arch/m68k/include/asm/checksum.h +++ b/arch/m68k/include/asm/checksum.h @@ -38,8 +38,7 @@ extern __wsum csum_and_copy_from_user(const void __user *src, int *csum_err); extern __wsum csum_partial_copy_nocheck(const void *src, - void *dst, int len, - __wsum sum); + void *dst, int len); /* * This is a version of ip_fast_csum() optimized for IP headers, diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c index 31797be9a3dc..86ddd2ee187d 100644 --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c @@ -324,9 +324,10 @@ EXPORT_SYMBOL(csum_and_copy_from_user); */ __wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) +csum_partial_copy_nocheck(const void *src, void *dst, int len) { unsigned long tmp1, tmp2; + __wsum sum = 0; __asm__("movel %2,%4\n\t" "btst #1,%4\n\t" /* Check alignment */ "jeq 2f\n\t" diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h index abdf1086873d..ec3159dbc1b3 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -102,8 +102,11 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, * we have just one address space, so this is identical to the above) */ #define _HAVE_ARCH_CSUM_AND_COPY -__wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum); +__wsum __csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); +static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len) +{ + return __csum_partial_copy_nocheck(src, dst, len, 0); +} /* * Fold a partial checksum without adding pseudo headers diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index 87fda0713b84..8d70855b0914 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S @@ -462,8 +462,8 @@ EXPORT_SYMBOL(csum_partial) lw errptr, 16(sp) #endif .if \__nocheck == 1 - FEXPORT(csum_partial_copy_nocheck) - EXPORT_SYMBOL(csum_partial_copy_nocheck) + FEXPORT(__csum_partial_copy_nocheck) + EXPORT_SYMBOL(__csum_partial_copy_nocheck) .endif move sum, zero move odd, zero diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h index d75fc5bf8f37..64299785f639 100644 --- a/arch/powerpc/include/asm/checksum.h +++ b/arch/powerpc/include/asm/checksum.h @@ -30,8 +30,8 @@ extern __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, __wsum sum, int *err_ptr); #define _HAVE_ARCH_CSUM_AND_COPY -#define csum_partial_copy_nocheck(src, dst, len, sum) \ - csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL) +#define csum_partial_copy_nocheck(src, dst, len) \ + csum_partial_copy_generic((src), (dst), (len), 0, NULL, NULL) /* diff --git a/arch/sh/include/asm/checksum_32.h b/arch/sh/include/asm/checksum_32.h index 87269642d78d..e8bf84d3b843 100644 --- a/arch/sh/include/asm/checksum_32.h +++ b/arch/sh/include/asm/checksum_32.h @@ -43,10 +43,9 @@ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, * access_ok(). */ static inline -__wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum) +__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len) { - return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); + return csum_partial_copy_generic(src, dst, len, 0, NULL, NULL); } #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER diff --git a/arch/sparc/include/asm/checksum_32.h b/arch/sparc/include/asm/checksum_32.h index 479a0b812af5..d21d114436ba 100644 --- a/arch/sparc/include/asm/checksum_32.h +++ b/arch/sparc/include/asm/checksum_32.h @@ -42,7 +42,7 @@ __wsum csum_partial(const void *buff, int len, __wsum sum); unsigned int __csum_partial_copy_sparc_generic (const unsigned char *, unsigned char *); static inline __wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) +csum_partial_copy_nocheck(const void *src, void *dst, int len) { register unsigned int ret asm("o0") = (unsigned int)src; register char *d asm("o1") = dst; @@ -52,7 +52,7 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) "call __csum_partial_copy_sparc_generic\n\t" " mov %6, %%g7\n" : "=&r" (ret), "=&r" (d), "=&r" (l) - : "0" (ret), "1" (d), "2" (l), "r" (sum) + : "0" (ret), "1" (d), "2" (l), "r" (0) : "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5", "g7", "memory", "cc"); diff --git a/arch/sparc/include/asm/checksum_64.h b/arch/sparc/include/asm/checksum_64.h index 0fa4433f5662..7aebdbe3ac96 100644 --- a/arch/sparc/include/asm/checksum_64.h +++ b/arch/sparc/include/asm/checksum_64.h @@ -38,8 +38,12 @@ __wsum csum_partial(const void * buff, int len, __wsum sum); * here even more important to align src and dst on a 32-bit (or even * better 64-bit) boundary */ -__wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum); +__wsum __csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); + +static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len) +{ + return __csum_partial_copy_nocheck(src, dst, len, 0); +} long __csum_partial_copy_from_user(const void __user *src, void *dst, int len, diff --git a/arch/sparc/lib/csum_copy.S b/arch/sparc/lib/csum_copy.S index 26c644ba3ecb..72c900d21b12 100644 --- a/arch/sparc/lib/csum_copy.S +++ b/arch/sparc/lib/csum_copy.S @@ -33,7 +33,7 @@ #endif #ifndef FUNC_NAME -#define FUNC_NAME csum_partial_copy_nocheck +#define FUNC_NAME __csum_partial_copy_nocheck #endif .register %g2, #scratch diff --git a/arch/x86/include/asm/checksum_32.h b/arch/x86/include/asm/checksum_32.h index 11624c8a9d8d..137a3033edcc 100644 --- a/arch/x86/include/asm/checksum_32.h +++ b/arch/x86/include/asm/checksum_32.h @@ -38,10 +38,9 @@ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, * If you use these functions directly please don't forget the * access_ok(). */ -static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum) +static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len) { - return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); + return csum_partial_copy_generic(src, dst, len, 0, NULL, NULL); } static inline __wsum csum_and_copy_from_user(const void __user *src, diff --git a/arch/x86/include/asm/checksum_64.h b/arch/x86/include/asm/checksum_64.h index 0a289b87e872..5339f5dfc776 100644 --- a/arch/x86/include/asm/checksum_64.h +++ b/arch/x86/include/asm/checksum_64.h @@ -139,8 +139,7 @@ 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_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum); +extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len); /** * ip_compute_csum - Compute an 16bit IP checksum. diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index ee63d7576fd2..245f929a1c2c 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -129,9 +129,9 @@ EXPORT_SYMBOL(csum_and_copy_to_user); * Returns an 32bit unfolded checksum of the buffer. */ __wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) +csum_partial_copy_nocheck(const void *src, void *dst, int len) { - return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); + return csum_partial_copy_generic(src, dst, len, 0, NULL, NULL); } EXPORT_SYMBOL(csum_partial_copy_nocheck); diff --git a/arch/xtensa/include/asm/checksum.h b/arch/xtensa/include/asm/checksum.h index 0c879099977f..dc09448935bf 100644 --- a/arch/xtensa/include/asm/checksum.h +++ b/arch/xtensa/include/asm/checksum.h @@ -47,10 +47,9 @@ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, * passed in an incorrect kernel address to one of these functions. */ static inline -__wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum) +__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len) { - return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); + return csum_partial_copy_generic(src, dst, len, 0, NULL, NULL); } #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER diff --git a/drivers/net/ethernet/3com/typhoon.c b/drivers/net/ethernet/3com/typhoon.c index d3b30bacc94e..049cc0158a64 100644 --- a/drivers/net/ethernet/3com/typhoon.c +++ b/drivers/net/ethernet/3com/typhoon.c @@ -1419,8 +1419,7 @@ typhoon_download_firmware(struct typhoon *tp) * the checksum, we can do this once, at the end. */ csum = csum_fold(csum_partial_copy_nocheck(image_data, - dpage, len, - 0)); + dpage, len)); iowrite32(len, ioaddr + TYPHOON_REG_BOOT_LENGTH); iowrite32(le16_to_cpu((__force __le16)csum), diff --git a/include/net/checksum.h b/include/net/checksum.h index db9d02b5f88a..1029191986e3 100644 --- a/include/net/checksum.h +++ b/include/net/checksum.h @@ -49,10 +49,10 @@ static __inline__ __wsum csum_and_copy_to_user #ifndef _HAVE_ARCH_CSUM_AND_COPY static inline __wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) +csum_partial_copy_nocheck(const void *src, void *dst, int len) { memcpy(dst, src, len); - return csum_partial(dst, len, sum); + return csum_partial(dst, len, 0); } #endif diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 5e40786c8f12..84f3a9156684 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -581,7 +581,7 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes, static __wsum csum_and_memcpy(void *to, const void *from, size_t len, __wsum sum, size_t off) { - __wsum next = csum_partial_copy_nocheck(from, to, len, 0); + __wsum next = csum_partial_copy_nocheck(from, to, len); return csum_block_add(sum, next, off); } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6e806da2913e..48dd4757b898 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2736,7 +2736,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, if (copy > len) copy = len; csum = csum_partial_copy_nocheck(skb->data + offset, to, - copy, 0); + copy); if ((len -= copy) == 0) return csum; offset += copy; @@ -2766,7 +2766,7 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, vaddr = kmap_atomic(p); csum2 = csum_partial_copy_nocheck(vaddr + p_off, to + copied, - p_len, 0); + p_len); kunmap_atomic(vaddr); csum = csum_block_add(csum, csum2, pos); pos += p_len; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index e23dd5fc2e73..bdaaee52c41b 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -381,7 +381,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, csum = csum_partial_copy_nocheck((void *)&icmp_param->data, (char *)icmph, - icmp_param->head_len, 0); + icmp_param->head_len); skb_queue_walk(&sk->sk_write_queue, skb1) { csum = csum_add(csum, skb1->csum); } diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 5bd059853376..bd79ea3e8c44 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1648,7 +1648,7 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, { __wsum csum; - csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0); + csum = csum_partial_copy_nocheck(dptr+offset, to, len); skb->csum = csum_block_add(skb->csum, csum, odd); return 0; } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 6fd4330287c2..79392154c30a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -478,7 +478,7 @@ static int raw_getfrag(void *from, char *to, int offset, int len, int odd, skb->csum = csum_block_add( skb->csum, csum_partial_copy_nocheck(rfv->hdr.c + offset, - to, copy, 0), + to, copy), odd); odd = 0; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 874f01cd7aec..6e4ab80a3b94 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -746,7 +746,7 @@ static int raw6_getfrag(void *from, char *to, int offset, int len, int odd, skb->csum = csum_block_add( skb->csum, csum_partial_copy_nocheck(rfv->c + offset, - to, copy, 0), + to, copy), odd); odd = 0; -- cgit v1.2.3-59-g8ed1b From c693cc4676a055c4126e487b30b0a96ea7ec9936 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 11 Jul 2020 00:27:49 -0400 Subject: 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 --- arch/alpha/include/asm/checksum.h | 2 +- arch/alpha/lib/csum_partial_copy.c | 25 ++++++------- arch/arm/include/asm/checksum.h | 13 ++++--- arch/m68k/include/asm/checksum.h | 3 +- arch/m68k/lib/checksum.c | 8 ++--- arch/mips/include/asm/checksum.h | 46 ++++++++++++------------ arch/parisc/include/asm/checksum.h | 20 ----------- arch/powerpc/include/asm/checksum.h | 4 +-- arch/powerpc/lib/checksum_wrappers.c | 68 +++++++++++------------------------- arch/sh/include/asm/checksum_32.h | 36 +++++++++---------- arch/sparc/include/asm/checksum_32.h | 65 ++++++++++++++++------------------ arch/sparc/include/asm/checksum_64.h | 14 ++++---- arch/x86/include/asm/checksum_32.h | 35 ++++++++----------- arch/x86/include/asm/checksum_64.h | 6 ++-- arch/x86/lib/csum-wrappers_64.c | 38 +++++++++----------- arch/x86/um/asm/checksum_32.h | 23 ------------ arch/xtensa/include/asm/checksum.h | 30 ++++++++-------- include/net/checksum.h | 15 ++++---- lib/iov_iter.c | 19 +++++----- 19 files changed, 183 insertions(+), 287 deletions(-) (limited to 'arch/alpha') diff --git a/arch/alpha/include/asm/checksum.h b/arch/alpha/include/asm/checksum.h index 84f9faea864a..99d631e146b2 100644 --- a/arch/alpha/include/asm/checksum.h +++ b/arch/alpha/include/asm/checksum.h @@ -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); diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index f363dc89fcbe..3c0e89c39ddb 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c @@ -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; } diff --git a/arch/arm/include/asm/checksum.h b/arch/arm/include/asm/checksum.h index 7612b2bd4e9b..1601c132b064 100644 --- a/arch/arm/include/asm/checksum.h +++ b/arch/arm/include/asm/checksum.h @@ -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; } /* diff --git a/arch/m68k/include/asm/checksum.h b/arch/m68k/include/asm/checksum.h index d5e74c64b6cd..692e7b6cc042 100644 --- a/arch/m68k/include/asm/checksum.h +++ b/arch/m68k/include/asm/checksum.h @@ -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); diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c index 86ddd2ee187d..3aeca261f622 100644 --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c @@ -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); diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h index ec3159dbc1b3..9dfce3522760 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -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) { + int err = 0; + __wsum sum = ~0U; + 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; - - return (__force __wsum)-1; /* invalid checksum */ + 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; } /* diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h index 522cd574c068..3c43baca7b39 100644 --- a/arch/parisc/include/asm/checksum.h +++ b/arch/parisc/include/asm/checksum.h @@ -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 diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h index 64299785f639..dba685d984c0 100644 --- a/arch/powerpc/include/asm/checksum.h +++ b/arch/powerpc/include/asm/checksum.h @@ -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) \ diff --git a/arch/powerpc/lib/checksum_wrappers.c b/arch/powerpc/lib/checksum_wrappers.c index fabe4db28726..b1faa82dd8af 100644 --- a/arch/powerpc/lib/checksum_wrappers.c +++ b/arch/powerpc/lib/checksum_wrappers.c @@ -12,82 +12,56 @@ #include __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(); - allow_read_from_user(src, len); - - *err_ptr = 0; - if (!len) { - csum = 0; - goto out; - } + if (unlikely(!access_ok(src, len))) + return 0; - if (unlikely((len < 0) || !access_ok(src, len))) { - *err_ptr = -EFAULT; - csum = (__force unsigned int)sum; - goto out; - } + allow_read_from_user(src, len); 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(); - allow_write_to_user(dst, len); - - *err_ptr = 0; - - if (!len) { - csum = 0; - goto out; - } + if (unlikely(!access_ok(dst, len))) + return 0; - if (unlikely((len < 0) || !access_ok(dst, len))) { - *err_ptr = -EFAULT; - csum = -1; /* invalid checksum */ - goto out; - } + allow_write_to_user(dst, len); 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; } diff --git a/arch/sh/include/asm/checksum_32.h b/arch/sh/include/asm/checksum_32.h index e8bf84d3b843..a08e8eb924ed 100644 --- a/arch/sh/include/asm/checksum_32.h +++ b/arch/sh/include/asm/checksum_32.h @@ -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); - - if (len) - *err_ptr = -EFAULT; - - return (__force __wsum)-1; /* invalid checksum */ + int err = 0; + __wsum sum = ~0U; + + 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 */ diff --git a/arch/sparc/include/asm/checksum_32.h b/arch/sparc/include/asm/checksum_32.h index d21d114436ba..b5873b7b7bf0 100644 --- a/arch/sparc/include/asm/checksum_32.h +++ b/arch/sparc/include/asm/checksum_32.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 diff --git a/arch/sparc/include/asm/checksum_64.h b/arch/sparc/include/asm/checksum_64.h index 7aebdbe3ac96..4d0bbff43e62 100644 --- a/arch/sparc/include/asm/checksum_64.h +++ b/arch/sparc/include/asm/checksum_64.h @@ -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; } diff --git a/arch/x86/include/asm/checksum_32.h b/arch/x86/include/asm/checksum_32.h index 137a3033edcc..5948cde9e4ad 100644 --- a/arch/x86/include/asm/checksum_32.h +++ b/arch/x86/include/asm/checksum_32.h @@ -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 */ diff --git a/arch/x86/include/asm/checksum_64.h b/arch/x86/include/asm/checksum_64.h index 5339f5dfc776..9af3aed54c6b 100644 --- a/arch/x86/include/asm/checksum_64.h +++ b/arch/x86/include/asm/checksum_64.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); /** diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index 245f929a1c2c..ae2fb87e2274 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -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); diff --git a/arch/x86/um/asm/checksum_32.h b/arch/x86/um/asm/checksum_32.h index b9ac7c9eb72c..0b13c2947ad1 100644 --- a/arch/x86/um/asm/checksum_32.h +++ b/arch/x86/um/asm/checksum_32.h @@ -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 diff --git a/arch/xtensa/include/asm/checksum.h b/arch/xtensa/include/asm/checksum.h index dc09448935bf..fe78fba7bd64 100644 --- a/arch/xtensa/include/asm/checksum.h +++ b/arch/xtensa/include/asm/checksum.h @@ -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 diff --git a/include/net/checksum.h b/include/net/checksum.h index 1029191986e3..0d05b9e8690b 100644 --- a/include/net/checksum.h +++ b/include/net/checksum.h @@ -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 diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 437fbc14c972..ccb247faf79b 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -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, -- cgit v1.2.3-59-g8ed1b From b712139543af98a91300c4e923b85d311cc77c44 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 12 Jul 2020 22:55:27 -0400 Subject: alpha: propagate the calling convention changes down to csum_partial_copy.c helpers get rid of set_fs() in csum_partial_copy_nocheck(), while we are at it - just take the part of csum_and_copy_from_user() sans the access_ok() check into a helper function and have csum_partial_copy_nocheck() call that. Signed-off-by: Al Viro --- arch/alpha/lib/csum_partial_copy.c | 157 ++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 88 deletions(-) (limited to 'arch/alpha') diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index 3c0e89c39ddb..dc68efbe9367 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c @@ -39,12 +39,11 @@ __asm__ __volatile__("insql %1,%2,%0":"=r" (z):"r" (x),"r" (y)) #define insqh(x,y,z) \ __asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y)) - -#define __get_user_u(x,ptr) \ +#define __get_word(insn,x,ptr) \ ({ \ long __guu_err; \ __asm__ __volatile__( \ - "1: ldq_u %0,%2\n" \ + "1: "#insn" %0,%2\n" \ "2:\n" \ EXC(1b,2b,%0,%1) \ : "=r"(x), "=r"(__guu_err) \ @@ -52,19 +51,6 @@ __asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y)) __guu_err; \ }) -#define __put_user_u(x,ptr) \ -({ \ - long __puu_err; \ - __asm__ __volatile__( \ - "1: stq_u %2,%1\n" \ - "2:\n" \ - EXC(1b,2b,$31,%0) \ - : "=r"(__puu_err) \ - : "m"(__m(addr)), "rJ"(x), "0"(0)); \ - __puu_err; \ -}) - - static inline unsigned short from64to16(unsigned long x) { /* Using extract instructions is a bit more efficient @@ -95,15 +81,15 @@ static inline unsigned short from64to16(unsigned long x) */ static inline unsigned long csum_partial_cfu_aligned(const unsigned long __user *src, unsigned long *dst, - long len, unsigned long checksum, - int *errp) + long len) { + unsigned long checksum = ~0U; unsigned long carry = 0; - int err = 0; while (len >= 0) { unsigned long word; - err |= __get_user(word, src); + if (__get_word(ldq, word, src)) + return 0; checksum += carry; src++; checksum += word; @@ -116,7 +102,8 @@ csum_partial_cfu_aligned(const unsigned long __user *src, unsigned long *dst, checksum += carry; if (len) { unsigned long word, tmp; - err |= __get_user(word, src); + if (__get_word(ldq, word, src)) + return 0; tmp = *dst; mskql(word, len, word); checksum += word; @@ -125,7 +112,6 @@ csum_partial_cfu_aligned(const unsigned long __user *src, unsigned long *dst, *dst = word | tmp; checksum += carry; } - if (err && errp) *errp = err; return checksum; } @@ -137,20 +123,21 @@ static inline unsigned long csum_partial_cfu_dest_aligned(const unsigned long __user *src, unsigned long *dst, unsigned long soff, - long len, unsigned long checksum, - int *errp) + long len) { unsigned long first; unsigned long word, carry; unsigned long lastsrc = 7+len+(unsigned long)src; - int err = 0; + unsigned long checksum = ~0U; - err |= __get_user_u(first,src); + if (__get_word(ldq_u, first,src)) + return 0; carry = 0; while (len >= 0) { unsigned long second; - err |= __get_user_u(second, src+1); + if (__get_word(ldq_u, second, src+1)) + return 0; extql(first, soff, word); len -= 8; src++; @@ -168,7 +155,8 @@ csum_partial_cfu_dest_aligned(const unsigned long __user *src, if (len) { unsigned long tmp; unsigned long second; - err |= __get_user_u(second, lastsrc); + if (__get_word(ldq_u, second, lastsrc)) + return 0; tmp = *dst; extql(first, soff, word); extqh(second, soff, first); @@ -180,7 +168,6 @@ csum_partial_cfu_dest_aligned(const unsigned long __user *src, *dst = word | tmp; checksum += carry; } - if (err && errp) *errp = err; return checksum; } @@ -191,18 +178,18 @@ static inline unsigned long csum_partial_cfu_src_aligned(const unsigned long __user *src, unsigned long *dst, unsigned long doff, - long len, unsigned long checksum, - unsigned long partial_dest, - int *errp) + long len, + unsigned long partial_dest) { unsigned long carry = 0; unsigned long word; unsigned long second_dest; - int err = 0; + unsigned long checksum = ~0U; mskql(partial_dest, doff, partial_dest); while (len >= 0) { - err |= __get_user(word, src); + if (__get_word(ldq, word, src)) + return 0; len -= 8; insql(word, doff, second_dest); checksum += carry; @@ -216,7 +203,8 @@ csum_partial_cfu_src_aligned(const unsigned long __user *src, len += 8; if (len) { checksum += carry; - err |= __get_user(word, src); + if (__get_word(ldq, word, src)) + return 0; mskql(word, len, word); len -= 8; checksum += word; @@ -237,7 +225,6 @@ csum_partial_cfu_src_aligned(const unsigned long __user *src, stq_u(partial_dest | second_dest, dst); out: checksum += carry; - if (err && errp) *errp = err; return checksum; } @@ -249,23 +236,23 @@ static inline unsigned long csum_partial_cfu_unaligned(const unsigned long __user * src, unsigned long * dst, unsigned long soff, unsigned long doff, - long len, unsigned long checksum, - unsigned long partial_dest, - int *errp) + long len, unsigned long partial_dest) { unsigned long carry = 0; unsigned long first; unsigned long lastsrc; - int err = 0; + unsigned long checksum = ~0U; - err |= __get_user_u(first, src); + if (__get_word(ldq_u, first, src)) + return 0; lastsrc = 7+len+(unsigned long)src; mskql(partial_dest, doff, partial_dest); while (len >= 0) { unsigned long second, word; unsigned long second_dest; - err |= __get_user_u(second, src+1); + if (__get_word(ldq_u, second, src+1)) + return 0; extql(first, soff, word); checksum += carry; len -= 8; @@ -286,7 +273,8 @@ csum_partial_cfu_unaligned(const unsigned long __user * src, unsigned long second, word; unsigned long second_dest; - err |= __get_user_u(second, lastsrc); + if (__get_word(ldq_u, second, lastsrc)) + return 0; extql(first, soff, word); extqh(second, soff, first); word |= first; @@ -307,7 +295,8 @@ csum_partial_cfu_unaligned(const unsigned long __user * src, unsigned long second, word; unsigned long second_dest; - err |= __get_user_u(second, lastsrc); + if (__get_word(ldq_u, second, lastsrc)) + return 0; extql(first, soff, word); extqh(second, soff, first); word |= first; @@ -320,63 +309,55 @@ csum_partial_cfu_unaligned(const unsigned long __user * src, stq_u(partial_dest | word | second_dest, dst); checksum += carry; } - if (err && errp) *errp = err; return checksum; } -__wsum -csum_and_copy_from_user(const void __user *src, void *dst, int len) +static __wsum __csum_and_copy(const void __user *src, void *dst, int len) { - 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)) - return 0; - if (!doff) { - if (!soff) - checksum = csum_partial_cfu_aligned( - (const unsigned long __user *) src, - (unsigned long *) dst, - len-8, checksum, &err); - else - checksum = csum_partial_cfu_dest_aligned( - (const unsigned long __user *) src, - (unsigned long *) dst, - soff, len-8, checksum, &err); - } else { - unsigned long partial_dest; - ldq_u(partial_dest, dst); - if (!soff) - checksum = csum_partial_cfu_src_aligned( - (const unsigned long __user *) src, - (unsigned long *) dst, - doff, len-8, checksum, - partial_dest, &err); - else - checksum = csum_partial_cfu_unaligned( - (const unsigned long __user *) src, - (unsigned long *) dst, - soff, doff, len-8, checksum, - partial_dest, &err); - } - checksum = err ? 0 : from64to16 (checksum); + unsigned long checksum; + + if (!doff) { + if (!soff) + checksum = csum_partial_cfu_aligned( + (const unsigned long __user *) src, + (unsigned long *) dst, len-8); + else + checksum = csum_partial_cfu_dest_aligned( + (const unsigned long __user *) src, + (unsigned long *) dst, + soff, len-8); + } else { + unsigned long partial_dest; + ldq_u(partial_dest, dst); + if (!soff) + checksum = csum_partial_cfu_src_aligned( + (const unsigned long __user *) src, + (unsigned long *) dst, + doff, len-8, partial_dest); + else + checksum = csum_partial_cfu_unaligned( + (const unsigned long __user *) src, + (unsigned long *) dst, + soff, doff, len-8, partial_dest); } - return (__force __wsum)checksum; + return (__force __wsum)from64to16 (checksum); +} + +__wsum +csum_and_copy_from_user(const void __user *src, void *dst, int len) +{ + if (!access_ok(src, len)) + return 0; + return __csum_and_copy(src, dst, len); } EXPORT_SYMBOL(csum_and_copy_from_user); __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len) { - __wsum checksum; - mm_segment_t oldfs = get_fs(); - set_fs(KERNEL_DS); - checksum = csum_and_copy_from_user((__force const void __user *)src, + return __csum_and_copy((__force const void __user *)src, dst, len); - set_fs(oldfs); - return checksum; } EXPORT_SYMBOL(csum_partial_copy_nocheck); -- cgit v1.2.3-59-g8ed1b