asm-generic changes for 5.15
The main content for 5.15 is a series that cleans up the handling of strncpy_from_user() and strnlen_user(), removing a lot of slightly incorrect versions of these in favor of the lib/strn*.c helpers that implement these correctly and more efficiently. The only architectures that retain a private version now are mips, ia64, um and parisc. I had offered to convert those at all, but Thomas Bogendoerfer wanted to keep the mips version for the moment until he had a chance to do regression testing. The branch also contains two patches for bitops and for ffs(). Signed-off-by: Arnd Bergmann <arnd@arndb.de> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAYS82fGCrR//JCVInAQL9AxAAruOge7r8vzXQC8ehR4iw4/pCyzsLWdjh bLvTCovhD6y1KXb0cU3qMI2SUESwy/w9YteyLs4Edh5Yhm9uWIXz2WO6zTNDuW1g eNd6lcmoOLOXFxCUX3TZqvnxaEEiedjEJjOTicTBRv8c79Kw+2DTFYEwi8MIWlbx gGdGLOJ2SORl6HeE+wn8bfMPCChisMod75koi+Vnp3kp9+aw8VIi0RVMjtZ4HI3v z9H0DD0jDAy1eaXnC2+dsaIyrAq8/Lo/pqVBvUJRoBFaV/FHvNH2M0yl15yJYx1V 1KNJlBhoedc0PiMO9OnsRS1GMq1kEeo+u9gJPqphZQWooAQotD5C0sXsPnsghGo0 IrsVANy4H0k2h0AazRZd3KwV03aJ6FWHz3qyvbglLAQjKU1MgZTgroF5Q6R2FMtV /VtswpGB707+oGtmFvHc1lVgRYZTfduGT1jjBgwUuTUmLhI3/yRIlnodd6dXneX6 FOK3WbxlhUuIaSZLObLved/yNBgoOajP3vHIUc4c9HrsPEvkjKPB1g/VpbqqWVXe vF5/MeUN+b3Rq+h1GnnZQmhiOPIydZmK3qK7zYzp5Da+Ke4I2zWv/Et0/eFSZmh8 rS/cNMLshSOKMbaPvdopUnWhLspUh82wWDNjDFJx2XNlStVpFkMikKtSY4TrtbV+ zzHxZpLyQxc= =NB0a -----END PGP SIGNATURE----- Merge tag 'asm-generic-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic Pull asm-generic updates from Arnd Bergmann: "The main content for 5.15 is a series that cleans up the handling of strncpy_from_user() and strnlen_user(), removing a lot of slightly incorrect versions of these in favor of the lib/strn*.c helpers that implement these correctly and more efficiently. The only architectures that retain a private version now are mips, ia64, um and parisc. I had offered to convert those at all, but Thomas Bogendoerfer wanted to keep the mips version for the moment until he had a chance to do regression testing. The branch also contains two patches for bitops and for ffs()" * tag 'asm-generic-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic: bitops/non-atomic: make @nr unsigned to avoid any DIV asm-generic: ffs: Drop bogus reference to ffz location asm-generic: reverse GENERIC_{STRNCPY_FROM,STRNLEN}_USER symbols asm-generic: remove extra strn{cpy_from,len}_user declarations asm-generic: uaccess: remove inline strncpy_from_user/strnlen_user s390: use generic strncpy/strnlen from_user microblaze: use generic strncpy/strnlen from_user csky: use generic strncpy/strnlen from_user arc: use generic strncpy/strnlen from_user hexagon: use generic strncpy/strnlen from_user h8300: remove stale strncpy_from_user asm-generic/uaccess.h: remove __strncpy_from_user/__strnlen_user
This commit is contained in:
commit
4cdc4cc2ad
|
@ -28,8 +28,6 @@ config ALPHA
|
|||
select AUDIT_ARCH
|
||||
select GENERIC_CPU_VULNERABILITIES
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select MODULES_USE_ELF_RELA
|
||||
|
|
|
@ -655,88 +655,16 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
|
|||
return res;
|
||||
}
|
||||
|
||||
static inline long
|
||||
__arc_strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
{
|
||||
long res = 0;
|
||||
char val;
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" mov lp_count, %5 \n"
|
||||
" lp 3f \n"
|
||||
"1: ldb.ab %3, [%2, 1] \n"
|
||||
" breq.d %3, 0, 3f \n"
|
||||
" stb.ab %3, [%1, 1] \n"
|
||||
" add %0, %0, 1 # Num of NON NULL bytes copied \n"
|
||||
"3: \n"
|
||||
" .section .fixup, \"ax\" \n"
|
||||
" .align 4 \n"
|
||||
"4: mov %0, %4 # sets @res as -EFAULT \n"
|
||||
" j 3b \n"
|
||||
" .previous \n"
|
||||
" .section __ex_table, \"a\" \n"
|
||||
" .align 4 \n"
|
||||
" .word 1b, 4b \n"
|
||||
" .previous \n"
|
||||
: "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
|
||||
: "g"(-EFAULT), "r"(count)
|
||||
: "lp_count", "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline long __arc_strnlen_user(const char __user *s, long n)
|
||||
{
|
||||
long res, tmp1, cnt;
|
||||
char val;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" mov %2, %1 \n"
|
||||
"1: ldb.ab %3, [%0, 1] \n"
|
||||
" breq.d %3, 0, 2f \n"
|
||||
" sub.f %2, %2, 1 \n"
|
||||
" bnz 1b \n"
|
||||
" sub %2, %2, 1 \n"
|
||||
"2: sub %0, %1, %2 \n"
|
||||
"3: ;nop \n"
|
||||
" .section .fixup, \"ax\" \n"
|
||||
" .align 4 \n"
|
||||
"4: mov %0, 0 \n"
|
||||
" j 3b \n"
|
||||
" .previous \n"
|
||||
" .section __ex_table, \"a\" \n"
|
||||
" .align 4 \n"
|
||||
" .word 1b, 4b \n"
|
||||
" .previous \n"
|
||||
: "=r"(res), "=r"(tmp1), "=r"(cnt), "=r"(val)
|
||||
: "0"(s), "1"(n)
|
||||
: "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
||||
|
||||
#define INLINE_COPY_TO_USER
|
||||
#define INLINE_COPY_FROM_USER
|
||||
|
||||
#define __clear_user(d, n) __arc_clear_user(d, n)
|
||||
#define __strncpy_from_user(d, s, n) __arc_strncpy_from_user(d, s, n)
|
||||
#define __strnlen_user(s, n) __arc_strnlen_user(s, n)
|
||||
#else
|
||||
extern unsigned long arc_clear_user_noinline(void __user *to,
|
||||
unsigned long n);
|
||||
extern long arc_strncpy_from_user_noinline (char *dst, const char __user *src,
|
||||
long count);
|
||||
extern long arc_strnlen_user_noinline(const char __user *src, long n);
|
||||
|
||||
#define __clear_user(d, n) arc_clear_user_noinline(d, n)
|
||||
#define __strncpy_from_user(d, s, n) arc_strncpy_from_user_noinline(d, s, n)
|
||||
#define __strnlen_user(s, n) arc_strnlen_user_noinline(s, n)
|
||||
|
||||
#endif
|
||||
|
||||
#include <asm/segment.h>
|
||||
|
|
|
@ -32,16 +32,4 @@ unsigned long arc_clear_user_noinline(void __user *to,
|
|||
}
|
||||
EXPORT_SYMBOL(arc_clear_user_noinline);
|
||||
|
||||
long arc_strncpy_from_user_noinline(char *dst, const char __user *src,
|
||||
long count)
|
||||
{
|
||||
return __arc_strncpy_from_user(dst, src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(arc_strncpy_from_user_noinline);
|
||||
|
||||
long arc_strnlen_user_noinline(const char __user *src, long n)
|
||||
{
|
||||
return __arc_strnlen_user(src, n);
|
||||
}
|
||||
EXPORT_SYMBOL(arc_strnlen_user_noinline);
|
||||
#endif
|
||||
|
|
|
@ -63,8 +63,6 @@ config ARM
|
|||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HARDIRQS_SW_RESEND
|
||||
select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
|
||||
|
|
|
@ -130,8 +130,6 @@ config ARM64
|
|||
select GENERIC_PTDUMP
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_GETTIMEOFDAY
|
||||
select GENERIC_VDSO_TIME_NS
|
||||
|
|
|
@ -209,12 +209,6 @@ unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n);
|
|||
unsigned long __clear_user(void __user *to, unsigned long n);
|
||||
#define __clear_user __clear_user
|
||||
|
||||
long __strncpy_from_user(char *dst, const char *src, long count);
|
||||
#define __strncpy_from_user __strncpy_from_user
|
||||
|
||||
long __strnlen_user(const char *s, long n);
|
||||
#define __strnlen_user __strnlen_user
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm-generic/uaccess.h>
|
||||
|
||||
|
|
|
@ -142,108 +142,6 @@ unsigned long raw_copy_to_user(void *to, const void *from,
|
|||
}
|
||||
EXPORT_SYMBOL(raw_copy_to_user);
|
||||
|
||||
/*
|
||||
* __strncpy_from_user: - Copy a NUL terminated string from userspace,
|
||||
* with less checking.
|
||||
* @dst: Destination address, in kernel space. This buffer must be at
|
||||
* least @count bytes long.
|
||||
* @src: Source address, in user space.
|
||||
* @count: Maximum number of bytes to copy, including the trailing NUL.
|
||||
*
|
||||
* Copies a NUL-terminated string from userspace to kernel space.
|
||||
* Caller must check the specified block with access_ok() before calling
|
||||
* this function.
|
||||
*
|
||||
* On success, returns the length of the string (not including the trailing
|
||||
* NUL).
|
||||
*
|
||||
* If access to userspace fails, returns -EFAULT (some data may have been
|
||||
* copied).
|
||||
*
|
||||
* If @count is smaller than the length of the string, copies @count bytes
|
||||
* and returns @count.
|
||||
*/
|
||||
long __strncpy_from_user(char *dst, const char *src, long count)
|
||||
{
|
||||
long res, faultres;
|
||||
int tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" cmpnei %3, 0 \n"
|
||||
" bf 4f \n"
|
||||
"1: cmpnei %1, 0 \n"
|
||||
" bf 5f \n"
|
||||
"2: ldb %4, (%3, 0) \n"
|
||||
" stb %4, (%2, 0) \n"
|
||||
" cmpnei %4, 0 \n"
|
||||
" bf 3f \n"
|
||||
" addi %3, 1 \n"
|
||||
" addi %2, 1 \n"
|
||||
" subi %1, 1 \n"
|
||||
" br 1b \n"
|
||||
"3: subu %0, %1 \n"
|
||||
" br 5f \n"
|
||||
"4: mov %0, %5 \n"
|
||||
" br 5f \n"
|
||||
".section __ex_table, \"a\" \n"
|
||||
".align 2 \n"
|
||||
".long 2b, 4b \n"
|
||||
".previous \n"
|
||||
"5: \n"
|
||||
: "=r"(res), "=r"(count), "=r"(dst),
|
||||
"=r"(src), "=r"(tmp), "=r"(faultres)
|
||||
: "5"(-EFAULT), "0"(count), "1"(count),
|
||||
"2"(dst), "3"(src)
|
||||
: "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(__strncpy_from_user);
|
||||
|
||||
/*
|
||||
* strnlen_user: - Get the size of a string in user space.
|
||||
* @str: The string to measure.
|
||||
* @n: The maximum valid length
|
||||
*
|
||||
* Get the size of a NUL-terminated string in user space.
|
||||
*
|
||||
* Returns the size of the string INCLUDING the terminating NUL.
|
||||
* On exception, returns 0.
|
||||
* If the string is too long, returns a value greater than @n.
|
||||
*/
|
||||
long __strnlen_user(const char *s, long n)
|
||||
{
|
||||
unsigned long res, tmp;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" cmpnei %1, 0 \n"
|
||||
" bf 3f \n"
|
||||
"1: cmpnei %0, 0 \n"
|
||||
" bf 3f \n"
|
||||
"2: ldb %3, (%1, 0) \n"
|
||||
" cmpnei %3, 0 \n"
|
||||
" bf 3f \n"
|
||||
" subi %0, 1 \n"
|
||||
" addi %1, 1 \n"
|
||||
" br 1b \n"
|
||||
"3: subu %2, %0 \n"
|
||||
" addi %2, 1 \n"
|
||||
" br 5f \n"
|
||||
"4: movi %0, 0 \n"
|
||||
" br 5f \n"
|
||||
".section __ex_table, \"a\" \n"
|
||||
".align 2 \n"
|
||||
".long 2b, 4b \n"
|
||||
".previous \n"
|
||||
"5: \n"
|
||||
: "=r"(n), "=r"(s), "=r"(res), "=r"(tmp)
|
||||
: "0"(n), "1"(s), "2"(n)
|
||||
: "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
|
||||
/*
|
||||
* __clear_user: - Zero a block of memory in user space, with less checking.
|
||||
* @to: Destination address, in user space.
|
||||
|
|
|
@ -19,7 +19,6 @@ asmlinkage long __mulsi3(long, long);
|
|||
asmlinkage long __udivsi3(long, long);
|
||||
asmlinkage void *memcpy(void *, const void *, size_t);
|
||||
asmlinkage void *memset(void *, int, size_t);
|
||||
asmlinkage long strncpy_from_user(void *to, void *from, size_t n);
|
||||
|
||||
/* gcc lib functions */
|
||||
EXPORT_SYMBOL(__ucmpdi2);
|
||||
|
@ -34,4 +33,3 @@ EXPORT_SYMBOL(__mulsi3);
|
|||
EXPORT_SYMBOL(__udivsi3);
|
||||
EXPORT_SYMBOL(memcpy);
|
||||
EXPORT_SYMBOL(memset);
|
||||
EXPORT_SYMBOL(strncpy_from_user);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# Makefile for H8/300-specific library files..
|
||||
#
|
||||
|
||||
lib-y = memcpy.o memset.o abs.o strncpy.o \
|
||||
lib-y = memcpy.o memset.o abs.o \
|
||||
mulsi3.o udivsi3.o muldi3.o moddivsi3.o \
|
||||
ashldi3.o lshrdi3.o ashrdi3.o ucmpdi2.o \
|
||||
delay.o
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
;;; SPDX-License-Identifier: GPL-2.0
|
||||
;;; strncpy.S
|
||||
|
||||
#include <asm/linkage.h>
|
||||
|
||||
.text
|
||||
.global strncpy_from_user
|
||||
|
||||
;;; long strncpy_from_user(void *to, void *from, size_t n)
|
||||
strncpy_from_user:
|
||||
mov.l er2,er2
|
||||
bne 1f
|
||||
sub.l er0,er0
|
||||
rts
|
||||
1:
|
||||
mov.l er4,@-sp
|
||||
sub.l er3,er3
|
||||
2:
|
||||
mov.b @er1+,r4l
|
||||
mov.b r4l,@er0
|
||||
adds #1,er0
|
||||
beq 3f
|
||||
inc.l #1,er3
|
||||
dec.l #1,er2
|
||||
bne 2b
|
||||
3:
|
||||
dec.l #1,er2
|
||||
4:
|
||||
mov.b r4l,@er0
|
||||
adds #1,er0
|
||||
dec.l #1,er2
|
||||
bne 4b
|
||||
mov.l er3,er0
|
||||
mov.l @sp+,er4
|
||||
rts
|
|
@ -57,38 +57,7 @@ unsigned long raw_copy_to_user(void __user *to, const void *from,
|
|||
__kernel_size_t __clear_user_hexagon(void __user *dest, unsigned long count);
|
||||
#define __clear_user(a, s) __clear_user_hexagon((a), (s))
|
||||
|
||||
#define __strncpy_from_user(dst, src, n) hexagon_strncpy_from_user(dst, src, n)
|
||||
|
||||
/* get around the ifndef in asm-generic/uaccess.h */
|
||||
#define __strnlen_user __strnlen_user
|
||||
|
||||
extern long __strnlen_user(const char __user *src, long n);
|
||||
|
||||
static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
|
||||
long n);
|
||||
|
||||
#include <asm-generic/uaccess.h>
|
||||
|
||||
/* Todo: an actual accelerated version of this. */
|
||||
static inline long hexagon_strncpy_from_user(char *dst, const char __user *src,
|
||||
long n)
|
||||
{
|
||||
long res = __strnlen_user(src, n);
|
||||
|
||||
if (unlikely(!res))
|
||||
return -EFAULT;
|
||||
|
||||
if (res > n) {
|
||||
long left = raw_copy_from_user(dst, src, n);
|
||||
if (unlikely(left))
|
||||
memset(dst + (n - left), 0, left);
|
||||
return n;
|
||||
} else {
|
||||
long left = raw_copy_from_user(dst, src, res);
|
||||
if (unlikely(left))
|
||||
memset(dst + (res - left), 0, left);
|
||||
return res-1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,7 +15,6 @@ EXPORT_SYMBOL(__clear_user_hexagon);
|
|||
EXPORT_SYMBOL(raw_copy_from_user);
|
||||
EXPORT_SYMBOL(raw_copy_to_user);
|
||||
EXPORT_SYMBOL(iounmap);
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
EXPORT_SYMBOL(__vmgetie);
|
||||
EXPORT_SYMBOL(__vmsetie);
|
||||
EXPORT_SYMBOL(__vmyield);
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
#
|
||||
|
||||
obj-y := init.o ioremap.o uaccess.o vm_fault.o cache.o
|
||||
obj-y += copy_to_user.o copy_from_user.o strnlen_user.o vm_tlb.o
|
||||
obj-y += copy_to_user.o copy_from_user.o vm_tlb.o
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* User string length functions for kernel
|
||||
*
|
||||
* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define isrc r0
|
||||
#define max r1 /* Do not change! */
|
||||
|
||||
#define end r2
|
||||
#define tmp1 r3
|
||||
|
||||
#define obo r6 /* off-by-one */
|
||||
#define start r7
|
||||
#define mod8 r8
|
||||
#define dbuf r15:14
|
||||
#define dcmp r13:12
|
||||
|
||||
/*
|
||||
* The vector mask version of this turned out *really* badly.
|
||||
* The hardware loop version also turned out *really* badly.
|
||||
* Seems straight pointer arithmetic basically wins here.
|
||||
*/
|
||||
|
||||
#define fname __strnlen_user
|
||||
|
||||
.text
|
||||
.global fname
|
||||
.type fname, @function
|
||||
.p2align 5 /* why? */
|
||||
fname:
|
||||
{
|
||||
mod8 = and(isrc,#7);
|
||||
end = add(isrc,max);
|
||||
start = isrc;
|
||||
}
|
||||
{
|
||||
P0 = cmp.eq(mod8,#0);
|
||||
mod8 = and(end,#7);
|
||||
dcmp = #0;
|
||||
if (P0.new) jump:t dw_loop; /* fire up the oven */
|
||||
}
|
||||
|
||||
alignment_loop:
|
||||
fail_1: {
|
||||
tmp1 = memb(start++#1);
|
||||
}
|
||||
{
|
||||
P0 = cmp.eq(tmp1,#0);
|
||||
if (P0.new) jump:nt exit_found;
|
||||
P1 = cmp.gtu(end,start);
|
||||
mod8 = and(start,#7);
|
||||
}
|
||||
{
|
||||
if (!P1) jump exit_error; /* hit the end */
|
||||
P0 = cmp.eq(mod8,#0);
|
||||
}
|
||||
{
|
||||
if (!P0) jump alignment_loop;
|
||||
}
|
||||
|
||||
|
||||
|
||||
dw_loop:
|
||||
fail_2: {
|
||||
dbuf = memd(start);
|
||||
obo = add(start,#1);
|
||||
}
|
||||
{
|
||||
P0 = vcmpb.eq(dbuf,dcmp);
|
||||
}
|
||||
{
|
||||
tmp1 = P0;
|
||||
P0 = cmp.gtu(end,start);
|
||||
}
|
||||
{
|
||||
tmp1 = ct0(tmp1);
|
||||
mod8 = and(end,#7);
|
||||
if (!P0) jump end_check;
|
||||
}
|
||||
{
|
||||
P0 = cmp.eq(tmp1,#32);
|
||||
if (!P0.new) jump:nt exit_found;
|
||||
if (!P0.new) start = add(obo,tmp1);
|
||||
}
|
||||
{
|
||||
start = add(start,#8);
|
||||
jump dw_loop;
|
||||
} /* might be nice to combine these jumps... */
|
||||
|
||||
|
||||
end_check:
|
||||
{
|
||||
P0 = cmp.gt(tmp1,mod8);
|
||||
if (P0.new) jump:nt exit_error; /* neverfound! */
|
||||
start = add(obo,tmp1);
|
||||
}
|
||||
|
||||
exit_found:
|
||||
{
|
||||
R0 = sub(start,isrc);
|
||||
jumpr R31;
|
||||
}
|
||||
|
||||
exit_error:
|
||||
{
|
||||
R0 = add(max,#1);
|
||||
jumpr R31;
|
||||
}
|
||||
|
||||
/* Uh, what does the "fixup" return here? */
|
||||
.falign
|
||||
fix_1:
|
||||
{
|
||||
R0 = #0;
|
||||
jumpr R31;
|
||||
}
|
||||
|
||||
.size fname,.-fname
|
||||
|
||||
|
||||
.section __ex_table,"a"
|
||||
.long fail_1,fix_1
|
||||
.long fail_2,fix_1
|
||||
.previous
|
|
@ -9,6 +9,8 @@ menu "Processor type and features"
|
|||
config IA64
|
||||
bool
|
||||
select ARCH_HAS_DMA_MARK_CLEAN
|
||||
select ARCH_HAS_STRNCPY_FROM_USER
|
||||
select ARCH_HAS_STRNLEN_USER
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select ARCH_MIGHT_HAVE_PC_SERIO
|
||||
select ACPI
|
||||
|
|
|
@ -16,8 +16,6 @@ config M68K
|
|||
select GENERIC_CPU_DEVICES
|
||||
select GENERIC_IOMAP
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_STRNCPY_FROM_USER if MMU
|
||||
select GENERIC_STRNLEN_USER if MMU
|
||||
select HAVE_AOUT if MMU
|
||||
select HAVE_ASM_MODVERSIONS
|
||||
select HAVE_DEBUG_BUGVERBOSE
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
# define get_fs() (current_thread_info()->addr_limit)
|
||||
# define set_fs(val) (current_thread_info()->addr_limit = (val))
|
||||
# define user_addr_max() get_fs().seg
|
||||
|
||||
# define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
|
@ -296,28 +297,14 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
|
|||
/*
|
||||
* Copy a null terminated string from userspace.
|
||||
*/
|
||||
extern int __strncpy_user(char *to, const char __user *from, int len);
|
||||
|
||||
static inline long
|
||||
strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
{
|
||||
if (!access_ok(src, 1))
|
||||
return -EFAULT;
|
||||
return __strncpy_user(dst, src, count);
|
||||
}
|
||||
__must_check long strncpy_from_user(char *dst, const char __user *src,
|
||||
long count);
|
||||
|
||||
/*
|
||||
* Return the size of a string (including the ending 0)
|
||||
*
|
||||
* Return 0 on exception, a value greater than N if too long
|
||||
*/
|
||||
extern int __strnlen_user(const char __user *sstr, int len);
|
||||
|
||||
static inline long strnlen_user(const char __user *src, long n)
|
||||
{
|
||||
if (!access_ok(src, 1))
|
||||
return 0;
|
||||
return __strnlen_user(src, n);
|
||||
}
|
||||
__must_check long strnlen_user(const char __user *sstr, long len);
|
||||
|
||||
#endif /* _ASM_MICROBLAZE_UACCESS_H */
|
||||
|
|
|
@ -26,7 +26,6 @@ EXPORT_SYMBOL(_mcount);
|
|||
* Assembly functions that may be used (directly or indirectly) by modules
|
||||
*/
|
||||
EXPORT_SYMBOL(__copy_tofrom_user);
|
||||
EXPORT_SYMBOL(__strncpy_user);
|
||||
|
||||
#ifdef CONFIG_OPT_LIB_ASM
|
||||
EXPORT_SYMBOL(memcpy);
|
||||
|
|
|
@ -12,96 +12,6 @@
|
|||
#include <linux/linkage.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
/*
|
||||
* int __strncpy_user(char *to, char *from, int len);
|
||||
*
|
||||
* Returns:
|
||||
* -EFAULT for an exception
|
||||
* len if we hit the buffer limit
|
||||
* bytes copied
|
||||
*/
|
||||
|
||||
.text
|
||||
.globl __strncpy_user;
|
||||
.type __strncpy_user, @function
|
||||
.align 4;
|
||||
__strncpy_user:
|
||||
|
||||
/*
|
||||
* r5 - to
|
||||
* r6 - from
|
||||
* r7 - len
|
||||
* r3 - temp count
|
||||
* r4 - temp val
|
||||
*/
|
||||
beqid r7,3f
|
||||
addik r3,r7,0 /* temp_count = len */
|
||||
1:
|
||||
lbu r4,r6,r0
|
||||
beqid r4,2f
|
||||
sb r4,r5,r0
|
||||
|
||||
addik r5,r5,1
|
||||
addik r6,r6,1 /* delay slot */
|
||||
|
||||
addik r3,r3,-1
|
||||
bnei r3,1b /* break on len */
|
||||
2:
|
||||
rsubk r3,r3,r7 /* temp_count = len - temp_count */
|
||||
3:
|
||||
rtsd r15,8
|
||||
nop
|
||||
.size __strncpy_user, . - __strncpy_user
|
||||
|
||||
.section .fixup, "ax"
|
||||
.align 2
|
||||
4:
|
||||
brid 3b
|
||||
addik r3,r0, -EFAULT
|
||||
|
||||
.section __ex_table, "a"
|
||||
.word 1b,4b
|
||||
|
||||
/*
|
||||
* int __strnlen_user(char __user *str, int maxlen);
|
||||
*
|
||||
* Returns:
|
||||
* 0 on error
|
||||
* maxlen + 1 if no NUL byte found within maxlen bytes
|
||||
* size of the string (including NUL byte)
|
||||
*/
|
||||
|
||||
.text
|
||||
.globl __strnlen_user;
|
||||
.type __strnlen_user, @function
|
||||
.align 4;
|
||||
__strnlen_user:
|
||||
beqid r6,3f
|
||||
addik r3,r6,0
|
||||
1:
|
||||
lbu r4,r5,r0
|
||||
beqid r4,2f /* break on NUL */
|
||||
addik r3,r3,-1 /* delay slot */
|
||||
|
||||
bneid r3,1b
|
||||
addik r5,r5,1 /* delay slot */
|
||||
|
||||
addik r3,r3,-1 /* for break on len */
|
||||
2:
|
||||
rsubk r3,r3,r6
|
||||
3:
|
||||
rtsd r15,8
|
||||
nop
|
||||
.size __strnlen_user, . - __strnlen_user
|
||||
|
||||
.section .fixup,"ax"
|
||||
4:
|
||||
brid 3b
|
||||
addk r3,r0,r0
|
||||
|
||||
.section __ex_table,"a"
|
||||
.word 1b,4b
|
||||
|
||||
/* Loop unrolling for __copy_tofrom_user */
|
||||
#define COPY(offset) \
|
||||
1: lwi r4 , r6, 0x0000 + offset; \
|
||||
|
|
|
@ -9,6 +9,8 @@ config MIPS
|
|||
select ARCH_HAS_KCOV
|
||||
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE if !EVA
|
||||
select ARCH_HAS_PTE_SPECIAL if !(32BIT && CPU_HAS_RIXI)
|
||||
select ARCH_HAS_STRNCPY_FROM_USER
|
||||
select ARCH_HAS_STRNLEN_USER
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||
select ARCH_HAS_GCOV_PROFILE_ALL
|
||||
|
|
|
@ -26,8 +26,6 @@ config NDS32
|
|||
select GENERIC_LIB_LSHRDI3
|
||||
select GENERIC_LIB_MULDI3
|
||||
select GENERIC_LIB_UCMPDI2
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
|
|
|
@ -13,8 +13,6 @@ config NIOS2
|
|||
select GENERIC_CPU_DEVICES
|
||||
select GENERIC_IRQ_PROBE
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_KGDB
|
||||
select IRQ_DOMAIN
|
||||
|
|
|
@ -25,8 +25,6 @@ config OPENRISC
|
|||
select HAVE_UID16
|
||||
select GENERIC_ATOMIC64
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select MODULES_USE_ELF_RELA
|
||||
select HAVE_DEBUG_STACKOVERFLOW
|
||||
|
|
|
@ -10,6 +10,7 @@ config PARISC
|
|||
select ARCH_HAS_ELF_RANDOMIZE
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX
|
||||
select ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||
select ARCH_HAS_STRNLEN_USER
|
||||
select ARCH_NO_SG_CHAIN
|
||||
select ARCH_SUPPORTS_HUGETLBFS if PA20
|
||||
select ARCH_SUPPORTS_MEMORY_FAILURE
|
||||
|
@ -33,7 +34,6 @@ config PARISC
|
|||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_CPU_DEVICES
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_LIB_DEVMEM_IS_ALLOWED
|
||||
select SYSCTL_ARCH_UNALIGN_ALLOW
|
||||
select SYSCTL_EXCEPTION_TRACE
|
||||
|
|
|
@ -183,8 +183,6 @@ config PPC
|
|||
select GENERIC_IRQ_SHOW_LEVEL
|
||||
select GENERIC_PCI_IOMAP if PCI
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_VDSO_TIME_NS
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
|
|
|
@ -56,8 +56,6 @@ config RISCV
|
|||
select GENERIC_PTDUMP if MMU
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_STRNCPY_FROM_USER if MMU
|
||||
select GENERIC_STRNLEN_USER if MMU
|
||||
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
|
||||
select HANDLE_DOMAIN_IRQ
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
|
|
|
@ -233,23 +233,9 @@ raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
|
|||
/*
|
||||
* Copy a null terminated string from userspace.
|
||||
*/
|
||||
long __must_check strncpy_from_user(char *dst, const char __user *src, long count);
|
||||
|
||||
long __strncpy_from_user(char *dst, const char __user *src, long count);
|
||||
|
||||
static inline long __must_check
|
||||
strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
{
|
||||
might_fault();
|
||||
return __strncpy_from_user(dst, src, count);
|
||||
}
|
||||
|
||||
unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count);
|
||||
|
||||
static inline unsigned long strnlen_user(const char __user *src, unsigned long n)
|
||||
{
|
||||
might_fault();
|
||||
return __strnlen_user(src, n);
|
||||
}
|
||||
long __must_check strnlen_user(const char __user *src, long count);
|
||||
|
||||
/*
|
||||
* Zero Userspace
|
||||
|
|
|
@ -338,55 +338,3 @@ unsigned long __clear_user(void __user *to, unsigned long size)
|
|||
return clear_user_xc(to, size);
|
||||
}
|
||||
EXPORT_SYMBOL(__clear_user);
|
||||
|
||||
static inline unsigned long strnlen_user_srst(const char __user *src,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long tmp1, tmp2;
|
||||
|
||||
asm volatile(
|
||||
" lghi 0,0\n"
|
||||
" la %2,0(%1)\n"
|
||||
" la %3,0(%0,%1)\n"
|
||||
" slgr %0,%0\n"
|
||||
" sacf 256\n"
|
||||
"0: srst %3,%2\n"
|
||||
" jo 0b\n"
|
||||
" la %0,1(%3)\n" /* strnlen_user results includes \0 */
|
||||
" slgr %0,%1\n"
|
||||
"1: sacf 768\n"
|
||||
EX_TABLE(0b,1b)
|
||||
: "+a" (size), "+a" (src), "=a" (tmp1), "=a" (tmp2)
|
||||
:
|
||||
: "cc", "memory", "0");
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned long __strnlen_user(const char __user *src, unsigned long size)
|
||||
{
|
||||
if (unlikely(!size))
|
||||
return 0;
|
||||
return strnlen_user_srst(src, size);
|
||||
}
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
|
||||
long __strncpy_from_user(char *dst, const char __user *src, long size)
|
||||
{
|
||||
size_t done, len, offset, len_str;
|
||||
|
||||
if (unlikely(size <= 0))
|
||||
return 0;
|
||||
done = 0;
|
||||
do {
|
||||
offset = (size_t)src & (L1_CACHE_BYTES - 1);
|
||||
len = min(size - done, L1_CACHE_BYTES - offset);
|
||||
if (copy_from_user(dst, src, len))
|
||||
return -EFAULT;
|
||||
len_str = strnlen(dst, len);
|
||||
done += len_str;
|
||||
src += len_str;
|
||||
dst += len_str;
|
||||
} while ((len_str == len) && (done < size));
|
||||
return done;
|
||||
}
|
||||
EXPORT_SYMBOL(__strncpy_from_user);
|
||||
|
|
|
@ -22,8 +22,6 @@ config SUPERH
|
|||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_PCI_IOMAP if PCI
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GUP_GET_PTE_LOW_HIGH if X2TLB
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
|
|
|
@ -37,8 +37,6 @@ config SPARC
|
|||
select HAVE_EBPF_JIT if SPARC64
|
||||
select HAVE_DEBUG_BUGVERBOSE
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select MODULES_USE_ELF_RELA
|
||||
select PCI_SYSCALL if PCI
|
||||
select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
|
||||
|
|
|
@ -7,6 +7,8 @@ config UML
|
|||
default y
|
||||
select ARCH_EPHEMERAL_INODES
|
||||
select ARCH_HAS_KCOV
|
||||
select ARCH_HAS_STRNCPY_FROM_USER
|
||||
select ARCH_HAS_STRNLEN_USER
|
||||
select ARCH_NO_PREEMPT
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
|
|
|
@ -23,16 +23,13 @@
|
|||
|
||||
extern unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n);
|
||||
extern unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n);
|
||||
extern long __strncpy_from_user(char *dst, const char __user *src, long count);
|
||||
extern long __strnlen_user(const void __user *str, long len);
|
||||
extern unsigned long __clear_user(void __user *mem, unsigned long len);
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size);
|
||||
|
||||
/* Teach asm-generic/uaccess.h that we have C functions for these. */
|
||||
#define __access_ok __access_ok
|
||||
#define __clear_user __clear_user
|
||||
#define __strnlen_user __strnlen_user
|
||||
#define __strncpy_from_user __strncpy_from_user
|
||||
|
||||
#define INLINE_COPY_FROM_USER
|
||||
#define INLINE_COPY_TO_USER
|
||||
|
||||
|
|
|
@ -189,11 +189,14 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
long __strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
long strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
{
|
||||
long n;
|
||||
char *ptr = dst;
|
||||
|
||||
if (!access_ok(src, 1))
|
||||
return -EFAULT;
|
||||
|
||||
if (uaccess_kernel()) {
|
||||
strncpy(dst, (__force void *) src, count);
|
||||
return strnlen(dst, count);
|
||||
|
@ -205,7 +208,7 @@ long __strncpy_from_user(char *dst, const char __user *src, long count)
|
|||
return -EFAULT;
|
||||
return strnlen(dst, count);
|
||||
}
|
||||
EXPORT_SYMBOL(__strncpy_from_user);
|
||||
EXPORT_SYMBOL(strncpy_from_user);
|
||||
|
||||
static int clear_chunk(unsigned long addr, int len, void *unused)
|
||||
{
|
||||
|
@ -236,10 +239,13 @@ static int strnlen_chunk(unsigned long str, int len, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
long __strnlen_user(const void __user *str, long len)
|
||||
long strnlen_user(const char __user *str, long len)
|
||||
{
|
||||
int count = 0, n;
|
||||
|
||||
if (!access_ok(str, 1))
|
||||
return -EFAULT;
|
||||
|
||||
if (uaccess_kernel())
|
||||
return strnlen((__force char*)str, len) + 1;
|
||||
|
||||
|
@ -248,7 +254,7 @@ long __strnlen_user(const void __user *str, long len)
|
|||
return count + 1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
EXPORT_SYMBOL(strnlen_user);
|
||||
|
||||
/**
|
||||
* arch_futex_atomic_op_inuser() - Atomic arithmetic operation with constant
|
||||
|
|
|
@ -145,8 +145,6 @@ config X86
|
|||
select GENERIC_PENDING_IRQ if SMP
|
||||
select GENERIC_PTDUMP
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
select GENERIC_TIME_VSYSCALL
|
||||
select GENERIC_GETTIMEOFDAY
|
||||
select GENERIC_VDSO_TIME_NS
|
||||
|
|
|
@ -7,6 +7,8 @@ config XTENSA
|
|||
select ARCH_HAS_SYNC_DMA_FOR_CPU if MMU
|
||||
select ARCH_HAS_SYNC_DMA_FOR_DEVICE if MMU
|
||||
select ARCH_HAS_DMA_SET_UNCACHED if MMU
|
||||
select ARCH_HAS_STRNCPY_FROM_USER if !KASAN
|
||||
select ARCH_HAS_STRNLEN_USER
|
||||
select ARCH_USE_MEMTEST
|
||||
select ARCH_USE_QUEUED_RWLOCKS
|
||||
select ARCH_USE_QUEUED_SPINLOCKS
|
||||
|
@ -20,7 +22,6 @@ config XTENSA
|
|||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_STRNCPY_FROM_USER if KASAN
|
||||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
|
||||
select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL
|
||||
|
|
|
@ -290,8 +290,7 @@ clear_user(void __user *addr, unsigned long size)
|
|||
#define __clear_user __xtensa_clear_user
|
||||
|
||||
|
||||
#ifndef CONFIG_GENERIC_STRNCPY_FROM_USER
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_STRNCPY_FROM_USER
|
||||
extern long __strncpy_user(char *dst, const char __user *src, long count);
|
||||
|
||||
static inline long
|
||||
|
|
|
@ -43,7 +43,7 @@ EXPORT_SYMBOL(memmove);
|
|||
EXPORT_SYMBOL(__memset);
|
||||
EXPORT_SYMBOL(__memcpy);
|
||||
EXPORT_SYMBOL(__memmove);
|
||||
#ifndef CONFIG_GENERIC_STRNCPY_FROM_USER
|
||||
#ifdef CONFIG_ARCH_HAS_STRNCPY_FROM_USER
|
||||
EXPORT_SYMBOL(__strncpy_user);
|
||||
#endif
|
||||
EXPORT_SYMBOL(clear_page);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
* This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
* differs in spirit from ffz (man ffs).
|
||||
*/
|
||||
#define ffs(x) __builtin_ffs(x)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
* This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
* differs in spirit from ffz (man ffs).
|
||||
*/
|
||||
static inline int ffs(int x)
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __always_inline void
|
||||
arch___set_bit(int nr, volatile unsigned long *addr)
|
||||
arch___set_bit(unsigned int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
@ -24,7 +24,7 @@ arch___set_bit(int nr, volatile unsigned long *addr)
|
|||
#define __set_bit arch___set_bit
|
||||
|
||||
static __always_inline void
|
||||
arch___clear_bit(int nr, volatile unsigned long *addr)
|
||||
arch___clear_bit(unsigned int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
@ -43,7 +43,7 @@ arch___clear_bit(int nr, volatile unsigned long *addr)
|
|||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __always_inline
|
||||
void arch___change_bit(int nr, volatile unsigned long *addr)
|
||||
void arch___change_bit(unsigned int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
@ -62,7 +62,7 @@ void arch___change_bit(int nr, volatile unsigned long *addr)
|
|||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __always_inline int
|
||||
arch___test_and_set_bit(int nr, volatile unsigned long *addr)
|
||||
arch___test_and_set_bit(unsigned int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
@ -83,7 +83,7 @@ arch___test_and_set_bit(int nr, volatile unsigned long *addr)
|
|||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __always_inline int
|
||||
arch___test_and_clear_bit(int nr, volatile unsigned long *addr)
|
||||
arch___test_and_clear_bit(unsigned int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
@ -96,7 +96,7 @@ arch___test_and_clear_bit(int nr, volatile unsigned long *addr)
|
|||
|
||||
/* WARNING: non atomic and it can be reordered! */
|
||||
static __always_inline int
|
||||
arch___test_and_change_bit(int nr, volatile unsigned long *addr)
|
||||
arch___test_and_change_bit(unsigned int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
@ -113,7 +113,7 @@ arch___test_and_change_bit(int nr, volatile unsigned long *addr)
|
|||
* @addr: Address to start counting from
|
||||
*/
|
||||
static __always_inline int
|
||||
arch_test_bit(int nr, const volatile unsigned long *addr)
|
||||
arch_test_bit(unsigned int nr, const volatile unsigned long *addr)
|
||||
{
|
||||
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
||||
}
|
||||
|
|
|
@ -119,6 +119,11 @@ static inline void set_fs(mm_segment_t fs)
|
|||
#ifndef uaccess_kernel
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
#endif
|
||||
|
||||
#ifndef user_addr_max
|
||||
#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_SET_FS */
|
||||
|
||||
#define access_ok(addr, size) __access_ok((unsigned long)(addr),(size))
|
||||
|
@ -243,50 +248,6 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
|
|||
|
||||
extern int __get_user_bad(void) __attribute__((noreturn));
|
||||
|
||||
/*
|
||||
* Copy a null terminated string from userspace.
|
||||
*/
|
||||
#ifndef __strncpy_from_user
|
||||
static inline long
|
||||
__strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
{
|
||||
char *tmp;
|
||||
strncpy(dst, (const char __force *)src, count);
|
||||
for (tmp = dst; *tmp && count > 0; tmp++, count--)
|
||||
;
|
||||
return (tmp - dst);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline long
|
||||
strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
{
|
||||
if (!access_ok(src, 1))
|
||||
return -EFAULT;
|
||||
return __strncpy_from_user(dst, src, count);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the size of a string (including the ending 0)
|
||||
*
|
||||
* Return 0 on exception, a value greater than N if too long
|
||||
*/
|
||||
#ifndef __strnlen_user
|
||||
#define __strnlen_user(s, n) (strnlen((s), (n)) + 1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unlike strnlen, strnlen_user includes the nul terminator in
|
||||
* its returned count. Callers should check for a returned value
|
||||
* greater than N as an indication the string is too long.
|
||||
*/
|
||||
static inline long strnlen_user(const char __user *src, long n)
|
||||
{
|
||||
if (!access_ok(src, 1))
|
||||
return 0;
|
||||
return __strnlen_user(src, n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero Userspace
|
||||
*/
|
||||
|
@ -311,4 +272,8 @@ clear_user(void __user *to, unsigned long n)
|
|||
|
||||
#include <asm/extable.h>
|
||||
|
||||
__must_check long strncpy_from_user(char *dst, const char __user *src,
|
||||
long count);
|
||||
__must_check long strnlen_user(const char __user *src, long n);
|
||||
|
||||
#endif /* __ASM_GENERIC_UACCESS_H */
|
||||
|
|
10
lib/Kconfig
10
lib/Kconfig
|
@ -50,12 +50,18 @@ config HAVE_ARCH_BITREVERSE
|
|||
This option enables the use of hardware bit-reversal instructions on
|
||||
architectures which support such operations.
|
||||
|
||||
config GENERIC_STRNCPY_FROM_USER
|
||||
config ARCH_HAS_STRNCPY_FROM_USER
|
||||
bool
|
||||
|
||||
config GENERIC_STRNLEN_USER
|
||||
config ARCH_HAS_STRNLEN_USER
|
||||
bool
|
||||
|
||||
config GENERIC_STRNCPY_FROM_USER
|
||||
def_bool !ARCH_HAS_STRNCPY_FROM_USER
|
||||
|
||||
config GENERIC_STRNLEN_USER
|
||||
def_bool !ARCH_HAS_STRNLEN_USER
|
||||
|
||||
config GENERIC_NET_UTILS
|
||||
bool
|
||||
|
||||
|
|
Loading…
Reference in New Issue