* [PATCH 0/3] x86-64: vsyscall emulation cleanups
@ 2011-06-06 17:27 Andy Lutomirski
2011-06-06 17:27 ` [PATCH 1/3] x86-64: Fix outdated comments in vsyscall_64.c Andy Lutomirski
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Andy Lutomirski @ 2011-06-06 17:27 UTC (permalink / raw)
To: x86, Ingo Molnar
Cc: pageexec, Mikael Pettersson, H. Peter Anvin, linux-kernel,
Linus Torvalds, Andy Lutomirski
[cc list trimmed from the previous patches to include only people who seem
like they would care about this round of changes. My apologies if I missed
anyone.]
This series applies to the x86/vdso branch of the -tip tree.
Patch 1/3 deletes some very outdated comments in vsyscall_64.c.
Patch 2/3 simplifies the vsyscall emulation int 0xcc mechanism and removes
some ret instructions that are (as pointed out by the PaX team) possibly
dangerous.
Patch 3/3 fixes what is arguably the most serious problem of all: people
thought that CONFIG_COMPAT_VSYSCALLS controlled binary compatibility. It
changes the Kconfig short description, help text, and feature removal entry
to make it a lot more clear what's going on.
Andy Lutomirski (3):
x86-64: Fix outdated comments in vsyscall_64.c
x86-64: Clean up vsyscall emulation and remove fixed-address ret
x86-64: Clarify CONFIG_COMPAT_VSYSCALLS text
Documentation/feature-removal-schedule.txt | 11 ++-
arch/x86/Kconfig | 27 +++++----
arch/x86/include/asm/vsyscall.h | 10 +++-
arch/x86/kernel/vsyscall_64.c | 85 +++++++++-------------------
arch/x86/kernel/vsyscall_emu_64.S | 17 +-----
5 files changed, 58 insertions(+), 92 deletions(-)
--
1.7.5.2
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/3] x86-64: Fix outdated comments in vsyscall_64.c
2011-06-06 17:27 [PATCH 0/3] x86-64: vsyscall emulation cleanups Andy Lutomirski
@ 2011-06-06 17:27 ` Andy Lutomirski
2011-06-06 21:40 ` [tip:x86/vdso] " tip-bot for Andy Lutomirski
2011-06-06 17:27 ` [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret Andy Lutomirski
2011-06-06 17:27 ` [PATCH 3/3] x86-64: Clarify CONFIG_COMPAT_VSYSCALLS text Andy Lutomirski
2 siblings, 1 reply; 10+ messages in thread
From: Andy Lutomirski @ 2011-06-06 17:27 UTC (permalink / raw)
To: x86, Ingo Molnar
Cc: pageexec, Mikael Pettersson, H. Peter Anvin, linux-kernel,
Linus Torvalds, Andy Lutomirski
Signed-off-by: Andy Lutomirski <luto@mit.edu>
---
arch/x86/kernel/vsyscall_64.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 27d49b7..0b50b3c 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -11,10 +11,11 @@
* vsyscalls. One vsyscall can reserve more than 1 slot to avoid
* jumping out of line if necessary. We cannot add more with this
* mechanism because older kernels won't return -ENOSYS.
- * If we want more than four we need a vDSO.
*
- * Note: the concept clashes with user mode linux. If you use UML and
- * want per guest time just set the kernel.vsyscall64 sysctl to 0.
+ * This mechanism is deprecated in favor of the vDSO.
+ *
+ * Note: the concept clashes with user mode linux. UML users should
+ * use the vDSO.
*/
/* Disable profiling for userspace code: */
--
1.7.5.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret
2011-06-06 17:27 [PATCH 0/3] x86-64: vsyscall emulation cleanups Andy Lutomirski
2011-06-06 17:27 ` [PATCH 1/3] x86-64: Fix outdated comments in vsyscall_64.c Andy Lutomirski
@ 2011-06-06 17:27 ` Andy Lutomirski
2011-06-06 17:41 ` Ingo Molnar
2011-06-06 21:40 ` [tip:x86/vdso] " tip-bot for Andy Lutomirski
2011-06-06 17:27 ` [PATCH 3/3] x86-64: Clarify CONFIG_COMPAT_VSYSCALLS text Andy Lutomirski
2 siblings, 2 replies; 10+ messages in thread
From: Andy Lutomirski @ 2011-06-06 17:27 UTC (permalink / raw)
To: x86, Ingo Molnar
Cc: pageexec, Mikael Pettersson, H. Peter Anvin, linux-kernel,
Linus Torvalds, Andy Lutomirski
Remove the fixed-address ret in the vsyscall emulation stubs. As a
result, int 0xcc no longer works if executed from user address space
(which is OK -- nothing sensible should do that).
Removing support for int 0xcc in user address space cleans up the
code considerably.
Signed-off-by: Andy Lutomirski <luto@mit.edu>
---
arch/x86/include/asm/vsyscall.h | 10 ++++-
arch/x86/kernel/vsyscall_64.c | 78 +++++++++++--------------------------
arch/x86/kernel/vsyscall_emu_64.S | 17 +--------
3 files changed, 32 insertions(+), 73 deletions(-)
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index 293ae08..bb710cb 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -32,9 +32,15 @@ extern struct timezone sys_tz;
extern void map_vsyscall(void);
/* Emulation */
-static inline bool in_vsyscall_page(unsigned long addr)
+
+static inline bool is_vsyscall_entry(unsigned long addr)
+{
+ return (addr & ~0xC00UL) == VSYSCALL_START;
+}
+
+static inline int vsyscall_entry_nr(unsigned long addr)
{
- return (addr & ~(PAGE_SIZE - 1)) == VSYSCALL_START;
+ return (addr & 0xC00UL) >> 10;
}
#endif /* __KERNEL__ */
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 0b50b3c..04540f7 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -96,25 +96,10 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
tsk = current;
- printk("%s%s[%d] %s ip:%lx sp:%lx ax:%lx si:%lx di:%lx",
+ printk("%s%s[%d] %s ip:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
level, tsk->comm, task_pid_nr(tsk),
message,
regs->ip - 2, regs->sp, regs->ax, regs->si, regs->di);
- if (!in_vsyscall_page(regs->ip - 2))
- print_vma_addr(" in ", regs->ip - 2);
- printk("\n");
-}
-
-/* al values for each vsyscall; see vsyscall_emu_64.S for why. */
-static u8 vsyscall_nr_to_al[] = {0xcc, 0xce, 0xf0};
-
-static int al_to_vsyscall_nr(u8 al)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(vsyscall_nr_to_al); i++)
- if (vsyscall_nr_to_al[i] == al)
- return i;
- return -1;
}
#ifdef CONFIG_COMPAT_VSYSCALLS
@@ -141,17 +126,12 @@ vtime(time_t *t)
#endif /* CONFIG_COMPAT_VSYSCALLS */
-/* If CONFIG_COMPAT_VSYSCALLS=y, then this is incorrect for vsyscall_nr == 1. */
-static inline unsigned long vsyscall_intcc_addr(int vsyscall_nr)
-{
- return VSYSCALL_START + 1024*vsyscall_nr + 2;
-}
-
void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
{
static DEFINE_RATELIMIT_STATE(rs, 3600 * HZ, 3);
struct task_struct *tsk;
const char *vsyscall_name;
+ unsigned long caller;
int vsyscall_nr;
long ret;
@@ -160,39 +140,26 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
local_irq_enable();
- vsyscall_nr = al_to_vsyscall_nr(regs->ax & 0xff);
- if (vsyscall_nr < 0) {
+ /*
+ * x86-ism here: regs->ip points to the instruction after the int 0xcc,
+ * and int 0xcc is two bytes long.
+ */
+ if (!is_vsyscall_entry(regs->ip - 2)) {
warn_bad_vsyscall(KERN_WARNING, regs, "illegal int 0xcc "
"(exploit attempt?)");
goto sigsegv;
}
+ vsyscall_nr = vsyscall_entry_nr(regs->ip - 2);
- if (regs->ip - 2 != vsyscall_intcc_addr(vsyscall_nr)) {
- if (in_vsyscall_page(regs->ip - 2)) {
- /* This should not be possible. */
- warn_bad_vsyscall(KERN_WARNING, regs,
- "int 0xcc bogus magic "
- "(exploit attempt?)");
- goto sigsegv;
- } else {
- /*
- * We allow the call because tools like ThreadSpotter
- * might copy the int 0xcc instruction to user memory.
- * We make it annoying, though, to try to persuade
- * the authors to stop doing that...
- */
- warn_bad_vsyscall(KERN_WARNING, regs,
- "int 0xcc in user code "
- "(exploit attempt? legacy "
- "instrumented code?)");
- }
+ if (get_user(caller, (unsigned long __user *)regs->sp) != 0) {
+ warn_bad_vsyscall(KERN_WARNING, regs, "int 0xcc with bad stack "
+ "(exploit attempt?)");
+ goto sigsegv;
}
tsk = current;
- if (seccomp_mode(&tsk->seccomp)) {
+ if (seccomp_mode(&tsk->seccomp))
do_exit(SIGKILL);
- goto out;
- }
switch (vsyscall_nr) {
case 0:
@@ -202,12 +169,8 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
(struct timezone __user *)regs->si);
break;
+#ifndef CONFIG_COMPAT_VSYSCALLS
case 1:
-#ifdef CONFIG_COMPAT_VSYSCALLS
- warn_bad_vsyscall(KERN_WARNING, regs, "bogus time() vsyscall "
- "emulation (exploit attempt?)");
- goto sigsegv;
-#else
vsyscall_name = "time";
ret = sys_time((time_t __user *)regs->di);
break;
@@ -221,6 +184,11 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
break;
default:
+ /*
+ * If we get here, then vsyscall_nr indicates that int 0xcc
+ * happened at an address in the vsyscall page that doesn't
+ * contain int 0xcc. That can't happen.
+ */
BUG();
}
@@ -240,9 +208,6 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
regs->ax = ret;
if (__ratelimit(&rs)) {
- unsigned long caller;
- if (get_user(caller, (unsigned long __user *)regs->sp))
- caller = 0; /* no need to crash on this fault. */
printk(KERN_INFO "%s[%d] emulated legacy vsyscall %s(); "
"upgrade your code to avoid a performance hit. "
"ip:%lx sp:%lx caller:%lx",
@@ -253,7 +218,10 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
printk("\n");
}
-out:
+ /* Emulate a ret instruction. */
+ regs->ip = caller;
+ regs->sp += 8;
+
local_irq_disable();
return;
diff --git a/arch/x86/kernel/vsyscall_emu_64.S b/arch/x86/kernel/vsyscall_emu_64.S
index 2d53e26..5658d42 100644
--- a/arch/x86/kernel/vsyscall_emu_64.S
+++ b/arch/x86/kernel/vsyscall_emu_64.S
@@ -7,36 +7,21 @@
#include <linux/linkage.h>
#include <asm/irq_vectors.h>
-/*
- * These magic incantations are chosen so that they fault if entered anywhere
- * other than an instruction boundary. The movb instruction is two bytes, and
- * the int imm8 instruction is also two bytes, so the only misaligned places
- * to enter are the immediate values for the two instructions. 0xcc is int3
- * (always faults), 0xce is into (faults on x64-64, and 32-bit code can't get
- * here), and 0xf0 is lock (lock int is invalid).
- *
- * The unused parts of the page are filled with 0xcc by the linker script.
- */
+/* The unused parts of the page are filled with 0xcc by the linker script. */
.section .vsyscall_0, "a"
ENTRY(vsyscall_0)
- movb $0xcc, %al
int $VSYSCALL_EMU_VECTOR
- ret
END(vsyscall_0)
#ifndef CONFIG_COMPAT_VSYSCALLS
.section .vsyscall_1, "a"
ENTRY(vsyscall_1)
- movb $0xce, %al
int $VSYSCALL_EMU_VECTOR
- ret
END(vsyscall_1)
#endif
.section .vsyscall_2, "a"
ENTRY(vsyscall_2)
- movb $0xf0, %al
int $VSYSCALL_EMU_VECTOR
- ret
END(vsyscall_2)
--
1.7.5.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/3] x86-64: Clarify CONFIG_COMPAT_VSYSCALLS text
2011-06-06 17:27 [PATCH 0/3] x86-64: vsyscall emulation cleanups Andy Lutomirski
2011-06-06 17:27 ` [PATCH 1/3] x86-64: Fix outdated comments in vsyscall_64.c Andy Lutomirski
2011-06-06 17:27 ` [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret Andy Lutomirski
@ 2011-06-06 17:27 ` Andy Lutomirski
2011-06-06 21:41 ` [tip:x86/vdso] x86-64: Rename COMPAT_VSYSCALLS to LEGACY_VTIME and clarify documentation tip-bot for Andy Lutomirski
2 siblings, 1 reply; 10+ messages in thread
From: Andy Lutomirski @ 2011-06-06 17:27 UTC (permalink / raw)
To: x86, Ingo Molnar
Cc: pageexec, Mikael Pettersson, H. Peter Anvin, linux-kernel,
Linus Torvalds, Andy Lutomirski
Enough people are confused about whether CONFIG_COMPAT_VSYSCALLS=n
breaks binary compatibility that we should make it harder to be
confused. So make it more clear what's going on.
The new text is a slight lie in that CONFIG_COMPAT_VSYSCALLS could
make it slightly harder to exploit *kernel* bugs once the kernel
address layout is randomized, but I mentioning that in the help text
might just cause more confusion
Signed-off-by: Andy Lutomirski <luto@mit.edu>
---
Documentation/feature-removal-schedule.txt | 11 +++++++----
arch/x86/Kconfig | 27 +++++++++++++++------------
2 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 4282ab2..ef5d1e9 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -602,11 +602,14 @@ Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----------------------------
What: CONFIG_COMPAT_VSYSCALLS (x86_64)
-When: When glibc 2.14 or newer is ubitquitous. Perhaps mid-2012.
+When: When glibc 2.14 or newer is ubiquitous. Perhaps 2013.
Why: Having user-executable syscall invoking code at a fixed addresses makes
- it easier for attackers to exploit security holes.
- Turning off CONFIG_COMPAT_VSYSCALLS mostly removes the risk but will
- make the time() function slower on glibc versions 2.13 and below.
+ it easier for attackers to exploit security holes. Turning off
+ CONFIG_COMPAT_VSYSCALLS reduces the risk without breaking binary
+ compatibility but will make the time() function slower on glibc
+ versions 2.13 and below.
+
+ We may flip the default setting to N before 2013.
Who: Andy Lutomirski <luto@mit.edu>
----------------------------
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 30041d8..17d99bc 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1648,24 +1648,27 @@ config COMPAT_VDSO
config COMPAT_VSYSCALLS
def_bool y
- prompt "Fixed address legacy vsyscalls"
+ prompt "Fast legacy sys_time() vsyscall"
depends on X86_64
---help---
- Legacy user code expects to be able to issue three syscalls
- by calling a fixed addresses. If you say N, then the kernel
- traps and emulates these calls. If you say Y, then there is
- actual executable code at a fixed address to implement time()
- efficiently.
+ Glibc 2.13 and older, statically linked binaries, and a few
+ other things use a legacy ABI to implement time().
- On a system with recent enough glibc (probably 2.14 or
- newer) and no static binaries, you can say N without a
- performance penalty to improve security: having no fixed
- address userspace-executable syscall invoking code makes
- it harder for both remote and local attackers to exploit
- security holes.
+ If you say N here, the kernel will emulate that interface in
+ order to make certain types of userspace bugs more difficult
+ to exploit. This will cause some legacy software to run
+ slightly more slowly.
+
+ If you say Y here, then the kernel will provide native code to
+ allow legacy programs to run without any performance impact.
+ This could make it easier to exploit certain types of
+ userspace bugs.
If unsure, say Y.
+ NOTE: disabling this option will not break any ABI; the kernel
+ will be fully compatible with all binaries either way.
+
config CMDLINE_BOOL
bool "Built-in kernel command line"
---help---
--
1.7.5.2
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret
2011-06-06 17:27 ` [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret Andy Lutomirski
@ 2011-06-06 17:41 ` Ingo Molnar
2011-06-06 17:45 ` Andrew Lutomirski
2011-06-06 21:40 ` [tip:x86/vdso] " tip-bot for Andy Lutomirski
1 sibling, 1 reply; 10+ messages in thread
From: Ingo Molnar @ 2011-06-06 17:41 UTC (permalink / raw)
To: Andy Lutomirski
Cc: x86, pageexec, Mikael Pettersson, H. Peter Anvin, linux-kernel,
Linus Torvalds
* Andy Lutomirski <luto@MIT.EDU> wrote:
> Remove the fixed-address ret in the vsyscall emulation stubs. As a
> result, int 0xcc no longer works if executed from user address space
> (which is OK -- nothing sensible should do that).
>
> Removing support for int 0xcc in user address space cleans up the
> code considerably.
>
> Signed-off-by: Andy Lutomirski <luto@mit.edu>
> ---
> arch/x86/include/asm/vsyscall.h | 10 ++++-
> arch/x86/kernel/vsyscall_64.c | 78 +++++++++++--------------------------
> arch/x86/kernel/vsyscall_emu_64.S | 17 +--------
> 3 files changed, 32 insertions(+), 73 deletions(-)
Ok, this makes the whole series a lot more palatable!
Can i propagate the rename suggested by hpa into patch #3:
CONFIG_COMPAT_VSYSCALL => CONFIG_LEGACY_VSYSCALL
? 'legacy' is probably the best name for this and it thus won't be
confused with the 32-bit compat facilities we have.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret
2011-06-06 17:41 ` Ingo Molnar
@ 2011-06-06 17:45 ` Andrew Lutomirski
2011-06-06 17:50 ` Ingo Molnar
0 siblings, 1 reply; 10+ messages in thread
From: Andrew Lutomirski @ 2011-06-06 17:45 UTC (permalink / raw)
To: Ingo Molnar
Cc: x86, pageexec, Mikael Pettersson, H. Peter Anvin, linux-kernel,
Linus Torvalds
On Mon, Jun 6, 2011 at 1:41 PM, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Andy Lutomirski <luto@MIT.EDU> wrote:
>
>> Remove the fixed-address ret in the vsyscall emulation stubs. As a
>> result, int 0xcc no longer works if executed from user address space
>> (which is OK -- nothing sensible should do that).
>>
>> Removing support for int 0xcc in user address space cleans up the
>> code considerably.
>>
>> Signed-off-by: Andy Lutomirski <luto@mit.edu>
>> ---
>> arch/x86/include/asm/vsyscall.h | 10 ++++-
>> arch/x86/kernel/vsyscall_64.c | 78 +++++++++++--------------------------
>> arch/x86/kernel/vsyscall_emu_64.S | 17 +--------
>> 3 files changed, 32 insertions(+), 73 deletions(-)
>
> Ok, this makes the whole series a lot more palatable!
>
> Can i propagate the rename suggested by hpa into patch #3:
>
> CONFIG_COMPAT_VSYSCALL => CONFIG_LEGACY_VSYSCALL
Certainly! CONFIG_LEGACY_VTIME might be even better, but I'm fine
with any renaming you'd like to do.
--Andy
>
> ? 'legacy' is probably the best name for this and it thus won't be
> confused with the 32-bit compat facilities we have.
>
> Thanks,
>
> Ingo
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret
2011-06-06 17:45 ` Andrew Lutomirski
@ 2011-06-06 17:50 ` Ingo Molnar
0 siblings, 0 replies; 10+ messages in thread
From: Ingo Molnar @ 2011-06-06 17:50 UTC (permalink / raw)
To: Andrew Lutomirski
Cc: x86, pageexec, Mikael Pettersson, H. Peter Anvin, linux-kernel,
Linus Torvalds
* Andrew Lutomirski <luto@mit.edu> wrote:
> >> arch/x86/include/asm/vsyscall.h | 10 ++++-
> >> arch/x86/kernel/vsyscall_64.c | 78 +++++++++++--------------------------
> >> arch/x86/kernel/vsyscall_emu_64.S | 17 +--------
> >> 3 files changed, 32 insertions(+), 73 deletions(-)
> >
> > Ok, this makes the whole series a lot more palatable!
> >
> > Can i propagate the rename suggested by hpa into patch #3:
> >
> > CONFIG_COMPAT_VSYSCALL => CONFIG_LEGACY_VSYSCALL
>
> Certainly! CONFIG_LEGACY_VTIME might be even better, but I'm fine
> with any renaming you'd like to do.
Good point, i changed it to CONFIG_LEGACY_VTIME - this correctly
implies that it's only about vtime(), not about any other vsyscall.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 10+ messages in thread
* [tip:x86/vdso] x86-64: Fix outdated comments in vsyscall_64.c
2011-06-06 17:27 ` [PATCH 1/3] x86-64: Fix outdated comments in vsyscall_64.c Andy Lutomirski
@ 2011-06-06 21:40 ` tip-bot for Andy Lutomirski
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Andy Lutomirski @ 2011-06-06 21:40 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, luto, torvalds, mikpe, tglx, mingo,
luto
Commit-ID: 8d6316596441de42e3f30c8e536579f6292b46a0
Gitweb: http://git.kernel.org/tip/8d6316596441de42e3f30c8e536579f6292b46a0
Author: Andy Lutomirski <luto@MIT.EDU>
AuthorDate: Mon, 6 Jun 2011 13:27:23 -0400
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Mon, 6 Jun 2011 19:47:20 +0200
x86-64: Fix outdated comments in vsyscall_64.c
Signed-off-by: Andy Lutomirski <luto@mit.edu>
Cc: pageexec@freemail.hu
Cc: Mikael Pettersson <mikpe@it.uu.se>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/ab1699caaea6c7863fb74abc2f5718353680070c.1307380481.git.luto@mit.edu
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
arch/x86/kernel/vsyscall_64.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 27d49b7..0b50b3c 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -11,10 +11,11 @@
* vsyscalls. One vsyscall can reserve more than 1 slot to avoid
* jumping out of line if necessary. We cannot add more with this
* mechanism because older kernels won't return -ENOSYS.
- * If we want more than four we need a vDSO.
*
- * Note: the concept clashes with user mode linux. If you use UML and
- * want per guest time just set the kernel.vsyscall64 sysctl to 0.
+ * This mechanism is deprecated in favor of the vDSO.
+ *
+ * Note: the concept clashes with user mode linux. UML users should
+ * use the vDSO.
*/
/* Disable profiling for userspace code: */
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [tip:x86/vdso] x86-64: Clean up vsyscall emulation and remove fixed-address ret
2011-06-06 17:27 ` [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret Andy Lutomirski
2011-06-06 17:41 ` Ingo Molnar
@ 2011-06-06 21:40 ` tip-bot for Andy Lutomirski
1 sibling, 0 replies; 10+ messages in thread
From: tip-bot for Andy Lutomirski @ 2011-06-06 21:40 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, luto, torvalds, mikpe, tglx, mingo,
luto
Commit-ID: 7dc0452808b75615d1dc4d5160b26aaabc6a7300
Gitweb: http://git.kernel.org/tip/7dc0452808b75615d1dc4d5160b26aaabc6a7300
Author: Andy Lutomirski <luto@MIT.EDU>
AuthorDate: Mon, 6 Jun 2011 13:27:24 -0400
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Mon, 6 Jun 2011 19:47:20 +0200
x86-64: Clean up vsyscall emulation and remove fixed-address ret
Remove the fixed-address ret in the vsyscall emulation stubs.
As a result, int 0xcc no longer works if executed from user
address space (which is OK -- nothing sensible should do that).
Removing support for int 0xcc in user address space cleans up
the code considerably.
Signed-off-by: Andy Lutomirski <luto@mit.edu>
Cc: pageexec@freemail.hu
Cc: Mikael Pettersson <mikpe@it.uu.se>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/bd468a0e02befab146667fab5de57df7332d54d9.1307380481.git.luto@mit.edu
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
arch/x86/include/asm/vsyscall.h | 10 ++++-
arch/x86/kernel/vsyscall_64.c | 78 +++++++++++--------------------------
arch/x86/kernel/vsyscall_emu_64.S | 17 +--------
3 files changed, 32 insertions(+), 73 deletions(-)
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index 293ae08..bb710cb 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -32,9 +32,15 @@ extern struct timezone sys_tz;
extern void map_vsyscall(void);
/* Emulation */
-static inline bool in_vsyscall_page(unsigned long addr)
+
+static inline bool is_vsyscall_entry(unsigned long addr)
+{
+ return (addr & ~0xC00UL) == VSYSCALL_START;
+}
+
+static inline int vsyscall_entry_nr(unsigned long addr)
{
- return (addr & ~(PAGE_SIZE - 1)) == VSYSCALL_START;
+ return (addr & 0xC00UL) >> 10;
}
#endif /* __KERNEL__ */
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 0b50b3c..04540f7 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -96,25 +96,10 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
tsk = current;
- printk("%s%s[%d] %s ip:%lx sp:%lx ax:%lx si:%lx di:%lx",
+ printk("%s%s[%d] %s ip:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
level, tsk->comm, task_pid_nr(tsk),
message,
regs->ip - 2, regs->sp, regs->ax, regs->si, regs->di);
- if (!in_vsyscall_page(regs->ip - 2))
- print_vma_addr(" in ", regs->ip - 2);
- printk("\n");
-}
-
-/* al values for each vsyscall; see vsyscall_emu_64.S for why. */
-static u8 vsyscall_nr_to_al[] = {0xcc, 0xce, 0xf0};
-
-static int al_to_vsyscall_nr(u8 al)
-{
- int i;
- for (i = 0; i < ARRAY_SIZE(vsyscall_nr_to_al); i++)
- if (vsyscall_nr_to_al[i] == al)
- return i;
- return -1;
}
#ifdef CONFIG_COMPAT_VSYSCALLS
@@ -141,17 +126,12 @@ vtime(time_t *t)
#endif /* CONFIG_COMPAT_VSYSCALLS */
-/* If CONFIG_COMPAT_VSYSCALLS=y, then this is incorrect for vsyscall_nr == 1. */
-static inline unsigned long vsyscall_intcc_addr(int vsyscall_nr)
-{
- return VSYSCALL_START + 1024*vsyscall_nr + 2;
-}
-
void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
{
static DEFINE_RATELIMIT_STATE(rs, 3600 * HZ, 3);
struct task_struct *tsk;
const char *vsyscall_name;
+ unsigned long caller;
int vsyscall_nr;
long ret;
@@ -160,39 +140,26 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
local_irq_enable();
- vsyscall_nr = al_to_vsyscall_nr(regs->ax & 0xff);
- if (vsyscall_nr < 0) {
+ /*
+ * x86-ism here: regs->ip points to the instruction after the int 0xcc,
+ * and int 0xcc is two bytes long.
+ */
+ if (!is_vsyscall_entry(regs->ip - 2)) {
warn_bad_vsyscall(KERN_WARNING, regs, "illegal int 0xcc "
"(exploit attempt?)");
goto sigsegv;
}
+ vsyscall_nr = vsyscall_entry_nr(regs->ip - 2);
- if (regs->ip - 2 != vsyscall_intcc_addr(vsyscall_nr)) {
- if (in_vsyscall_page(regs->ip - 2)) {
- /* This should not be possible. */
- warn_bad_vsyscall(KERN_WARNING, regs,
- "int 0xcc bogus magic "
- "(exploit attempt?)");
- goto sigsegv;
- } else {
- /*
- * We allow the call because tools like ThreadSpotter
- * might copy the int 0xcc instruction to user memory.
- * We make it annoying, though, to try to persuade
- * the authors to stop doing that...
- */
- warn_bad_vsyscall(KERN_WARNING, regs,
- "int 0xcc in user code "
- "(exploit attempt? legacy "
- "instrumented code?)");
- }
+ if (get_user(caller, (unsigned long __user *)regs->sp) != 0) {
+ warn_bad_vsyscall(KERN_WARNING, regs, "int 0xcc with bad stack "
+ "(exploit attempt?)");
+ goto sigsegv;
}
tsk = current;
- if (seccomp_mode(&tsk->seccomp)) {
+ if (seccomp_mode(&tsk->seccomp))
do_exit(SIGKILL);
- goto out;
- }
switch (vsyscall_nr) {
case 0:
@@ -202,12 +169,8 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
(struct timezone __user *)regs->si);
break;
+#ifndef CONFIG_COMPAT_VSYSCALLS
case 1:
-#ifdef CONFIG_COMPAT_VSYSCALLS
- warn_bad_vsyscall(KERN_WARNING, regs, "bogus time() vsyscall "
- "emulation (exploit attempt?)");
- goto sigsegv;
-#else
vsyscall_name = "time";
ret = sys_time((time_t __user *)regs->di);
break;
@@ -221,6 +184,11 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
break;
default:
+ /*
+ * If we get here, then vsyscall_nr indicates that int 0xcc
+ * happened at an address in the vsyscall page that doesn't
+ * contain int 0xcc. That can't happen.
+ */
BUG();
}
@@ -240,9 +208,6 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
regs->ax = ret;
if (__ratelimit(&rs)) {
- unsigned long caller;
- if (get_user(caller, (unsigned long __user *)regs->sp))
- caller = 0; /* no need to crash on this fault. */
printk(KERN_INFO "%s[%d] emulated legacy vsyscall %s(); "
"upgrade your code to avoid a performance hit. "
"ip:%lx sp:%lx caller:%lx",
@@ -253,7 +218,10 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
printk("\n");
}
-out:
+ /* Emulate a ret instruction. */
+ regs->ip = caller;
+ regs->sp += 8;
+
local_irq_disable();
return;
diff --git a/arch/x86/kernel/vsyscall_emu_64.S b/arch/x86/kernel/vsyscall_emu_64.S
index 2d53e26..5658d42 100644
--- a/arch/x86/kernel/vsyscall_emu_64.S
+++ b/arch/x86/kernel/vsyscall_emu_64.S
@@ -7,36 +7,21 @@
#include <linux/linkage.h>
#include <asm/irq_vectors.h>
-/*
- * These magic incantations are chosen so that they fault if entered anywhere
- * other than an instruction boundary. The movb instruction is two bytes, and
- * the int imm8 instruction is also two bytes, so the only misaligned places
- * to enter are the immediate values for the two instructions. 0xcc is int3
- * (always faults), 0xce is into (faults on x64-64, and 32-bit code can't get
- * here), and 0xf0 is lock (lock int is invalid).
- *
- * The unused parts of the page are filled with 0xcc by the linker script.
- */
+/* The unused parts of the page are filled with 0xcc by the linker script. */
.section .vsyscall_0, "a"
ENTRY(vsyscall_0)
- movb $0xcc, %al
int $VSYSCALL_EMU_VECTOR
- ret
END(vsyscall_0)
#ifndef CONFIG_COMPAT_VSYSCALLS
.section .vsyscall_1, "a"
ENTRY(vsyscall_1)
- movb $0xce, %al
int $VSYSCALL_EMU_VECTOR
- ret
END(vsyscall_1)
#endif
.section .vsyscall_2, "a"
ENTRY(vsyscall_2)
- movb $0xf0, %al
int $VSYSCALL_EMU_VECTOR
- ret
END(vsyscall_2)
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [tip:x86/vdso] x86-64: Rename COMPAT_VSYSCALLS to LEGACY_VTIME and clarify documentation
2011-06-06 17:27 ` [PATCH 3/3] x86-64: Clarify CONFIG_COMPAT_VSYSCALLS text Andy Lutomirski
@ 2011-06-06 21:41 ` tip-bot for Andy Lutomirski
0 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Andy Lutomirski @ 2011-06-06 21:41 UTC (permalink / raw)
To: linux-tip-commits
Cc: linux-kernel, hpa, mingo, luto, torvalds, mikpe, tglx, mingo,
luto
Commit-ID: feba7e97df8c463331071b79fba2164ead6aa14b
Gitweb: http://git.kernel.org/tip/feba7e97df8c463331071b79fba2164ead6aa14b
Author: Andy Lutomirski <luto@MIT.EDU>
AuthorDate: Mon, 6 Jun 2011 13:27:25 -0400
Committer: Ingo Molnar <mingo@elte.hu>
CommitDate: Mon, 6 Jun 2011 19:49:31 +0200
x86-64: Rename COMPAT_VSYSCALLS to LEGACY_VTIME and clarify documentation
Rename COMPAT_VSYSCALLS to LEGACY_VTIME to make sure
it's not confused with the 32-bit compat facilities we
have on x86-64.
Also, in the discussions enough people were confused about
whether LEGACY_VTIME=n breaks binary compatibility that
we should make it harder to be confused. So make it more
clear what's going on.
[ The new text is slightly inaccurate in that LEGACY_VTIME
could make it slightly harder to exploit *kernel* bugs once the
kernel address layout is randomized, but me mentioning that in
the help text might just cause more confusion. ]
Signed-off-by: Andy Lutomirski <luto@mit.edu>
Cc: pageexec@freemail.hu
Cc: Mikael Pettersson <mikpe@it.uu.se>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/4ad5860f9c9c79ecd303f345cf9c06f8859c44d4.1307380481.git.luto@mit.edu
Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
Documentation/feature-removal-schedule.txt | 13 +++++++----
arch/x86/Kconfig | 29 +++++++++++++++------------
arch/x86/kernel/vsyscall_64.c | 6 ++--
arch/x86/kernel/vsyscall_emu_64.S | 2 +-
4 files changed, 28 insertions(+), 22 deletions(-)
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 4282ab2..7a7446b 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -601,12 +601,15 @@ Who: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
----------------------------
-What: CONFIG_COMPAT_VSYSCALLS (x86_64)
-When: When glibc 2.14 or newer is ubitquitous. Perhaps mid-2012.
+What: CONFIG_LEGACY_VTIME (x86_64)
+When: When glibc 2.14 or newer is ubiquitous. Perhaps 2013.
Why: Having user-executable syscall invoking code at a fixed addresses makes
- it easier for attackers to exploit security holes.
- Turning off CONFIG_COMPAT_VSYSCALLS mostly removes the risk but will
- make the time() function slower on glibc versions 2.13 and below.
+ it easier for attackers to exploit security holes. Turning off
+ CONFIG_LEGACY_VTIME reduces the risk without breaking binary
+ compatibility but will make the time() function slightly slower on
+ glibc versions 2.13 and below.
+
+ We may flip the default setting to N before 2013.
Who: Andy Lutomirski <luto@mit.edu>
----------------------------
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 30041d8..6746d35 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1646,26 +1646,29 @@ config COMPAT_VDSO
If unsure, say Y.
-config COMPAT_VSYSCALLS
+config LEGACY_VTIME
def_bool y
- prompt "Fixed address legacy vsyscalls"
+ prompt "Fast legacy sys_time() vsyscall"
depends on X86_64
---help---
- Legacy user code expects to be able to issue three syscalls
- by calling a fixed addresses. If you say N, then the kernel
- traps and emulates these calls. If you say Y, then there is
- actual executable code at a fixed address to implement time()
- efficiently.
+ Glibc 2.13 and older, statically linked binaries, and a few
+ other things use a legacy ABI to implement time().
- On a system with recent enough glibc (probably 2.14 or
- newer) and no static binaries, you can say N without a
- performance penalty to improve security: having no fixed
- address userspace-executable syscall invoking code makes
- it harder for both remote and local attackers to exploit
- security holes.
+ If you say N here, the kernel will emulate that interface in
+ order to make certain types of userspace bugs more difficult
+ to exploit. This will cause some legacy software to run
+ slightly more slowly.
+
+ If you say Y here, then the kernel will provide native code to
+ allow legacy programs to run without any performance impact.
+ This could make it easier to exploit certain types of
+ userspace bugs.
If unsure, say Y.
+ NOTE: disabling this option will not break any ABI; the kernel
+ will be fully compatible with all binaries either way.
+
config CMDLINE_BOOL
bool "Built-in kernel command line"
---help---
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 04540f7..f56644e 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -102,7 +102,7 @@ static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
regs->ip - 2, regs->sp, regs->ax, regs->si, regs->di);
}
-#ifdef CONFIG_COMPAT_VSYSCALLS
+#ifdef CONFIG_LEGACY_VTIME
/* This will break when the xtime seconds get inaccurate, but that is
* unlikely */
@@ -124,7 +124,7 @@ vtime(time_t *t)
return result;
}
-#endif /* CONFIG_COMPAT_VSYSCALLS */
+#endif /* CONFIG_LEGACY_VTIME */
void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
{
@@ -169,7 +169,7 @@ void dotraplinkage do_emulate_vsyscall(struct pt_regs *regs, long error_code)
(struct timezone __user *)regs->si);
break;
-#ifndef CONFIG_COMPAT_VSYSCALLS
+#ifndef CONFIG_LEGACY_VTIME
case 1:
vsyscall_name = "time";
ret = sys_time((time_t __user *)regs->di);
diff --git a/arch/x86/kernel/vsyscall_emu_64.S b/arch/x86/kernel/vsyscall_emu_64.S
index 5658d42..b192283 100644
--- a/arch/x86/kernel/vsyscall_emu_64.S
+++ b/arch/x86/kernel/vsyscall_emu_64.S
@@ -14,7 +14,7 @@ ENTRY(vsyscall_0)
int $VSYSCALL_EMU_VECTOR
END(vsyscall_0)
-#ifndef CONFIG_COMPAT_VSYSCALLS
+#ifndef CONFIG_LEGACY_VTIME
.section .vsyscall_1, "a"
ENTRY(vsyscall_1)
int $VSYSCALL_EMU_VECTOR
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-06-06 21:41 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-06 17:27 [PATCH 0/3] x86-64: vsyscall emulation cleanups Andy Lutomirski
2011-06-06 17:27 ` [PATCH 1/3] x86-64: Fix outdated comments in vsyscall_64.c Andy Lutomirski
2011-06-06 21:40 ` [tip:x86/vdso] " tip-bot for Andy Lutomirski
2011-06-06 17:27 ` [PATCH 2/3] x86-64: Clean up vsyscall emulation and remove fixed-address ret Andy Lutomirski
2011-06-06 17:41 ` Ingo Molnar
2011-06-06 17:45 ` Andrew Lutomirski
2011-06-06 17:50 ` Ingo Molnar
2011-06-06 21:40 ` [tip:x86/vdso] " tip-bot for Andy Lutomirski
2011-06-06 17:27 ` [PATCH 3/3] x86-64: Clarify CONFIG_COMPAT_VSYSCALLS text Andy Lutomirski
2011-06-06 21:41 ` [tip:x86/vdso] x86-64: Rename COMPAT_VSYSCALLS to LEGACY_VTIME and clarify documentation tip-bot for Andy Lutomirski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.