saner calling conventions for csum_and_copy_..._user()
All callers of these primitives will * discard anything we might've copied in case of error * ignore the csum value in case of error * always pass 0xffffffff as the initial sum, so the resulting csum value (in case of success, that is) will never be 0. That suggest the following calling conventions: * don't pass err_ptr - just return 0 on error. * don't bother with zeroing destination, etc. in case of error * don't pass the initial sum - just use 0xffffffff. This commit does the minimal conversion in the instances of csum_and_copy_...(); the changes of actual asm code behind them are done later in the series. Note that this asm code is often shared with csum_partial_copy_nocheck(); the difference is that csum_partial_copy_nocheck() passes 0 for initial sum while csum_and_copy_..._user() pass 0xffffffff. Fortunately, we are free to pass 0xffffffff in all cases and subsequent patches will use that freedom without any special comments. A part that could be split off: parisc and uml/i386 claimed to have csum_and_copy_to_user() instances of their own, but those were identical to the generic one, so we simply drop them. Not sure if it's worth a separate commit... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
99a2c96d52
commit
c693cc4676
|
@ -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_COPY_AND_CSUM_FROM_USER
|
||||||
#define _HAVE_ARCH_CSUM_AND_COPY
|
#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);
|
__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len);
|
||||||
|
|
||||||
|
|
|
@ -325,30 +325,27 @@ csum_partial_cfu_unaligned(const unsigned long __user * src,
|
||||||
}
|
}
|
||||||
|
|
||||||
__wsum
|
__wsum
|
||||||
csum_and_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;
|
unsigned long checksum = ~0U;
|
||||||
unsigned long soff = 7 & (unsigned long) src;
|
unsigned long soff = 7 & (unsigned long) src;
|
||||||
unsigned long doff = 7 & (unsigned long) dst;
|
unsigned long doff = 7 & (unsigned long) dst;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
if (len) {
|
if (len) {
|
||||||
if (!access_ok(src, len)) {
|
if (!access_ok(src, len))
|
||||||
if (errp) *errp = -EFAULT;
|
return 0;
|
||||||
memset(dst, 0, len);
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
if (!doff) {
|
if (!doff) {
|
||||||
if (!soff)
|
if (!soff)
|
||||||
checksum = csum_partial_cfu_aligned(
|
checksum = csum_partial_cfu_aligned(
|
||||||
(const unsigned long __user *) src,
|
(const unsigned long __user *) src,
|
||||||
(unsigned long *) dst,
|
(unsigned long *) dst,
|
||||||
len-8, checksum, errp);
|
len-8, checksum, &err);
|
||||||
else
|
else
|
||||||
checksum = csum_partial_cfu_dest_aligned(
|
checksum = csum_partial_cfu_dest_aligned(
|
||||||
(const unsigned long __user *) src,
|
(const unsigned long __user *) src,
|
||||||
(unsigned long *) dst,
|
(unsigned long *) dst,
|
||||||
soff, len-8, checksum, errp);
|
soff, len-8, checksum, &err);
|
||||||
} else {
|
} else {
|
||||||
unsigned long partial_dest;
|
unsigned long partial_dest;
|
||||||
ldq_u(partial_dest, dst);
|
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,
|
(const unsigned long __user *) src,
|
||||||
(unsigned long *) dst,
|
(unsigned long *) dst,
|
||||||
doff, len-8, checksum,
|
doff, len-8, checksum,
|
||||||
partial_dest, errp);
|
partial_dest, &err);
|
||||||
else
|
else
|
||||||
checksum = csum_partial_cfu_unaligned(
|
checksum = csum_partial_cfu_unaligned(
|
||||||
(const unsigned long __user *) src,
|
(const unsigned long __user *) src,
|
||||||
(unsigned long *) dst,
|
(unsigned long *) dst,
|
||||||
soff, doff, len-8, checksum,
|
soff, doff, len-8, checksum,
|
||||||
partial_dest, errp);
|
partial_dest, &err);
|
||||||
}
|
}
|
||||||
checksum = from64to16 (checksum);
|
checksum = err ? 0 : from64to16 (checksum);
|
||||||
}
|
}
|
||||||
return (__force __wsum)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();
|
mm_segment_t oldfs = get_fs();
|
||||||
set_fs(KERNEL_DS);
|
set_fs(KERNEL_DS);
|
||||||
checksum = csum_and_copy_from_user((__force const void __user *)src,
|
checksum = csum_and_copy_from_user((__force const void __user *)src,
|
||||||
dst, len, 0, NULL);
|
dst, len);
|
||||||
set_fs(oldfs);
|
set_fs(oldfs);
|
||||||
return checksum;
|
return checksum;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,16 +43,15 @@ csum_partial_copy_from_user(const void __user *src, void *dst, int len, __wsum s
|
||||||
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
||||||
#define _HAVE_ARCH_CSUM_AND_COPY
|
#define _HAVE_ARCH_CSUM_AND_COPY
|
||||||
static inline
|
static inline
|
||||||
__wsum csum_and_copy_from_user (const void __user *src, void *dst,
|
__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len)
|
||||||
int len, __wsum sum, int *err_ptr)
|
|
||||||
{
|
{
|
||||||
if (access_ok(src, len))
|
int err = 0;
|
||||||
return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
|
|
||||||
|
|
||||||
if (len)
|
if (!access_ok(src, len))
|
||||||
*err_ptr = -EFAULT;
|
return 0;
|
||||||
|
|
||||||
return sum;
|
sum = csum_partial_copy_from_user(src, dst, len, ~0U, &err);
|
||||||
|
return err ? 0 : sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -34,8 +34,7 @@ __wsum csum_partial(const void *buff, int len, __wsum sum);
|
||||||
#define _HAVE_ARCH_CSUM_AND_COPY
|
#define _HAVE_ARCH_CSUM_AND_COPY
|
||||||
extern __wsum csum_and_copy_from_user(const void __user *src,
|
extern __wsum csum_and_copy_from_user(const void __user *src,
|
||||||
void *dst,
|
void *dst,
|
||||||
int len, __wsum sum,
|
int len);
|
||||||
int *csum_err);
|
|
||||||
|
|
||||||
extern __wsum csum_partial_copy_nocheck(const void *src,
|
extern __wsum csum_partial_copy_nocheck(const void *src,
|
||||||
void *dst, int len);
|
void *dst, int len);
|
||||||
|
|
|
@ -129,8 +129,7 @@ EXPORT_SYMBOL(csum_partial);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
__wsum
|
__wsum
|
||||||
csum_and_copy_from_user(const void __user *src, void *dst,
|
csum_and_copy_from_user(const void __user *src, void *dst, int len)
|
||||||
int len, __wsum sum, int *csum_err)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* GCC doesn't like more than 10 operands for the asm
|
* 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.
|
* code.
|
||||||
*/
|
*/
|
||||||
unsigned long tmp1, tmp2;
|
unsigned long tmp1, tmp2;
|
||||||
|
__wsum sum = ~0U;
|
||||||
|
|
||||||
__asm__("movel %2,%4\n\t"
|
__asm__("movel %2,%4\n\t"
|
||||||
"btst #1,%4\n\t" /* Check alignment */
|
"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)
|
: "0" (sum), "1" (len), "2" (src), "3" (dst)
|
||||||
);
|
);
|
||||||
|
|
||||||
*csum_err = tmp2;
|
return tmp2 ? 0 : sum;
|
||||||
|
|
||||||
return(sum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(csum_and_copy_from_user);
|
EXPORT_SYMBOL(csum_and_copy_from_user);
|
||||||
|
|
|
@ -60,16 +60,15 @@ __wsum csum_partial_copy_from_user(const void __user *src, void *dst, int len,
|
||||||
|
|
||||||
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
||||||
static inline
|
static inline
|
||||||
__wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len)
|
||||||
int len, __wsum sum, int *err_ptr)
|
|
||||||
{
|
{
|
||||||
if (access_ok(src, len))
|
__wsum sum = ~0U;
|
||||||
return csum_partial_copy_from_user(src, dst, len, sum,
|
int err = 0;
|
||||||
err_ptr);
|
|
||||||
if (len)
|
|
||||||
*err_ptr = -EFAULT;
|
|
||||||
|
|
||||||
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
|
#define HAVE_CSUM_COPY_USER
|
||||||
static inline
|
static inline
|
||||||
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
|
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len)
|
||||||
__wsum sum, int *err_ptr)
|
|
||||||
{
|
{
|
||||||
might_fault();
|
int err = 0;
|
||||||
if (access_ok(dst, len)) {
|
__wsum sum = ~0U;
|
||||||
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 */
|
might_fault();
|
||||||
|
if (!access_ok(dst, len))
|
||||||
|
return 0;
|
||||||
|
if (uaccess_kernel())
|
||||||
|
sum = __csum_partial_copy_kernel(src,
|
||||||
|
(__force void *)dst,
|
||||||
|
len, sum, &err);
|
||||||
|
else
|
||||||
|
sum = __csum_partial_copy_to_user(src,
|
||||||
|
(__force void *)dst,
|
||||||
|
len, sum, &err);
|
||||||
|
return err ? 0 : sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -173,25 +173,5 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
|
||||||
return csum_fold(sum);
|
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
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@ extern __wsum csum_partial_copy_generic(const void *src, void *dst,
|
||||||
|
|
||||||
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
||||||
extern __wsum csum_and_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 *err_ptr);
|
int len);
|
||||||
#define HAVE_CSUM_COPY_USER
|
#define HAVE_CSUM_COPY_USER
|
||||||
extern __wsum csum_and_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 sum, int *err_ptr);
|
int len);
|
||||||
|
|
||||||
#define _HAVE_ARCH_CSUM_AND_COPY
|
#define _HAVE_ARCH_CSUM_AND_COPY
|
||||||
#define csum_partial_copy_nocheck(src, dst, len) \
|
#define csum_partial_copy_nocheck(src, dst, len) \
|
||||||
|
|
|
@ -12,82 +12,56 @@
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
__wsum csum_and_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)
|
int len)
|
||||||
{
|
{
|
||||||
unsigned int csum;
|
unsigned int csum;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
|
if (unlikely(!access_ok(src, len)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
allow_read_from_user(src, len);
|
allow_read_from_user(src, len);
|
||||||
|
|
||||||
*err_ptr = 0;
|
|
||||||
|
|
||||||
if (!len) {
|
|
||||||
csum = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely((len < 0) || !access_ok(src, len))) {
|
|
||||||
*err_ptr = -EFAULT;
|
|
||||||
csum = (__force unsigned int)sum;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
csum = csum_partial_copy_generic((void __force *)src, dst,
|
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);
|
int missing = __copy_from_user(dst, src, len);
|
||||||
|
|
||||||
if (missing) {
|
if (missing)
|
||||||
memset(dst + len - missing, 0, missing);
|
csum = 0;
|
||||||
*err_ptr = -EFAULT;
|
else
|
||||||
} else {
|
csum = csum_partial(dst, len, ~0U);
|
||||||
*err_ptr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
csum = csum_partial(dst, len, sum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
prevent_read_from_user(src, len);
|
prevent_read_from_user(src, len);
|
||||||
return (__force __wsum)csum;
|
return (__force __wsum)csum;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(csum_and_copy_from_user);
|
EXPORT_SYMBOL(csum_and_copy_from_user);
|
||||||
|
|
||||||
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
|
__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len)
|
||||||
__wsum sum, int *err_ptr)
|
|
||||||
{
|
{
|
||||||
unsigned int csum;
|
unsigned int csum;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
if (unlikely(!access_ok(dst, len)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
allow_write_to_user(dst, len);
|
allow_write_to_user(dst, len);
|
||||||
|
|
||||||
*err_ptr = 0;
|
|
||||||
|
|
||||||
if (!len) {
|
|
||||||
csum = 0;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely((len < 0) || !access_ok(dst, len))) {
|
|
||||||
*err_ptr = -EFAULT;
|
|
||||||
csum = -1; /* invalid checksum */
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
csum = csum_partial_copy_generic(src, (void __force *)dst,
|
csum = csum_partial_copy_generic(src, (void __force *)dst,
|
||||||
len, sum, NULL, err_ptr);
|
len, ~0U, NULL, &err);
|
||||||
|
|
||||||
if (unlikely(*err_ptr)) {
|
if (unlikely(err)) {
|
||||||
csum = csum_partial(src, len, sum);
|
csum = csum_partial(src, len, ~0U);
|
||||||
|
|
||||||
if (copy_to_user(dst, src, len)) {
|
if (copy_to_user(dst, src, len))
|
||||||
*err_ptr = -EFAULT;
|
csum = 0;
|
||||||
csum = -1; /* invalid checksum */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
|
||||||
prevent_write_to_user(dst, len);
|
prevent_write_to_user(dst, len);
|
||||||
return (__force __wsum)csum;
|
return (__force __wsum)csum;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,15 +50,16 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len)
|
||||||
|
|
||||||
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
||||||
static inline
|
static inline
|
||||||
__wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len)
|
||||||
int len, __wsum sum, int *err_ptr)
|
|
||||||
{
|
{
|
||||||
if (access_ok(src, len))
|
int err = 0;
|
||||||
return csum_partial_copy_generic((__force const void *)src, dst,
|
__wsum sum = ~0U;
|
||||||
len, sum, err_ptr, NULL);
|
|
||||||
if (len)
|
if (!access_ok(src, len))
|
||||||
*err_ptr = -EFAULT;
|
return 0;
|
||||||
return sum;
|
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
|
#define HAVE_CSUM_COPY_USER
|
||||||
static inline __wsum csum_and_copy_to_user(const void *src,
|
static inline __wsum csum_and_copy_to_user(const void *src,
|
||||||
void __user *dst,
|
void __user *dst,
|
||||||
int len, __wsum sum,
|
int len)
|
||||||
int *err_ptr)
|
|
||||||
{
|
{
|
||||||
if (access_ok(dst, len))
|
int err = 0;
|
||||||
return csum_partial_copy_generic((__force const void *)src,
|
__wsum sum = ~0U;
|
||||||
dst, len, sum, NULL, err_ptr);
|
|
||||||
|
|
||||||
if (len)
|
if (!access_ok(dst, len))
|
||||||
*err_ptr = -EFAULT;
|
return 0;
|
||||||
|
sum = csum_partial_copy_generic((__force const void *)src,
|
||||||
return (__force __wsum)-1; /* invalid checksum */
|
dst, len, sum, NULL, &err);
|
||||||
|
return err ? 0 : sum;
|
||||||
}
|
}
|
||||||
#endif /* __ASM_SH_CHECKSUM_H */
|
#endif /* __ASM_SH_CHECKSUM_H */
|
||||||
|
|
|
@ -60,19 +60,16 @@ csum_partial_copy_nocheck(const void *src, void *dst, int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __wsum
|
static inline __wsum
|
||||||
csum_and_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;
|
register unsigned long ret asm("o0") = (unsigned long)src;
|
||||||
register char *d asm("o1") = dst;
|
register char *d asm("o1") = dst;
|
||||||
register int l asm("g1") = len;
|
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 (unlikely(!access_ok(src, len)))
|
||||||
if (len)
|
return 0;
|
||||||
*err = -EFAULT;
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
".section __ex_table,#alloc\n\t"
|
".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"
|
"call __csum_partial_copy_sparc_generic\n\t"
|
||||||
" st %8, [%%sp + 64]\n"
|
" st %8, [%%sp + 64]\n"
|
||||||
: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
|
: "=&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",
|
: "o2", "o3", "o4", "o5", "o7", "g2", "g3", "g4", "g5",
|
||||||
"cc", "memory");
|
"cc", "memory");
|
||||||
return (__force __wsum)ret;
|
return err ? 0 : (__force __wsum)ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HAVE_CSUM_COPY_USER
|
#define HAVE_CSUM_COPY_USER
|
||||||
|
|
||||||
static inline __wsum
|
static inline __wsum
|
||||||
csum_and_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)) {
|
register unsigned long ret asm("o0") = (unsigned long)src;
|
||||||
*err = -EFAULT;
|
register char __user *d asm("o1") = dst;
|
||||||
return sum;
|
register int l asm("g1") = len;
|
||||||
} else {
|
register __wsum s asm("g7") = ~0U;
|
||||||
register unsigned long ret asm("o0") = (unsigned long)src;
|
int err = 0;
|
||||||
register char __user *d asm("o1") = dst;
|
|
||||||
register int l asm("g1") = len;
|
|
||||||
register __wsum s asm("g7") = sum;
|
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
if (!access_ok(dst, len))
|
||||||
".section __ex_table,#alloc\n\t"
|
return 0;
|
||||||
".align 4\n\t"
|
|
||||||
".word 1f,1\n\t"
|
__asm__ __volatile__ (
|
||||||
".previous\n"
|
".section __ex_table,#alloc\n\t"
|
||||||
"1:\n\t"
|
".align 4\n\t"
|
||||||
"call __csum_partial_copy_sparc_generic\n\t"
|
".word 1f,1\n\t"
|
||||||
" st %8, [%%sp + 64]\n"
|
".previous\n"
|
||||||
: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
|
"1:\n\t"
|
||||||
: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (err)
|
"call __csum_partial_copy_sparc_generic\n\t"
|
||||||
: "o2", "o3", "o4", "o5", "o7",
|
" st %8, [%%sp + 64]\n"
|
||||||
"g2", "g3", "g4", "g5",
|
: "=&r" (ret), "=&r" (d), "=&r" (l), "=&r" (s)
|
||||||
"cc", "memory");
|
: "0" (ret), "1" (d), "2" (l), "3" (s), "r" (&err)
|
||||||
return (__force __wsum)ret;
|
: "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
|
/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
|
||||||
|
|
|
@ -51,12 +51,11 @@ long __csum_partial_copy_from_user(const void __user *src,
|
||||||
|
|
||||||
static inline __wsum
|
static inline __wsum
|
||||||
csum_and_copy_from_user(const void __user *src,
|
csum_and_copy_from_user(const void __user *src,
|
||||||
void *dst, int len,
|
void *dst, int len)
|
||||||
__wsum sum, int *err)
|
|
||||||
{
|
{
|
||||||
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)
|
if (ret < 0)
|
||||||
*err = -EFAULT;
|
return 0;
|
||||||
return (__force __wsum) ret;
|
return (__force __wsum) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,12 +69,11 @@ long __csum_partial_copy_to_user(const void *src,
|
||||||
|
|
||||||
static inline __wsum
|
static inline __wsum
|
||||||
csum_and_copy_to_user(const void *src,
|
csum_and_copy_to_user(const void *src,
|
||||||
void __user *dst, int len,
|
void __user *dst, int len)
|
||||||
__wsum sum, int *err)
|
|
||||||
{
|
{
|
||||||
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)
|
if (ret < 0)
|
||||||
*err = -EFAULT;
|
return 0;
|
||||||
return (__force __wsum) ret;
|
return (__force __wsum) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,22 +44,19 @@ static inline __wsum csum_partial_copy_nocheck(const void *src, void *dst, int l
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __wsum csum_and_copy_from_user(const void __user *src,
|
static inline __wsum csum_and_copy_from_user(const void __user *src,
|
||||||
void *dst, int len,
|
void *dst, int len)
|
||||||
__wsum sum, int *err_ptr)
|
|
||||||
{
|
{
|
||||||
__wsum ret;
|
__wsum ret;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
if (!user_access_begin(src, len)) {
|
if (!user_access_begin(src, len))
|
||||||
if (len)
|
return 0;
|
||||||
*err_ptr = -EFAULT;
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
ret = csum_partial_copy_generic((__force void *)src, dst,
|
ret = csum_partial_copy_generic((__force void *)src, dst,
|
||||||
len, sum, err_ptr, NULL);
|
len, ~0U, &err, NULL);
|
||||||
user_access_end();
|
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,
|
static inline __wsum csum_and_copy_to_user(const void *src,
|
||||||
void __user *dst,
|
void __user *dst,
|
||||||
int len, __wsum sum,
|
int len)
|
||||||
int *err_ptr)
|
|
||||||
{
|
{
|
||||||
__wsum ret;
|
__wsum ret;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
if (user_access_begin(dst, len)) {
|
if (!user_access_begin(dst, len))
|
||||||
ret = csum_partial_copy_generic(src, (__force void *)dst,
|
return 0;
|
||||||
len, sum, NULL, err_ptr);
|
|
||||||
user_access_end();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len)
|
ret = csum_partial_copy_generic(src, (__force void *)dst,
|
||||||
*err_ptr = -EFAULT;
|
len, ~0U, NULL, &err);
|
||||||
|
user_access_end();
|
||||||
return (__force __wsum)-1; /* invalid checksum */
|
return err ? 0 : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _ASM_X86_CHECKSUM_32_H */
|
#endif /* _ASM_X86_CHECKSUM_32_H */
|
||||||
|
|
|
@ -135,10 +135,8 @@ extern __visible __wsum csum_partial_copy_generic(const void *src, const void *d
|
||||||
int *src_err_ptr, int *dst_err_ptr);
|
int *src_err_ptr, int *dst_err_ptr);
|
||||||
|
|
||||||
|
|
||||||
extern __wsum csum_and_copy_from_user(const void __user *src, void *dst,
|
extern __wsum csum_and_copy_from_user(const void __user *src, void *dst, int len);
|
||||||
int len, __wsum isum, int *errp);
|
extern __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len);
|
||||||
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);
|
extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,13 +22,15 @@
|
||||||
*/
|
*/
|
||||||
__wsum
|
__wsum
|
||||||
csum_and_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)
|
int len)
|
||||||
{
|
{
|
||||||
|
int err = 0;
|
||||||
|
__wsum isum = ~0U;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
*errp = 0;
|
|
||||||
|
|
||||||
if (!user_access_begin(src, len))
|
if (!user_access_begin(src, len))
|
||||||
goto out_err;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Why 6, not 7? To handle odd addresses aligned we
|
* 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,
|
isum = csum_partial_copy_generic((__force const void *)src,
|
||||||
dst, len, isum, errp, NULL);
|
dst, len, isum, &err, NULL);
|
||||||
user_access_end();
|
user_access_end();
|
||||||
if (unlikely(*errp))
|
if (unlikely(err))
|
||||||
goto out_err;
|
isum = 0;
|
||||||
|
|
||||||
return isum;
|
return isum;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
user_access_end();
|
user_access_end();
|
||||||
out_err:
|
return 0;
|
||||||
*errp = -EFAULT;
|
|
||||||
memset(dst, 0, len);
|
|
||||||
|
|
||||||
return isum;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(csum_and_copy_from_user);
|
EXPORT_SYMBOL(csum_and_copy_from_user);
|
||||||
|
|
||||||
|
@ -83,16 +80,15 @@ EXPORT_SYMBOL(csum_and_copy_from_user);
|
||||||
*/
|
*/
|
||||||
__wsum
|
__wsum
|
||||||
csum_and_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)
|
int len)
|
||||||
{
|
{
|
||||||
__wsum ret;
|
__wsum ret, isum = ~0U;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
if (!user_access_begin(dst, len)) {
|
if (!user_access_begin(dst, len))
|
||||||
*errp = -EFAULT;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely((unsigned long)dst & 6)) {
|
if (unlikely((unsigned long)dst & 6)) {
|
||||||
while (((unsigned long)dst & 6) && len >= 2) {
|
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,
|
ret = csum_partial_copy_generic(src, (void __force *)dst,
|
||||||
len, isum, NULL, errp);
|
len, isum, NULL, &err);
|
||||||
user_access_end();
|
user_access_end();
|
||||||
return ret;
|
return err ? 0 : ret;
|
||||||
out:
|
out:
|
||||||
user_access_end();
|
user_access_end();
|
||||||
*errp = -EFAULT;
|
return 0;
|
||||||
return isum;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(csum_and_copy_to_user);
|
EXPORT_SYMBOL(csum_and_copy_to_user);
|
||||||
|
|
||||||
|
|
|
@ -35,27 +35,4 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
|
||||||
return csum_fold(sum);
|
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
|
#endif
|
||||||
|
|
|
@ -55,14 +55,16 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len)
|
||||||
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
||||||
static inline
|
static inline
|
||||||
__wsum csum_and_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)
|
int len)
|
||||||
{
|
{
|
||||||
if (access_ok(src, len))
|
int err = 0;
|
||||||
return csum_partial_copy_generic((__force const void *)src, dst,
|
|
||||||
len, sum, err_ptr, NULL);
|
if (!access_ok(src, len))
|
||||||
if (len)
|
return 0;
|
||||||
*err_ptr = -EFAULT;
|
|
||||||
return sum;
|
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
|
#define HAVE_CSUM_COPY_USER
|
||||||
static __inline__ __wsum csum_and_copy_to_user(const void *src,
|
static __inline__ __wsum csum_and_copy_to_user(const void *src,
|
||||||
void __user *dst, int len,
|
void __user *dst, int len)
|
||||||
__wsum sum, int *err_ptr)
|
|
||||||
{
|
{
|
||||||
if (access_ok(dst, len))
|
int err = 0;
|
||||||
return csum_partial_copy_generic(src,dst,len,sum,NULL,err_ptr);
|
__wsum sum = ~0U;
|
||||||
|
|
||||||
if (len)
|
if (!access_ok(dst, len))
|
||||||
*err_ptr = -EFAULT;
|
return 0;
|
||||||
|
|
||||||
return (__force __wsum)-1; /* invalid checksum */
|
sum = csum_partial_copy_generic(src,dst,len,sum,NULL,&err);
|
||||||
|
return err ? 0 : sum;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,26 +24,23 @@
|
||||||
#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
|
||||||
static inline
|
static inline
|
||||||
__wsum csum_and_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)
|
int len)
|
||||||
{
|
{
|
||||||
if (copy_from_user(dst, src, len))
|
if (copy_from_user(dst, src, len))
|
||||||
*err_ptr = -EFAULT;
|
return 0;
|
||||||
return csum_partial(dst, len, sum);
|
return csum_partial(dst, len, ~0U);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_CSUM_COPY_USER
|
#ifndef HAVE_CSUM_COPY_USER
|
||||||
static __inline__ __wsum csum_and_copy_to_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)
|
if (copy_to_user(dst, src, len) == 0)
|
||||||
return sum;
|
return sum;
|
||||||
if (len)
|
return 0;
|
||||||
*err_ptr = -EFAULT;
|
|
||||||
|
|
||||||
return (__force __wsum)-1; /* invalid checksum */
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1449,15 +1449,14 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
iterate_and_advance(i, bytes, v, ({
|
iterate_and_advance(i, bytes, v, ({
|
||||||
int err = 0;
|
|
||||||
next = csum_and_copy_from_user(v.iov_base,
|
next = csum_and_copy_from_user(v.iov_base,
|
||||||
(to += v.iov_len) - v.iov_len,
|
(to += v.iov_len) - v.iov_len,
|
||||||
v.iov_len, ~0U, &err);
|
v.iov_len);
|
||||||
if (!err) {
|
if (next) {
|
||||||
sum = csum_block_add(sum, next, off);
|
sum = csum_block_add(sum, next, off);
|
||||||
off += v.iov_len;
|
off += v.iov_len;
|
||||||
}
|
}
|
||||||
err ? v.iov_len : 0;
|
next ? 0 : v.iov_len;
|
||||||
}), ({
|
}), ({
|
||||||
char *p = kmap_atomic(v.bv_page);
|
char *p = kmap_atomic(v.bv_page);
|
||||||
sum = csum_and_memcpy((to += v.bv_len) - v.bv_len,
|
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))
|
if (unlikely(i->count < bytes))
|
||||||
return false;
|
return false;
|
||||||
iterate_all_kinds(i, bytes, v, ({
|
iterate_all_kinds(i, bytes, v, ({
|
||||||
int err = 0;
|
|
||||||
next = csum_and_copy_from_user(v.iov_base,
|
next = csum_and_copy_from_user(v.iov_base,
|
||||||
(to += v.iov_len) - v.iov_len,
|
(to += v.iov_len) - v.iov_len,
|
||||||
v.iov_len, ~0U, &err);
|
v.iov_len);
|
||||||
if (err)
|
if (!next)
|
||||||
return false;
|
return false;
|
||||||
sum = csum_block_add(sum, next, off);
|
sum = csum_block_add(sum, next, off);
|
||||||
off += v.iov_len;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
iterate_and_advance(i, bytes, v, ({
|
iterate_and_advance(i, bytes, v, ({
|
||||||
int err = 0;
|
|
||||||
next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len,
|
next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len,
|
||||||
v.iov_base,
|
v.iov_base,
|
||||||
v.iov_len, ~0U, &err);
|
v.iov_len);
|
||||||
if (!err) {
|
if (next) {
|
||||||
sum = csum_block_add(sum, next, off);
|
sum = csum_block_add(sum, next, off);
|
||||||
off += v.iov_len;
|
off += v.iov_len;
|
||||||
}
|
}
|
||||||
err ? v.iov_len : 0;
|
next ? 0 : v.iov_len;
|
||||||
}), ({
|
}), ({
|
||||||
char *p = kmap_atomic(v.bv_page);
|
char *p = kmap_atomic(v.bv_page);
|
||||||
sum = csum_and_memcpy(p + v.bv_offset,
|
sum = csum_and_memcpy(p + v.bv_offset,
|
||||||
|
|
Loading…
Reference in New Issue