From 2a89b674fd6834dacf2a6edfbdf5607c163dd36e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 19 Mar 2020 13:19:34 -0400 Subject: get rid of csum_partial_copy_to_user() For historical reasons some architectures call their csum_and_copy_to_user() csum_partial_copy_to_user() instead (and supply a macro defining the former as the latter). That's the last remnants of old experiment that went nowhere; time to bury them. Rename those to csum_and_copy_to_user() and get rid of the macros. Signed-off-by: Al Viro --- arch/sparc/include/asm/checksum_32.h | 7 +++---- arch/x86/include/asm/checksum_64.h | 4 +--- arch/x86/lib/csum-wrappers_64.c | 6 +++--- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/checksum_32.h b/arch/sparc/include/asm/checksum_32.h index 5fc98d80b03b..450ddfb444c8 100644 --- a/arch/sparc/include/asm/checksum_32.h +++ b/arch/sparc/include/asm/checksum_32.h @@ -83,8 +83,10 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len, return (__force __wsum)ret; } +#define HAVE_CSUM_COPY_USER + static inline __wsum -csum_partial_copy_to_user(const void *src, void __user *dst, int len, +csum_and_copy_to_user(const void *src, void __user *dst, int len, __wsum sum, int *err) { if (!access_ok(dst, len)) { @@ -113,9 +115,6 @@ csum_partial_copy_to_user(const void *src, void __user *dst, int len, } } -#define HAVE_CSUM_COPY_USER -#define csum_and_copy_to_user csum_partial_copy_to_user - /* ihl is always 5 or greater, almost always is 5, and iph is word aligned * the majority of the time. */ diff --git a/arch/x86/include/asm/checksum_64.h b/arch/x86/include/asm/checksum_64.h index 3ec6d3267cf9..ac9c06494827 100644 --- a/arch/x86/include/asm/checksum_64.h +++ b/arch/x86/include/asm/checksum_64.h @@ -141,13 +141,11 @@ extern __visible __wsum csum_partial_copy_generic(const void *src, const void *d extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum isum, int *errp); -extern __wsum csum_partial_copy_to_user(const void *src, void __user *dst, +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); -/* Old names. To be removed. */ -#define csum_and_copy_to_user csum_partial_copy_to_user #define csum_and_copy_from_user csum_partial_copy_from_user /** diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index c66c8b00f236..875c2f5968a0 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -71,7 +71,7 @@ out_err: EXPORT_SYMBOL(csum_partial_copy_from_user); /** - * csum_partial_copy_to_user - Copy and checksum to user space. + * csum_and_copy_to_user - Copy and checksum to user space. * @src: source address * @dst: destination address (user space) * @len: number of bytes to be copied. @@ -82,7 +82,7 @@ EXPORT_SYMBOL(csum_partial_copy_from_user); * src and dst are best aligned to 64bits. */ __wsum -csum_partial_copy_to_user(const void *src, void __user *dst, +csum_and_copy_to_user(const void *src, void __user *dst, int len, __wsum isum, int *errp) { __wsum ret; @@ -116,7 +116,7 @@ csum_partial_copy_to_user(const void *src, void __user *dst, clac(); return ret; } -EXPORT_SYMBOL(csum_partial_copy_to_user); +EXPORT_SYMBOL(csum_and_copy_to_user); /** * csum_partial_copy_nocheck - Copy and checksum. -- cgit v1.2.3 From 73e800ecb67bf24c0508c63350c1dc509f00b1ce Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Feb 2020 14:56:36 -0500 Subject: x86_64: csum_..._copy_..._user(): switch to unsafe_..._user() We already have stac/clac pair around the calls of csum_partial_copy_generic(). Stretch that area back, so that it covers the preceding loop (and convert the loop body from __{get,put}_user() to unsafe_{get,put}_user()). That brings the beginning of the areas to the earlier access_ok(), which allows to convert them into user_access_{begin,end}() ones. Signed-off-by: Al Viro --- arch/x86/lib/csum-wrappers_64.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index 875c2f5968a0..7028d1dc5c6b 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -27,7 +27,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, might_sleep(); *errp = 0; - if (!likely(access_ok(src, len))) + if (!user_access_begin(src, len)) goto out_err; /* @@ -42,8 +42,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, while (((unsigned long)src & 6) && len >= 2) { __u16 val16; - if (__get_user(val16, (const __u16 __user *)src)) - goto out_err; + unsafe_get_user(val16, (const __u16 __user *)src, out); *(__u16 *)dst = val16; isum = (__force __wsum)add32_with_carry( @@ -53,15 +52,16 @@ csum_partial_copy_from_user(const void __user *src, void *dst, len -= 2; } } - stac(); isum = csum_partial_copy_generic((__force const void *)src, dst, len, isum, errp, NULL); - clac(); + user_access_end(); if (unlikely(*errp)) goto out_err; return isum; +out: + user_access_end(); out_err: *errp = -EFAULT; memset(dst, 0, len); @@ -89,7 +89,7 @@ csum_and_copy_to_user(const void *src, void __user *dst, might_sleep(); - if (unlikely(!access_ok(dst, len))) { + if (!user_access_begin(dst, len)) { *errp = -EFAULT; return 0; } @@ -100,9 +100,7 @@ csum_and_copy_to_user(const void *src, void __user *dst, isum = (__force __wsum)add32_with_carry( (__force unsigned)isum, val16); - *errp = __put_user(val16, (__u16 __user *)dst); - if (*errp) - return isum; + unsafe_put_user(val16, (__u16 __user *)dst, out); src += 2; dst += 2; len -= 2; @@ -110,11 +108,14 @@ csum_and_copy_to_user(const void *src, void __user *dst, } *errp = 0; - stac(); ret = csum_partial_copy_generic(src, (void __force *)dst, len, isum, NULL, errp); - clac(); + user_access_end(); return ret; +out: + user_access_end(); + *errp = -EFAULT; + return isum; } EXPORT_SYMBOL(csum_and_copy_to_user); -- cgit v1.2.3 From 0a5ea224b2fdf9dca9291ef7b5a12fd846a5dc34 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Feb 2020 16:50:00 -0500 Subject: x86: switch both 32bit and 64bit to providing csum_and_copy_from_user() ... rather than messing with the wrapper. As a side effect, 32bit variant gets access_ok() into it and can be switched to user_access_begin()/user_access_end() Signed-off-by: Al Viro --- arch/x86/include/asm/checksum.h | 1 + arch/x86/include/asm/checksum_32.h | 15 +++++++++------ arch/x86/include/asm/checksum_64.h | 5 +---- arch/x86/lib/csum-wrappers_64.c | 6 +++--- 4 files changed, 14 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/checksum.h b/arch/x86/include/asm/checksum.h index d79d1e622dcf..1ab9572ae4c2 100644 --- a/arch/x86/include/asm/checksum.h +++ b/arch/x86/include/asm/checksum.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1 #ifdef CONFIG_X86_32 # include #else diff --git a/arch/x86/include/asm/checksum_32.h b/arch/x86/include/asm/checksum_32.h index f57b94e02c57..2487b7fc2d24 100644 --- a/arch/x86/include/asm/checksum_32.h +++ b/arch/x86/include/asm/checksum_32.h @@ -44,18 +44,21 @@ static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst, return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); } -static inline __wsum csum_partial_copy_from_user(const void __user *src, - void *dst, - int len, __wsum sum, - int *err_ptr) +static inline __wsum csum_and_copy_from_user(const void __user *src, + void *dst, int len, + __wsum sum, int *err_ptr) { __wsum ret; might_sleep(); - stac(); + if (!user_access_begin(src, len)) { + if (len) + *err_ptr = -EFAULT; + return sum; + } ret = csum_partial_copy_generic((__force void *)src, dst, len, sum, err_ptr, NULL); - clac(); + user_access_end(); return ret; } diff --git a/arch/x86/include/asm/checksum_64.h b/arch/x86/include/asm/checksum_64.h index ac9c06494827..2f8435542376 100644 --- a/arch/x86/include/asm/checksum_64.h +++ b/arch/x86/include/asm/checksum_64.h @@ -129,7 +129,6 @@ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, */ extern __wsum csum_partial(const void *buff, int len, __wsum sum); -#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1 #define HAVE_CSUM_COPY_USER 1 @@ -139,15 +138,13 @@ extern __visible __wsum csum_partial_copy_generic(const void *src, const void *d int *src_err_ptr, int *dst_err_ptr); -extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, +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); -#define csum_and_copy_from_user csum_partial_copy_from_user - /** * ip_compute_csum - Compute an 16bit IP checksum. * @buff: buffer address. diff --git a/arch/x86/lib/csum-wrappers_64.c b/arch/x86/lib/csum-wrappers_64.c index 7028d1dc5c6b..ee63d7576fd2 100644 --- a/arch/x86/lib/csum-wrappers_64.c +++ b/arch/x86/lib/csum-wrappers_64.c @@ -10,7 +10,7 @@ #include /** - * csum_partial_copy_from_user - Copy and checksum from user space. + * csum_and_copy_from_user - Copy and checksum from user space. * @src: source address (user space) * @dst: destination address * @len: number of bytes to be copied. @@ -21,7 +21,7 @@ * src and dst are best aligned to 64bits. */ __wsum -csum_partial_copy_from_user(const void __user *src, void *dst, +csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum isum, int *errp) { might_sleep(); @@ -68,7 +68,7 @@ out_err: return isum; } -EXPORT_SYMBOL(csum_partial_copy_from_user); +EXPORT_SYMBOL(csum_and_copy_from_user); /** * csum_and_copy_to_user - Copy and checksum to user space. -- cgit v1.2.3 From c281a6c1ac6b0867e4341ea801030fa9a62157f9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Feb 2020 17:11:48 -0500 Subject: x86: switch 32bit csum_and_copy_to_user() to user_access_{begin,end}() consolidate HAVE_CSUM_COPY_USER for 32bit and 64bit, while are at it Signed-off-by: Al Viro --- arch/x86/include/asm/checksum.h | 1 + arch/x86/include/asm/checksum_32.h | 6 ++---- arch/x86/include/asm/checksum_64.h | 3 --- 3 files changed, 3 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/checksum.h b/arch/x86/include/asm/checksum.h index 1ab9572ae4c2..0ada98d5d09f 100644 --- a/arch/x86/include/asm/checksum.h +++ b/arch/x86/include/asm/checksum.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER 1 +#define HAVE_CSUM_COPY_USER #ifdef CONFIG_X86_32 # include #else diff --git a/arch/x86/include/asm/checksum_32.h b/arch/x86/include/asm/checksum_32.h index 2487b7fc2d24..11624c8a9d8d 100644 --- a/arch/x86/include/asm/checksum_32.h +++ b/arch/x86/include/asm/checksum_32.h @@ -176,7 +176,6 @@ static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, /* * 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, @@ -185,11 +184,10 @@ static inline __wsum csum_and_copy_to_user(const void *src, __wsum ret; might_sleep(); - if (access_ok(dst, len)) { - stac(); + if (user_access_begin(dst, len)) { ret = csum_partial_copy_generic(src, (__force void *)dst, len, sum, NULL, err_ptr); - clac(); + user_access_end(); return ret; } diff --git a/arch/x86/include/asm/checksum_64.h b/arch/x86/include/asm/checksum_64.h index 2f8435542376..0a289b87e872 100644 --- a/arch/x86/include/asm/checksum_64.h +++ b/arch/x86/include/asm/checksum_64.h @@ -129,9 +129,6 @@ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, */ extern __wsum csum_partial(const void *buff, int len, __wsum sum); -#define HAVE_CSUM_COPY_USER 1 - - /* Do not call this directly. Use the wrappers below */ extern __visible __wsum csum_partial_copy_generic(const void *src, const void *dst, int len, __wsum sum, -- cgit v1.2.3 From cc03f19cfd45f44a75f0445c5be0073bbd3dda1c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Feb 2020 15:10:33 -0500 Subject: ia64: csum_partial_copy_nocheck(): don't abuse csum_partial_copy_from_user() Just inline the call and use memcpy() instead of __copy_from_user() and note that the tail is precisely ia64 csum_partial(). Signed-off-by: Al Viro --- arch/ia64/lib/csum_partial_copy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c index bf9396b1ed32..9ab570d0f756 100644 --- a/arch/ia64/lib/csum_partial_copy.c +++ b/arch/ia64/lib/csum_partial_copy.c @@ -134,8 +134,8 @@ EXPORT_SYMBOL(csum_partial_copy_from_user); __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) { - return csum_partial_copy_from_user((__force const void __user *)src, - dst, len, sum, NULL); + memcpy(dst, src, len); + return csum_partial(dst, len, sum); } EXPORT_SYMBOL(csum_partial_copy_nocheck); -- cgit v1.2.3 From bfdaf029c9c95072359fd0870c282e53953220f6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 12:56:09 -0500 Subject: ia64: turn csum_partial_copy_from_user() into csum_and_copy_from_user() Just use copy_from_user() there, rather than relying upon the wrapper to have done access_ok() Signed-off-by: Al Viro --- arch/ia64/include/asm/checksum.h | 3 ++- arch/ia64/lib/csum_partial_copy.c | 18 ++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/ia64/include/asm/checksum.h b/arch/ia64/include/asm/checksum.h index 0ed18bc3f6cf..279ea4dcee79 100644 --- a/arch/ia64/include/asm/checksum.h +++ b/arch/ia64/include/asm/checksum.h @@ -37,13 +37,14 @@ extern __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, */ extern __wsum csum_partial(const void *buff, int len, __wsum sum); +#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER /* * Same as csum_partial, but copies from src while it checksums. * * Here it is even more important to align src and dst on a 32-bit (or * even better 64-bit) boundary. */ -extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, +extern __wsum csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *errp); diff --git a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c index 9ab570d0f756..ab59eb399900 100644 --- a/arch/ia64/lib/csum_partial_copy.c +++ b/arch/ia64/lib/csum_partial_copy.c @@ -103,33 +103,23 @@ out: * This is very ugly but temporary. THIS NEEDS SERIOUS ENHANCEMENTS. * But it's very tricky to get right even in C. */ -extern unsigned long do_csum(const unsigned char *, long); - __wsum -csum_partial_copy_from_user(const void __user *src, void *dst, +csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum psum, int *errp) { - unsigned long result; - /* XXX Fixme * for now we separate the copy from checksum for obvious * alignment difficulties. Look at the Alpha code and you'll be * scared. */ - if (__copy_from_user(dst, src, len) != 0 && errp) + if (copy_from_user(dst, src, len)) *errp = -EFAULT; - result = do_csum(dst, len); - - /* add in old sum, and carry.. */ - result += (__force u32)psum; - /* 32+c bits -> 32 bits */ - result = (result & 0xffffffff) + (result >> 32); - return (__force __wsum)result; + return csum_partial(dst, len, psum); } -EXPORT_SYMBOL(csum_partial_copy_from_user); +EXPORT_SYMBOL(csum_and_copy_from_user); __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) -- cgit v1.2.3 From 808b49da54e640cba5c5c92dee658018a529226b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 12:49:07 -0500 Subject: alpha: turn csum_partial_copy_from_user() into csum_and_copy_from_user() It's already doing the right thing - it does access_ok() and the wrapper in net/checksum.h is pointless here. Just rename it and be done with that... Signed-off-by: Al Viro --- arch/alpha/include/asm/checksum.h | 3 ++- arch/alpha/lib/csum_partial_copy.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/alpha/include/asm/checksum.h b/arch/alpha/include/asm/checksum.h index 473e6ccb65a3..0eac81624d01 100644 --- a/arch/alpha/include/asm/checksum.h +++ b/arch/alpha/include/asm/checksum.h @@ -41,7 +41,8 @@ extern __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_from_user(const void __user *src, void *dst, int len, __wsum sum, int *errp); +#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER +__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); diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index e53f96e8aa6d..af1dad74e933 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c @@ -325,7 +325,7 @@ csum_partial_cfu_unaligned(const unsigned long __user * src, } __wsum -csum_partial_copy_from_user(const void __user *src, void *dst, int len, +csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *errp) { unsigned long checksum = (__force u32) sum; @@ -369,7 +369,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len, } return (__force __wsum)checksum; } -EXPORT_SYMBOL(csum_partial_copy_from_user); +EXPORT_SYMBOL(csum_and_copy_from_user); __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) @@ -377,7 +377,7 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) __wsum checksum; mm_segment_t oldfs = get_fs(); set_fs(KERNEL_DS); - checksum = csum_partial_copy_from_user((__force const void __user *)src, + checksum = csum_and_copy_from_user((__force const void __user *)src, dst, len, sum, NULL); set_fs(oldfs); return checksum; -- cgit v1.2.3 From 77a8710ba7ef7ffcb71f0618bddf78c1b04f01d3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 13:01:02 -0500 Subject: parisc: turn csum_partial_copy_from_user() into csum_and_copy_from_user() Already has the right semantics. Incidentally. failing copy_from_user() zeroes the tail of destination - no need to repeat that manually Signed-off-by: Al Viro --- arch/parisc/include/asm/checksum.h | 3 ++- arch/parisc/lib/checksum.c | 12 +++--------- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h index c1c22819a04d..7c69ce9634c7 100644 --- a/arch/parisc/include/asm/checksum.h +++ b/arch/parisc/include/asm/checksum.h @@ -26,11 +26,12 @@ extern __wsum csum_partial(const void *, int, __wsum); */ extern __wsum csum_partial_copy_nocheck(const void *, void *, int, __wsum); +#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER /* * this is a new version of the above that records errors it finds in *errp, * but continues and zeros the rest of the buffer. */ -extern __wsum csum_partial_copy_from_user(const void __user *src, +extern __wsum csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *errp); /* diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c index 256322c7b648..4e47c2ff2bcd 100644 --- a/arch/parisc/lib/checksum.c +++ b/arch/parisc/lib/checksum.c @@ -128,18 +128,12 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck); * Copy from userspace and compute checksum. If we catch an exception * then zero the rest of the buffer. */ -__wsum csum_partial_copy_from_user(const void __user *src, +__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr) { - int missing; - - missing = copy_from_user(dst, src, len); - if (missing) { - memset(dst + len - missing, 0, missing); + if (copy_from_user(dst, src, len)) *err_ptr = -EFAULT; - } - return csum_partial(dst, len, sum); } -EXPORT_SYMBOL(csum_partial_copy_from_user); +EXPORT_SYMBOL(csum_and_copy_from_user); -- cgit v1.2.3 From 76666be8c9df456373a4e00ce51d2547f1d90627 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 13:07:41 -0500 Subject: sparc: switch to providing csum_and_copy_from_user() sparc64 already is equivalent to that (trivial access_ok()); add it into sparc32 csum_partial_copy_from_user() and we can rename both to csum_and_copy_fromUser() and be done with that. Signed-off-by: Al Viro --- arch/sparc/include/asm/checksum.h | 1 + arch/sparc/include/asm/checksum_32.h | 8 +++++++- arch/sparc/include/asm/checksum_64.h | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/checksum.h b/arch/sparc/include/asm/checksum.h index c3be56e2e768..a6256cb6fc5c 100644 --- a/arch/sparc/include/asm/checksum.h +++ b/arch/sparc/include/asm/checksum.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef ___ASM_SPARC_CHECKSUM_H #define ___ASM_SPARC_CHECKSUM_H +#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER #if defined(__sparc__) && defined(__arch64__) #include #else diff --git a/arch/sparc/include/asm/checksum_32.h b/arch/sparc/include/asm/checksum_32.h index 450ddfb444c8..479a0b812af5 100644 --- a/arch/sparc/include/asm/checksum_32.h +++ b/arch/sparc/include/asm/checksum_32.h @@ -60,7 +60,7 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) } static inline __wsum -csum_partial_copy_from_user(const void __user *src, void *dst, int len, +csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err) { register unsigned long ret asm("o0") = (unsigned long)src; @@ -68,6 +68,12 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len, register int l asm("g1") = len; register __wsum s asm("g7") = sum; + if (unlikely(!access_ok(src, len))) { + if (len) + *err = -EFAULT; + return sum; + } + __asm__ __volatile__ ( ".section __ex_table,#alloc\n\t" ".align 4\n\t" diff --git a/arch/sparc/include/asm/checksum_64.h b/arch/sparc/include/asm/checksum_64.h index e52450930e4e..0fa4433f5662 100644 --- a/arch/sparc/include/asm/checksum_64.h +++ b/arch/sparc/include/asm/checksum_64.h @@ -46,7 +46,7 @@ long __csum_partial_copy_from_user(const void __user *src, __wsum sum); static inline __wsum -csum_partial_copy_from_user(const void __user *src, +csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err) { -- cgit v1.2.3 From d341659f470b6c5536296a6bd575744c38610ce8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 13:12:08 -0500 Subject: xtensa: switch to providing csum_and_copy_from_user() Signed-off-by: Al Viro --- arch/xtensa/include/asm/checksum.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/include/asm/checksum.h b/arch/xtensa/include/asm/checksum.h index 8b687176ad72..d8292cc9ebdf 100644 --- a/arch/xtensa/include/asm/checksum.h +++ b/arch/xtensa/include/asm/checksum.h @@ -44,8 +44,6 @@ asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, /* * Note: when you get a NULL pointer exception here this means someone * passed in an incorrect kernel address to one of these functions. - * - * 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, @@ -54,12 +52,17 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); } +#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER static inline -__wsum csum_partial_copy_from_user(const void __user *src, void *dst, +__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr) { - return csum_partial_copy_generic((__force const void *)src, dst, + if (access_ok(dst, len)) + return csum_partial_copy_generic((__force const void *)src, dst, len, sum, err_ptr, NULL); + if (len) + *err_ptr = -EFAULT; + return sum; } /* -- cgit v1.2.3 From 8084c99b9af68621ff15562732bfc9f8e7cce93c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 14:15:37 -0500 Subject: m68k: convert to csum_and_copy_from_user() trivial access_ok() there... Signed-off-by: Al Viro --- arch/m68k/include/asm/checksum.h | 3 ++- arch/m68k/lib/checksum.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/m68k/include/asm/checksum.h b/arch/m68k/include/asm/checksum.h index f9b94e4b94f9..3f2c15d6f18c 100644 --- a/arch/m68k/include/asm/checksum.h +++ b/arch/m68k/include/asm/checksum.h @@ -30,7 +30,8 @@ __wsum csum_partial(const void *buff, int len, __wsum sum); * better 64-bit) boundary */ -extern __wsum csum_partial_copy_from_user(const void __user *src, +#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 *csum_err); diff --git a/arch/m68k/lib/checksum.c b/arch/m68k/lib/checksum.c index 5fa3d392e181..31797be9a3dc 100644 --- a/arch/m68k/lib/checksum.c +++ b/arch/m68k/lib/checksum.c @@ -129,7 +129,7 @@ EXPORT_SYMBOL(csum_partial); */ __wsum -csum_partial_copy_from_user(const void __user *src, void *dst, +csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *csum_err) { /* @@ -316,7 +316,7 @@ csum_partial_copy_from_user(const void __user *src, void *dst, return(sum); } -EXPORT_SYMBOL(csum_partial_copy_from_user); +EXPORT_SYMBOL(csum_and_copy_from_user); /* -- cgit v1.2.3 From 7fe8970a78a1934545d53267281f1737eefea3bb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 14:18:09 -0500 Subject: sh32: convert to csum_and_copy_from_user() Signed-off-by: Al Viro --- arch/sh/include/asm/checksum_32.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sh/include/asm/checksum_32.h b/arch/sh/include/asm/checksum_32.h index 36b84cfd3f67..91571a42e44e 100644 --- a/arch/sh/include/asm/checksum_32.h +++ b/arch/sh/include/asm/checksum_32.h @@ -48,12 +48,17 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); } +#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER static inline -__wsum csum_partial_copy_from_user(const void __user *src, void *dst, +__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr) { - return csum_partial_copy_generic((__force const void *)src, dst, + 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; } /* -- cgit v1.2.3 From 24f9aa928c3cc88bae573b39b6976844968f80a0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 14:19:54 -0500 Subject: arm: switch to csum_and_copy_from_user() Note that csum_partial_copy_from_user() is in assembler here, so I'm leaving it alone and just providing the wrapper for it. When/if we go for switching arm to user_access_{begin,end}() (doing domain switches in those), somebody well need to look into that one. Signed-off-by: Al Viro --- arch/arm/include/asm/checksum.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/asm/checksum.h b/arch/arm/include/asm/checksum.h index 20043e0ebb07..ed6073fee338 100644 --- a/arch/arm/include/asm/checksum.h +++ b/arch/arm/include/asm/checksum.h @@ -40,6 +40,20 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr); +#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) +{ + if (access_ok(src, len)) + return csum_partial_copy_from_user(src, dst, len, sum, err_ptr); + + if (len) + *err_ptr = -EFAULT; + + return sum; +} + /* * Fold a partial checksum without adding pseudo headers */ -- cgit v1.2.3 From 5904122c46581a5ccee54a51ef07e0d891fd7aef Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Feb 2020 14:26:32 -0500 Subject: take the dummy csum_and_copy_from_user() into net/checksum.h now that can be done conveniently - all non-trivial cases have _HAVE_ARCH_COPY_AND_CSUM_FROM_USER defined, so the fallback in net/checksum.h is used only for dummy (copy_from_user, then csum_partial) implementation. Allowing us to get rid of all dummy instances, both of csum_and_copy_from_user() and csum_partial_copy_from_user(). Signed-off-by: Al Viro --- arch/c6x/lib/checksum.c | 22 ---------------------- arch/ia64/include/asm/checksum.h | 11 ----------- arch/ia64/lib/csum_partial_copy.c | 18 ------------------ arch/nios2/include/asm/checksum.h | 2 -- arch/parisc/include/asm/checksum.h | 8 -------- arch/parisc/lib/checksum.c | 14 -------------- arch/s390/include/asm/checksum.h | 19 ------------------- arch/x86/um/asm/checksum.h | 20 -------------------- include/asm-generic/checksum.h | 9 --------- include/net/checksum.h | 8 ++------ lib/checksum.c | 20 -------------------- 11 files changed, 2 insertions(+), 149 deletions(-) (limited to 'arch') diff --git a/arch/c6x/lib/checksum.c b/arch/c6x/lib/checksum.c index 46940844c553..335ca4900808 100644 --- a/arch/c6x/lib/checksum.c +++ b/arch/c6x/lib/checksum.c @@ -4,28 +4,6 @@ #include #include -#include - -/* - * copy from fs while checksumming, otherwise like csum_partial - */ -__wsum -csum_partial_copy_from_user(const void __user *src, void *dst, int len, - __wsum sum, int *csum_err) -{ - int missing; - - missing = __copy_from_user(dst, src, len); - if (missing) { - memset(dst + len - missing, 0, missing); - *csum_err = -EFAULT; - } else - *csum_err = 0; - - return csum_partial(dst, len, sum); -} -EXPORT_SYMBOL(csum_partial_copy_from_user); - /* These are from csum_64plus.S */ EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy); diff --git a/arch/ia64/include/asm/checksum.h b/arch/ia64/include/asm/checksum.h index 279ea4dcee79..2a1c64629cdc 100644 --- a/arch/ia64/include/asm/checksum.h +++ b/arch/ia64/include/asm/checksum.h @@ -37,17 +37,6 @@ extern __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, */ extern __wsum csum_partial(const void *buff, int len, __wsum sum); -#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER -/* - * Same as csum_partial, but copies from src while it checksums. - * - * Here it is even more important to align src and dst on a 32-bit (or - * even better 64-bit) boundary. - */ -extern __wsum csum_and_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, - int *errp); - extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); diff --git a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c index ab59eb399900..5d147a33d648 100644 --- a/arch/ia64/lib/csum_partial_copy.c +++ b/arch/ia64/lib/csum_partial_copy.c @@ -103,24 +103,6 @@ out: * This is very ugly but temporary. THIS NEEDS SERIOUS ENHANCEMENTS. * But it's very tricky to get right even in C. */ -__wsum -csum_and_copy_from_user(const void __user *src, void *dst, - int len, __wsum psum, int *errp) -{ - /* XXX Fixme - * for now we separate the copy from checksum for obvious - * alignment difficulties. Look at the Alpha code and you'll be - * scared. - */ - - if (copy_from_user(dst, src, len)) - *errp = -EFAULT; - - return csum_partial(dst, len, psum); -} - -EXPORT_SYMBOL(csum_and_copy_from_user); - __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) { diff --git a/arch/nios2/include/asm/checksum.h b/arch/nios2/include/asm/checksum.h index 703c5ee63421..ec39698d3bea 100644 --- a/arch/nios2/include/asm/checksum.h +++ b/arch/nios2/include/asm/checksum.h @@ -14,8 +14,6 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum); extern __wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum); -extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *csum_err); #define csum_partial_copy_nocheck(src, dst, len, sum) \ csum_partial_copy((src), (dst), (len), (sum)) diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h index 7c69ce9634c7..fe8c63b2d2c3 100644 --- a/arch/parisc/include/asm/checksum.h +++ b/arch/parisc/include/asm/checksum.h @@ -26,14 +26,6 @@ extern __wsum csum_partial(const void *, int, __wsum); */ extern __wsum csum_partial_copy_nocheck(const void *, void *, int, __wsum); -#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER -/* - * this is a new version of the above that records errors it finds in *errp, - * but continues and zeros the rest of the buffer. - */ -extern __wsum csum_and_copy_from_user(const void __user *src, - void *dst, int len, __wsum sum, int *errp); - /* * Optimized for IP headers, which always checksum on 4 octet boundaries. * diff --git a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c index 4e47c2ff2bcd..c6f161583549 100644 --- a/arch/parisc/lib/checksum.c +++ b/arch/parisc/lib/checksum.c @@ -123,17 +123,3 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, return sum; } EXPORT_SYMBOL(csum_partial_copy_nocheck); - -/* - * Copy from userspace and compute checksum. If we catch an exception - * then zero the rest of the buffer. - */ -__wsum csum_and_copy_from_user(const void __user *src, - void *dst, int len, - __wsum sum, int *err_ptr) -{ - if (copy_from_user(dst, src, len)) - *err_ptr = -EFAULT; - return csum_partial(dst, len, sum); -} -EXPORT_SYMBOL(csum_and_copy_from_user); diff --git a/arch/s390/include/asm/checksum.h b/arch/s390/include/asm/checksum.h index 91e376b0d28c..6d01c96aeb5c 100644 --- a/arch/s390/include/asm/checksum.h +++ b/arch/s390/include/asm/checksum.h @@ -39,25 +39,6 @@ csum_partial(const void *buff, int len, __wsum sum) return sum; } -/* - * the same as csum_partial_copy, but copies from user space. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - * - * Copy from userspace and compute checksum. - */ -static inline __wsum -csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, - int *err_ptr) -{ - if (unlikely(copy_from_user(dst, src, len))) - *err_ptr = -EFAULT; - return csum_partial(dst, len, sum); -} - - static inline __wsum csum_partial_copy_nocheck (const void *src, void *dst, int len, __wsum sum) { diff --git a/arch/x86/um/asm/checksum.h b/arch/x86/um/asm/checksum.h index 2a56cac64687..ff6bba2c8ab6 100644 --- a/arch/x86/um/asm/checksum.h +++ b/arch/x86/um/asm/checksum.h @@ -36,26 +36,6 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, return csum_partial(dst, len, sum); } -/* - * the same as csum_partial, but copies from src while it - * checksums, and handles user-space pointer exceptions correctly, when needed. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ - -static __inline__ -__wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *err_ptr) -{ - if (copy_from_user(dst, src, len)) { - *err_ptr = -EFAULT; - return (__force __wsum)-1; - } - - return csum_partial(dst, len, sum); -} - /** * csum_fold - Fold and invert a 32bit checksum. * sum: 32bit unfolded sum diff --git a/include/asm-generic/checksum.h b/include/asm-generic/checksum.h index 34785c0f57b0..5a80f8e54300 100644 --- a/include/asm-generic/checksum.h +++ b/include/asm-generic/checksum.h @@ -25,15 +25,6 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum); */ extern __wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum); -/* - * the same as csum_partial_copy, but copies from user space. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ -extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *csum_err); - #ifndef csum_partial_copy_nocheck #define csum_partial_copy_nocheck(src, dst, len, sum) \ csum_partial_copy((src), (dst), (len), (sum)) diff --git a/include/net/checksum.h b/include/net/checksum.h index 97bf4885a962..5f9c73c0eeb9 100644 --- a/include/net/checksum.h +++ b/include/net/checksum.h @@ -26,13 +26,9 @@ static inline __wsum csum_and_copy_from_user (const void __user *src, void *dst, int len, __wsum sum, int *err_ptr) { - if (access_ok(src, len)) - return csum_partial_copy_from_user(src, dst, len, sum, err_ptr); - - if (len) + if (copy_from_user(dst, src, len)) *err_ptr = -EFAULT; - - return sum; + return csum_partial(dst, len, sum); } #endif diff --git a/lib/checksum.c b/lib/checksum.c index de032ad96f4a..7ac65a0000ff 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -145,26 +145,6 @@ __sum16 ip_compute_csum(const void *buff, int len) } EXPORT_SYMBOL(ip_compute_csum); -/* - * copy from fs while checksumming, otherwise like csum_partial - */ -__wsum -csum_partial_copy_from_user(const void __user *src, void *dst, int len, - __wsum sum, int *csum_err) -{ - int missing; - - missing = __copy_from_user(dst, src, len); - if (missing) { - memset(dst + len - missing, 0, missing); - *csum_err = -EFAULT; - } else - *csum_err = 0; - - return csum_partial(dst, len, sum); -} -EXPORT_SYMBOL(csum_partial_copy_from_user); - /* * copy from ds while checksumming, otherwise like csum_partial */ -- cgit v1.2.3