microblaze: use generic strncpy/strnlen from_user
Remove the microblaze implemenation of strncpy/strnlen and instead use the generic versions. The microblaze version is fairly slow because it always does byte accesses even for aligned data, and it lacks a checks for user_addr_max(). Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
@@ -21,6 +21,8 @@ config MICROBLAZE
|
|||||||
select GENERIC_IRQ_SHOW
|
select GENERIC_IRQ_SHOW
|
||||||
select GENERIC_PCI_IOMAP
|
select GENERIC_PCI_IOMAP
|
||||||
select GENERIC_SCHED_CLOCK
|
select GENERIC_SCHED_CLOCK
|
||||||
|
select GENERIC_STRNCPY_FROM_USER
|
||||||
|
select GENERIC_STRNLEN_USER
|
||||||
select HAVE_ARCH_HASH
|
select HAVE_ARCH_HASH
|
||||||
select HAVE_ARCH_KGDB
|
select HAVE_ARCH_KGDB
|
||||||
select HAVE_ARCH_SECCOMP
|
select HAVE_ARCH_SECCOMP
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
# define get_fs() (current_thread_info()->addr_limit)
|
# define get_fs() (current_thread_info()->addr_limit)
|
||||||
# define set_fs(val) (current_thread_info()->addr_limit = (val))
|
# 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)
|
# 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.
|
* Copy a null terminated string from userspace.
|
||||||
*/
|
*/
|
||||||
extern int __strncpy_user(char *to, const char __user *from, int len);
|
__must_check long strncpy_from_user(char *dst, const char __user *src,
|
||||||
|
long count);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the size of a string (including the ending 0)
|
* Return the size of a string (including the ending 0)
|
||||||
*
|
*
|
||||||
* Return 0 on exception, a value greater than N if too long
|
* Return 0 on exception, a value greater than N if too long
|
||||||
*/
|
*/
|
||||||
extern int __strnlen_user(const char __user *sstr, int len);
|
__must_check long strnlen_user(const char __user *sstr, long len);
|
||||||
|
|
||||||
static inline long strnlen_user(const char __user *src, long n)
|
|
||||||
{
|
|
||||||
if (!access_ok(src, 1))
|
|
||||||
return 0;
|
|
||||||
return __strnlen_user(src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ASM_MICROBLAZE_UACCESS_H */
|
#endif /* _ASM_MICROBLAZE_UACCESS_H */
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ EXPORT_SYMBOL(_mcount);
|
|||||||
* Assembly functions that may be used (directly or indirectly) by modules
|
* Assembly functions that may be used (directly or indirectly) by modules
|
||||||
*/
|
*/
|
||||||
EXPORT_SYMBOL(__copy_tofrom_user);
|
EXPORT_SYMBOL(__copy_tofrom_user);
|
||||||
EXPORT_SYMBOL(__strncpy_user);
|
|
||||||
|
|
||||||
#ifdef CONFIG_OPT_LIB_ASM
|
#ifdef CONFIG_OPT_LIB_ASM
|
||||||
EXPORT_SYMBOL(memcpy);
|
EXPORT_SYMBOL(memcpy);
|
||||||
|
|||||||
@@ -12,96 +12,6 @@
|
|||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <asm/page.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 */
|
/* Loop unrolling for __copy_tofrom_user */
|
||||||
#define COPY(offset) \
|
#define COPY(offset) \
|
||||||
1: lwi r4 , r6, 0x0000 + offset; \
|
1: lwi r4 , r6, 0x0000 + offset; \
|
||||||
|
|||||||
Reference in New Issue
Block a user