x86, smap: Add STAC and CLAC instructions to control user space access
When Supervisor Mode Access Prevention (SMAP) is enabled, access to userspace from the kernel is controlled by the AC flag. To make the performance of manipulating that flag acceptable, there are two new instructions, STAC and CLAC, to set and clear it. This patch adds those instructions, via alternative(), when the SMAP feature is enabled. It also adds X86_EFLAGS_AC unconditionally to the SYSCALL entry mask; there is simply no reason to make that one conditional. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Link: http://lkml.kernel.org/r/1348256595-29119-9-git-send-email-hpa@linux.intel.com
This commit is contained in:
@@ -42,10 +42,11 @@ do { \
|
||||
int __d0; \
|
||||
might_fault(); \
|
||||
__asm__ __volatile__( \
|
||||
ASM_STAC "\n" \
|
||||
"0: rep; stosl\n" \
|
||||
" movl %2,%0\n" \
|
||||
"1: rep; stosb\n" \
|
||||
"2:\n" \
|
||||
"2: " ASM_CLAC "\n" \
|
||||
".section .fixup,\"ax\"\n" \
|
||||
"3: lea 0(%2,%0,4),%0\n" \
|
||||
" jmp 2b\n" \
|
||||
@@ -626,10 +627,12 @@ survive:
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
stac();
|
||||
if (movsl_is_ok(to, from, n))
|
||||
__copy_user(to, from, n);
|
||||
else
|
||||
n = __copy_user_intel(to, from, n);
|
||||
clac();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_to_user_ll);
|
||||
@@ -637,10 +640,12 @@ EXPORT_SYMBOL(__copy_to_user_ll);
|
||||
unsigned long __copy_from_user_ll(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
if (movsl_is_ok(to, from, n))
|
||||
__copy_user_zeroing(to, from, n);
|
||||
else
|
||||
n = __copy_user_zeroing_intel(to, from, n);
|
||||
clac();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_from_user_ll);
|
||||
@@ -648,11 +653,13 @@ EXPORT_SYMBOL(__copy_from_user_ll);
|
||||
unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
if (movsl_is_ok(to, from, n))
|
||||
__copy_user(to, from, n);
|
||||
else
|
||||
n = __copy_user_intel((void __user *)to,
|
||||
(const void *)from, n);
|
||||
clac();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_from_user_ll_nozero);
|
||||
@@ -660,6 +667,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nozero);
|
||||
unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
#ifdef CONFIG_X86_INTEL_USERCOPY
|
||||
if (n > 64 && cpu_has_xmm2)
|
||||
n = __copy_user_zeroing_intel_nocache(to, from, n);
|
||||
@@ -668,6 +676,7 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
|
||||
#else
|
||||
__copy_user_zeroing(to, from, n);
|
||||
#endif
|
||||
clac();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_from_user_ll_nocache);
|
||||
@@ -675,6 +684,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nocache);
|
||||
unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
|
||||
unsigned long n)
|
||||
{
|
||||
stac();
|
||||
#ifdef CONFIG_X86_INTEL_USERCOPY
|
||||
if (n > 64 && cpu_has_xmm2)
|
||||
n = __copy_user_intel_nocache(to, from, n);
|
||||
@@ -683,6 +693,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
|
||||
#else
|
||||
__copy_user(to, from, n);
|
||||
#endif
|
||||
clac();
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
|
||||
|
Reference in New Issue
Block a user