2005-04-17 05:20:36 +07:00
|
|
|
/*
|
|
|
|
* User address space access functions.
|
|
|
|
*
|
|
|
|
* Copyright 1997 Andi Kleen <ak@muc.de>
|
|
|
|
* Copyright 1997 Linus Torvalds
|
|
|
|
* Copyright 2002 Andi Kleen <ak@suse.de>
|
|
|
|
*/
|
2006-06-26 18:59:44 +07:00
|
|
|
#include <linux/module.h>
|
2005-04-17 05:20:36 +07:00
|
|
|
#include <asm/uaccess.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy a null terminated string from userspace.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define __do_strncpy_from_user(dst,src,count,res) \
|
|
|
|
do { \
|
|
|
|
long __d0, __d1, __d2; \
|
2008-09-10 18:37:17 +07:00
|
|
|
might_fault(); \
|
2005-04-17 05:20:36 +07:00
|
|
|
__asm__ __volatile__( \
|
|
|
|
" testq %1,%1\n" \
|
|
|
|
" jz 2f\n" \
|
|
|
|
"0: lodsb\n" \
|
|
|
|
" stosb\n" \
|
|
|
|
" testb %%al,%%al\n" \
|
|
|
|
" jz 1f\n" \
|
|
|
|
" decq %1\n" \
|
|
|
|
" jnz 0b\n" \
|
|
|
|
"1: subq %1,%0\n" \
|
|
|
|
"2:\n" \
|
|
|
|
".section .fixup,\"ax\"\n" \
|
|
|
|
"3: movq %5,%0\n" \
|
|
|
|
" jmp 2b\n" \
|
|
|
|
".previous\n" \
|
2008-02-04 22:47:57 +07:00
|
|
|
_ASM_EXTABLE(0b,3b) \
|
x86: use early clobbers in usercopy*.c
Impact: fix rare (but currently harmless) miscompile with certain configs and gcc versions
Hugh Dickins noticed that strncpy_from_user() was miscompiled
in some circumstances with gcc 4.3.
Thanks to Hugh's excellent analysis it was easy to track down.
Hugh writes:
> Try building an x86_64 defconfig 2.6.29-rc1 kernel tree,
> except not quite defconfig, switch CONFIG_PREEMPT_NONE=y
> and CONFIG_PREEMPT_VOLUNTARY off (because it expands a
> might_fault() there, which hides the issue): using a
> gcc 4.3.2 (I've checked both openSUSE 11.1 and Fedora 10).
>
> It generates the following:
>
> 0000000000000000 <__strncpy_from_user>:
> 0: 48 89 d1 mov %rdx,%rcx
> 3: 48 85 c9 test %rcx,%rcx
> 6: 74 0e je 16 <__strncpy_from_user+0x16>
> 8: ac lods %ds:(%rsi),%al
> 9: aa stos %al,%es:(%rdi)
> a: 84 c0 test %al,%al
> c: 74 05 je 13 <__strncpy_from_user+0x13>
> e: 48 ff c9 dec %rcx
> 11: 75 f5 jne 8 <__strncpy_from_user+0x8>
> 13: 48 29 c9 sub %rcx,%rcx
> 16: 48 89 c8 mov %rcx,%rax
> 19: c3 retq
>
> Observe that "sub %rcx,%rcx; mov %rcx,%rax", whereas gcc 4.2.1
> (and many other configs) say "sub %rcx,%rdx; mov %rdx,%rax".
> Isn't it returning 0 when it ought to be returning strlen?
The asm constraints for the strncpy_from_user() result were missing an
early clobber, which tells gcc that the last output arguments
are written before all input arguments are read.
Also add more early clobbers in the rest of the file and fix 32-bit
usercopy.c in the same way.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
[ since this API is rarely used and no in-kernel user relies on a 'len'
return value (they only rely on negative return values) this miscompile
was never noticed in the field. But it's worth fixing it nevertheless. ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-01-16 21:22:11 +07:00
|
|
|
: "=&r"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \
|
2005-04-17 05:20:36 +07:00
|
|
|
"=&D" (__d2) \
|
|
|
|
: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
|
|
|
|
: "memory"); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
long
|
|
|
|
__strncpy_from_user(char *dst, const char __user *src, long count)
|
|
|
|
{
|
|
|
|
long res;
|
|
|
|
__do_strncpy_from_user(dst, src, count, res);
|
|
|
|
return res;
|
|
|
|
}
|
2006-06-26 18:59:44 +07:00
|
|
|
EXPORT_SYMBOL(__strncpy_from_user);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
long
|
|
|
|
strncpy_from_user(char *dst, const char __user *src, long count)
|
|
|
|
{
|
|
|
|
long res = -EFAULT;
|
|
|
|
if (access_ok(VERIFY_READ, src, 1))
|
2006-06-26 18:59:47 +07:00
|
|
|
return __strncpy_from_user(dst, src, count);
|
2005-04-17 05:20:36 +07:00
|
|
|
return res;
|
|
|
|
}
|
2006-06-26 18:59:44 +07:00
|
|
|
EXPORT_SYMBOL(strncpy_from_user);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Zero Userspace
|
|
|
|
*/
|
|
|
|
|
|
|
|
unsigned long __clear_user(void __user *addr, unsigned long size)
|
|
|
|
{
|
|
|
|
long __d0;
|
2008-09-10 18:37:17 +07:00
|
|
|
might_fault();
|
2005-04-17 05:20:36 +07:00
|
|
|
/* no memory constraint because it doesn't change any memory gcc knows
|
|
|
|
about */
|
|
|
|
asm volatile(
|
|
|
|
" testq %[size8],%[size8]\n"
|
|
|
|
" jz 4f\n"
|
|
|
|
"0: movq %[zero],(%[dst])\n"
|
|
|
|
" addq %[eight],%[dst]\n"
|
|
|
|
" decl %%ecx ; jnz 0b\n"
|
|
|
|
"4: movq %[size1],%%rcx\n"
|
|
|
|
" testl %%ecx,%%ecx\n"
|
|
|
|
" jz 2f\n"
|
|
|
|
"1: movb %b[zero],(%[dst])\n"
|
|
|
|
" incq %[dst]\n"
|
|
|
|
" decl %%ecx ; jnz 1b\n"
|
|
|
|
"2:\n"
|
|
|
|
".section .fixup,\"ax\"\n"
|
|
|
|
"3: lea 0(%[size1],%[size8],8),%[size8]\n"
|
|
|
|
" jmp 2b\n"
|
|
|
|
".previous\n"
|
2008-02-04 22:47:57 +07:00
|
|
|
_ASM_EXTABLE(0b,3b)
|
|
|
|
_ASM_EXTABLE(1b,2b)
|
x86: use early clobbers in usercopy*.c
Impact: fix rare (but currently harmless) miscompile with certain configs and gcc versions
Hugh Dickins noticed that strncpy_from_user() was miscompiled
in some circumstances with gcc 4.3.
Thanks to Hugh's excellent analysis it was easy to track down.
Hugh writes:
> Try building an x86_64 defconfig 2.6.29-rc1 kernel tree,
> except not quite defconfig, switch CONFIG_PREEMPT_NONE=y
> and CONFIG_PREEMPT_VOLUNTARY off (because it expands a
> might_fault() there, which hides the issue): using a
> gcc 4.3.2 (I've checked both openSUSE 11.1 and Fedora 10).
>
> It generates the following:
>
> 0000000000000000 <__strncpy_from_user>:
> 0: 48 89 d1 mov %rdx,%rcx
> 3: 48 85 c9 test %rcx,%rcx
> 6: 74 0e je 16 <__strncpy_from_user+0x16>
> 8: ac lods %ds:(%rsi),%al
> 9: aa stos %al,%es:(%rdi)
> a: 84 c0 test %al,%al
> c: 74 05 je 13 <__strncpy_from_user+0x13>
> e: 48 ff c9 dec %rcx
> 11: 75 f5 jne 8 <__strncpy_from_user+0x8>
> 13: 48 29 c9 sub %rcx,%rcx
> 16: 48 89 c8 mov %rcx,%rax
> 19: c3 retq
>
> Observe that "sub %rcx,%rcx; mov %rcx,%rax", whereas gcc 4.2.1
> (and many other configs) say "sub %rcx,%rdx; mov %rdx,%rax".
> Isn't it returning 0 when it ought to be returning strlen?
The asm constraints for the strncpy_from_user() result were missing an
early clobber, which tells gcc that the last output arguments
are written before all input arguments are read.
Also add more early clobbers in the rest of the file and fix 32-bit
usercopy.c in the same way.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
[ since this API is rarely used and no in-kernel user relies on a 'len'
return value (they only rely on negative return values) this miscompile
was never noticed in the field. But it's worth fixing it nevertheless. ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-01-16 21:22:11 +07:00
|
|
|
: [size8] "=&c"(size), [dst] "=&D" (__d0)
|
2005-04-17 05:20:36 +07:00
|
|
|
: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
|
|
|
|
[zero] "r" (0UL), [eight] "r" (8UL));
|
|
|
|
return size;
|
|
|
|
}
|
2006-06-26 18:59:44 +07:00
|
|
|
EXPORT_SYMBOL(__clear_user);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
unsigned long clear_user(void __user *to, unsigned long n)
|
|
|
|
{
|
|
|
|
if (access_ok(VERIFY_WRITE, to, n))
|
|
|
|
return __clear_user(to, n);
|
|
|
|
return n;
|
|
|
|
}
|
2006-06-26 18:59:44 +07:00
|
|
|
EXPORT_SYMBOL(clear_user);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the size of a string (including the ending 0)
|
|
|
|
*
|
|
|
|
* Return 0 on exception, a value greater than N if too long
|
|
|
|
*/
|
|
|
|
|
2006-01-12 04:46:48 +07:00
|
|
|
long __strnlen_user(const char __user *s, long n)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
|
|
|
long res = 0;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (res>n)
|
|
|
|
return n+1;
|
|
|
|
if (__get_user(c, s))
|
|
|
|
return 0;
|
|
|
|
if (!c)
|
|
|
|
return res+1;
|
|
|
|
res++;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
2006-06-26 18:59:44 +07:00
|
|
|
EXPORT_SYMBOL(__strnlen_user);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2006-01-12 04:46:48 +07:00
|
|
|
long strnlen_user(const char __user *s, long n)
|
|
|
|
{
|
x86, 64-bit: Clean up user address masking
The discussion about using "access_ok()" in get_user_pages_fast() (see
commit 7f8189068726492950bf1a2dcfd9b51314560abf: "x86: don't use
'access_ok()' as a range check in get_user_pages_fast()" for details and
end result), made us notice that x86-64 was really being very sloppy
about virtual address checking.
So be way more careful and straightforward about masking x86-64 virtual
addresses:
- All the VIRTUAL_MASK* variants now cover half of the address
space, it's not like we can use the full mask on a signed
integer, and the larger mask just invites mistakes when
applying it to either half of the 48-bit address space.
- /proc/kcore's kc_offset_to_vaddr() becomes a lot more
obvious when it transforms a file offset into a
(kernel-half) virtual address.
- Unify/simplify the 32-bit and 64-bit USER_DS definition to
be based on TASK_SIZE_MAX.
This cleanup and more careful/obvious user virtual address checking also
uncovered a buglet in the x86-64 implementation of strnlen_user(): it
would do an "access_ok()" check on the whole potential area, even if the
string itself was much shorter, and thus return an error even for valid
strings. Our sloppy checking had hidden this.
So this fixes 'strnlen_user()' to do this properly, the same way we
already handled user strings in 'strncpy_from_user()'. Namely by just
checking the first byte, and then relying on fault handling for the
rest. That always works, since we impose a guard page that cannot be
mapped at the end of the user space address space (and even if we
didn't, we'd have the address space hole).
Acked-by: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Nick Piggin <npiggin@suse.de>
Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-06-21 05:40:00 +07:00
|
|
|
if (!access_ok(VERIFY_READ, s, 1))
|
2006-01-12 04:46:48 +07:00
|
|
|
return 0;
|
|
|
|
return __strnlen_user(s, n);
|
|
|
|
}
|
2006-06-26 18:59:44 +07:00
|
|
|
EXPORT_SYMBOL(strnlen_user);
|
2006-01-12 04:46:48 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
long strlen_user(const char __user *s)
|
|
|
|
{
|
|
|
|
long res = 0;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (get_user(c, s))
|
|
|
|
return 0;
|
|
|
|
if (!c)
|
|
|
|
return res+1;
|
|
|
|
res++;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
2006-06-26 18:59:44 +07:00
|
|
|
EXPORT_SYMBOL(strlen_user);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len)
|
|
|
|
{
|
|
|
|
if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) {
|
|
|
|
return copy_user_generic((__force void *)to, (__force void *)from, len);
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
2006-06-26 18:59:44 +07:00
|
|
|
EXPORT_SYMBOL(copy_in_user);
|
|
|
|
|
2008-07-02 20:48:21 +07:00
|
|
|
/*
|
|
|
|
* Try to copy last bytes and clear the rest if needed.
|
|
|
|
* Since protection fault in copy_from/to_user is not a normal situation,
|
|
|
|
* it is not necessary to optimize tail handling.
|
|
|
|
*/
|
|
|
|
unsigned long
|
|
|
|
copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest)
|
|
|
|
{
|
|
|
|
char c;
|
|
|
|
unsigned zero_len;
|
|
|
|
|
|
|
|
for (; len; --len) {
|
|
|
|
if (__get_user_nocheck(c, from++, sizeof(char)))
|
|
|
|
break;
|
|
|
|
if (__put_user_nocheck(c, to++, sizeof(char)))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (c = 0, zero_len = len; zerorest && zero_len; --zero_len)
|
|
|
|
if (__put_user_nocheck(c, to++, sizeof(char)))
|
|
|
|
break;
|
|
|
|
return len;
|
|
|
|
}
|