forked from Minki/linux
sh: use the new generic strnlen_user() function
This discards both the _32 and _64 versions in favour of the consolidated generic one. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
0e100e11bd
commit
cba8df4be3
@ -33,6 +33,7 @@ config SUPERH
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
|
||||
select GENERIC_STRNCPY_FROM_USER
|
||||
select GENERIC_STRNLEN_USER
|
||||
help
|
||||
The SuperH is a RISC processor targeted for use in embedded systems
|
||||
and consumer electronics; it was also used in the Sega Dreamcast
|
||||
|
@ -104,6 +104,9 @@ struct __large_struct { unsigned long buf[100]; };
|
||||
|
||||
extern long strncpy_from_user(char *dest, const char __user *src, long count);
|
||||
|
||||
extern __must_check long strlen_user(const char __user *str);
|
||||
extern __must_check long strnlen_user(const char __user *str, long n);
|
||||
|
||||
/* Generic arbitrary sized copy. */
|
||||
/* Return the number of bytes NOT copied */
|
||||
__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
|
||||
@ -165,43 +168,6 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
|
||||
return __copy_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* strnlen_user: - Get the size of a string in user space.
|
||||
* @s: The string to measure.
|
||||
* @n: The maximum valid length
|
||||
*
|
||||
* Context: User context only. This function may sleep.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
static inline long strnlen_user(const char __user *s, long n)
|
||||
{
|
||||
if (!__addr_ok(s))
|
||||
return 0;
|
||||
else
|
||||
return __strnlen_user(s, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* strlen_user: - Get the size of a string in user space.
|
||||
* @str: The string to measure.
|
||||
*
|
||||
* Context: User context only. This function may sleep.
|
||||
*
|
||||
* 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 there is a limit on the length of a valid string, you may wish to
|
||||
* consider using strnlen_user() instead.
|
||||
*/
|
||||
#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
|
||||
|
||||
/*
|
||||
* The exception table consists of pairs of addresses: the first is the
|
||||
* address of an instruction that is allowed to fault, and the second is
|
||||
|
@ -170,40 +170,4 @@ __asm__ __volatile__( \
|
||||
|
||||
extern void __put_user_unknown(void);
|
||||
|
||||
/*
|
||||
* Return the size of a string (including the ending 0 even when we have
|
||||
* exceeded the maximum string length).
|
||||
*/
|
||||
static inline long __strnlen_user(const char __user *__s, long __n)
|
||||
{
|
||||
unsigned long res;
|
||||
unsigned long __dummy;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1:\t"
|
||||
"mov.b @(%0,%3), %1\n\t"
|
||||
"cmp/eq %4, %0\n\t"
|
||||
"bt/s 2f\n\t"
|
||||
" add #1, %0\n\t"
|
||||
"tst %1, %1\n\t"
|
||||
"bf 1b\n\t"
|
||||
"2:\n"
|
||||
".section .fixup,\"ax\"\n"
|
||||
"3:\n\t"
|
||||
"mov.l 4f, %1\n\t"
|
||||
"jmp @%1\n\t"
|
||||
" mov #0, %0\n"
|
||||
".balign 4\n"
|
||||
"4: .long 2b\n"
|
||||
".previous\n"
|
||||
".section __ex_table,\"a\"\n"
|
||||
" .balign 4\n"
|
||||
" .long 1b,3b\n"
|
||||
".previous"
|
||||
: "=z" (res), "=&r" (__dummy)
|
||||
: "0" (0), "r" (__s), "r" (__n)
|
||||
: "t");
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* __ASM_SH_UACCESS_32_H */
|
||||
|
@ -84,6 +84,4 @@ extern long __put_user_asm_l(void *, long);
|
||||
extern long __put_user_asm_q(void *, long);
|
||||
extern void __put_user_unknown(void);
|
||||
|
||||
extern long __strnlen_user(const char *__s, long __n);
|
||||
|
||||
#endif /* __ASM_SH_UACCESS_64_H */
|
||||
|
53
arch/sh/include/asm/word-at-a-time.h
Normal file
53
arch/sh/include/asm/word-at-a-time.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef __ASM_SH_WORD_AT_A_TIME_H
|
||||
#define __ASM_SH_WORD_AT_A_TIME_H
|
||||
|
||||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
# include <asm-generic/word-at-a-time.h>
|
||||
#else
|
||||
/*
|
||||
* Little-endian version cribbed from x86.
|
||||
*/
|
||||
struct word_at_a_time {
|
||||
const unsigned long one_bits, high_bits;
|
||||
};
|
||||
|
||||
#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) }
|
||||
|
||||
/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
|
||||
static inline long count_masked_bytes(long mask)
|
||||
{
|
||||
/* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
|
||||
long a = (0x0ff0001+mask) >> 23;
|
||||
/* Fix the 1 for 00 case */
|
||||
return a & mask;
|
||||
}
|
||||
|
||||
/* Return nonzero if it has a zero */
|
||||
static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c)
|
||||
{
|
||||
unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits;
|
||||
*bits = mask;
|
||||
return mask;
|
||||
}
|
||||
|
||||
static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c)
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
|
||||
static inline unsigned long create_zero_mask(unsigned long bits)
|
||||
{
|
||||
bits = (bits - 1) & ~bits;
|
||||
return bits >> 7;
|
||||
}
|
||||
|
||||
/* The mask we created is directly usable as a bytemask */
|
||||
#define zero_bytemask(mask) (mask)
|
||||
|
||||
static inline unsigned long find_zero(unsigned long mask)
|
||||
{
|
||||
return count_masked_bytes(mask);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1568,46 +1568,6 @@ ___clear_user_exit:
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
/*
|
||||
* extern long __strnlen_user(const char *__s, long __n)
|
||||
*
|
||||
* Inputs:
|
||||
* (r2) source address
|
||||
* (r3) source size in bytes
|
||||
*
|
||||
* Ouputs:
|
||||
* (r2) -EFAULT (in case of faulting)
|
||||
* string length (otherwise)
|
||||
*/
|
||||
.global __strnlen_user
|
||||
__strnlen_user:
|
||||
pta ___strnlen_user_set_reply, tr0
|
||||
pta ___strnlen_user1, tr1
|
||||
or ZERO, ZERO, r5 /* r5 = counter */
|
||||
movi -(EFAULT), r6 /* r6 = reply, no real fixup */
|
||||
or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
|
||||
beq r3, ZERO, tr0
|
||||
|
||||
___strnlen_user1:
|
||||
ldx.b r2, r5, r7 /* Fault address: only in reading */
|
||||
addi r3, -1, r3 /* No real fixup */
|
||||
addi r5, 1, r5
|
||||
beq r3, ZERO, tr0
|
||||
bne r7, ZERO, tr1
|
||||
! The line below used to be active. This meant led to a junk byte lying between each pair
|
||||
! of entries in the argv & envp structures in memory. Whilst the program saw the right data
|
||||
! via the argv and envp arguments to main, it meant the 'flat' representation visible through
|
||||
! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example.
|
||||
! addi r5, 1, r5 /* Include '\0' */
|
||||
|
||||
___strnlen_user_set_reply:
|
||||
or r5, ZERO, r6 /* If done, return counter */
|
||||
|
||||
___strnlen_user_exit:
|
||||
or r6, ZERO, r2
|
||||
ptabs LINK, tr0
|
||||
blink tr0, ZERO
|
||||
|
||||
/*
|
||||
* extern long __get_user_asm_?(void *val, long addr)
|
||||
*
|
||||
@ -1942,7 +1902,6 @@ asm_uaccess_start:
|
||||
.long ___copy_user2, ___copy_user_exit
|
||||
.long ___clear_user1, ___clear_user_exit
|
||||
#endif
|
||||
.long ___strnlen_user1, ___strnlen_user_exit
|
||||
.long ___get_user_asm_b1, ___get_user_asm_b_exit
|
||||
.long ___get_user_asm_w1, ___get_user_asm_w_exit
|
||||
.long ___get_user_asm_l1, ___get_user_asm_l_exit
|
||||
|
@ -32,7 +32,6 @@ EXPORT_SYMBOL(__get_user_asm_b);
|
||||
EXPORT_SYMBOL(__get_user_asm_w);
|
||||
EXPORT_SYMBOL(__get_user_asm_l);
|
||||
EXPORT_SYMBOL(__get_user_asm_q);
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
EXPORT_SYMBOL(__clear_user);
|
||||
EXPORT_SYMBOL(copy_page);
|
||||
EXPORT_SYMBOL(__copy_user);
|
||||
|
Loading…
Reference in New Issue
Block a user