* PROBLEM: x86 alignment check bug
@ 2004-09-07 23:51 Zachary Amsden
2004-09-08 0:08 ` David S. Miller
2004-09-08 13:26 ` Alan Cox
0 siblings, 2 replies; 6+ messages in thread
From: Zachary Amsden @ 2004-09-07 23:51 UTC (permalink / raw)
To: linux-kernel, davej, hpa, bgerst, Riley
[-- Attachment #1: Type: text/plain, Size: 1864 bytes --]
Exception reporting for alignment check violations on x86 is broken
(unfortunately, rather badly, and rather hard to fix). Look at the trap
function which fills in the si_addr field during an unaligned memory
access, 2.6.8.1-mm4+, arch/i386/kernel/traps.c, Line 522:
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check,
BUS_ADRALN, get_cr2())
The hardware does not fill in %cr2 with the faulting address on
alignment check exceptions (at least on all processors I have tested);
this assumed behavior is also not documented in either the Intel or AMD
processor manuals, so at least in my understanding, it does not exist.
What happens instead is that the last occuring page fault address is
passed to the user via the siginfo struct. This address may be
completely random and have nothing at all to do with the alignment check
exception. If any memory debuggers use #AC and are relying on SIGBUS to
provide a correct address, they may get very confused.
I've attached a sample C program demonstrating the problem.
zach-dev:zach $ ./a.out
Read only write address = 40016000
fault address = 40016000
Unaligned write address = 40018001
fault address = 400a2b70
Clearly, this is not correct. Considering how difficult the fix is (the
kernel must disassemble the faulting instruction and use register
information to determine the faulting address), perhaps it is best to
simply remove the extra error info from the siginfo struct - the single
UNIX spec does not actually say that SIGBUS must provide and address
information. If the si_addr info is left, it should be clearly
documented that it does not work properly.
Keywords: signal,i386
Kernel version: apparently, all
Doing a historical search, apparently this was discovered before:
http://seclists.org/lists/linux-kernel/2001/May/0309.html
Zachary Amsden (zach@vmware.com)
[-- Attachment #2: foo.c --]
[-- Type: text/plain, Size: 1016 bytes --]
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/mman.h>
void *faultAddress = 0;
jmp_buf env;
void getFaultAddress(int signo, struct siginfo *info, void *data)
{
faultAddress = info->si_addr;
longjmp(env, 1);
}
int main()
{
long *l;
struct sigaction sa;
sa.sa_sigaction = getFaultAddress;
sa.sa_flags = SA_SIGINFO | SA_ONESHOT;
l = (long *)mmap(0,4096, PROT_READ, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
printf("Read only write address = %08x\n", l);
sigaction(SIGSEGV, &sa, NULL);
if (!setjmp(env))
l[0] = 1;
else
printf("fault address = %08x\n", faultAddress);
l = (long *)mmap(0,8192, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
l[0] = 2;
l[1024] = 3;
l = (long *)(((char *)l)+1);
printf("Unaligned write address = %08x\n", l);
sigaction(SIGBUS, &sa, NULL);
__asm__ __volatile__("pushfl\n\t"
"orl $0x40000,(%esp)\n\t"
"popfl");
if (!setjmp(env))
l[0] = 4;
else
printf("fault address = %08x\n", faultAddress);
}
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: PROBLEM: x86 alignment check bug
2004-09-07 23:51 PROBLEM: x86 alignment check bug Zachary Amsden
@ 2004-09-08 0:08 ` David S. Miller
2004-09-08 12:12 ` Gabriel Paubert
2004-09-08 13:26 ` Alan Cox
1 sibling, 1 reply; 6+ messages in thread
From: David S. Miller @ 2004-09-08 0:08 UTC (permalink / raw)
To: Zachary Amsden; +Cc: linux-kernel, davej, hpa, bgerst, Riley
On Tue, 07 Sep 2004 16:51:41 -0700
Zachary Amsden <zach@vmware.com> wrote:
> Clearly, this is not correct. Considering how difficult the fix is (the
> kernel must disassemble the faulting instruction and use register
> information to determine the faulting address),
While it is more difficult to disassemble x86 opcodes,
what you describe is exactly how we handle this on
sparc64. In fact we do opcode decoding for most fault
types.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PROBLEM: x86 alignment check bug
2004-09-08 0:08 ` David S. Miller
@ 2004-09-08 12:12 ` Gabriel Paubert
2004-09-08 18:26 ` David S. Miller
0 siblings, 1 reply; 6+ messages in thread
From: Gabriel Paubert @ 2004-09-08 12:12 UTC (permalink / raw)
To: David S. Miller; +Cc: Zachary Amsden, linux-kernel, davej, hpa, bgerst, Riley
On Tue, Sep 07, 2004 at 05:08:07PM -0700, David S. Miller wrote:
> On Tue, 07 Sep 2004 16:51:41 -0700
> Zachary Amsden <zach@vmware.com> wrote:
>
> > Clearly, this is not correct. Considering how difficult the fix is (the
> > kernel must disassemble the faulting instruction and use register
> > information to determine the faulting address),
>
> While it is more difficult to disassemble x86 opcodes,
> what you describe is exactly how we handle this on
> sparc64. In fact we do opcode decoding for most fault
> types.
For page faults, cr2 gives you the linear address, i.e., after
adding the base of the segment, which you can only find
by looking up the GDT and/or LDT for the correct segment.
Of course, the address decoding depends also of the size
attributes of the code segment (16 or 32 bits for i386,
64 bits for x86_64) which needs also a lookup of CS in the
segment tables, and of a possible address prefix which
affects the decoding. Of course this is fraught with race
if another thread modifies the LDT at the same time.
Then most instructions use a standard memory address
encoding, but there are a few exceptions which implicitly
use ESI and/or EDI. For the ones that use two memory
addresses (movs/cmps), you'd have to even compute both
addresses and decide which one is the unaligned one.
I somehow suspect that Sparc is somewhat simpler to decode
than i386/x86_64 ;-)
Don't bloat the kernel with decoding this mess, please.
A helper library in user space, why not?
Regards,
Gabriel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PROBLEM: x86 alignment check bug
2004-09-08 12:12 ` Gabriel Paubert
@ 2004-09-08 18:26 ` David S. Miller
0 siblings, 0 replies; 6+ messages in thread
From: David S. Miller @ 2004-09-08 18:26 UTC (permalink / raw)
To: Gabriel Paubert; +Cc: zach, linux-kernel, davej, hpa, bgerst, Riley
On Wed, 8 Sep 2004 14:12:36 +0200
Gabriel Paubert <paubert@iram.es> wrote:
> On Tue, Sep 07, 2004 at 05:08:07PM -0700, David S. Miller wrote:
I said:
> > While it is more difficult to disassemble x86 opcodes,
Then you said:
> I somehow suspect that Sparc is somewhat simpler to decode
> than i386/x86_64 ;-)
Thanks for agreeing with me! :-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PROBLEM: x86 alignment check bug
2004-09-07 23:51 PROBLEM: x86 alignment check bug Zachary Amsden
2004-09-08 0:08 ` David S. Miller
@ 2004-09-08 13:26 ` Alan Cox
1 sibling, 0 replies; 6+ messages in thread
From: Alan Cox @ 2004-09-08 13:26 UTC (permalink / raw)
To: Zachary Amsden; +Cc: Linux Kernel Mailing List, davej, hpa, bgerst, Riley
On Mer, 2004-09-08 at 00:51, Zachary Amsden wrote:
> Exception reporting for alignment check violations on x86 is broken
> (unfortunately, rather badly, and rather hard to fix). Look at the trap
> function which fills in the si_addr field during an unaligned memory
> access, 2.6.8.1-mm4+, arch/i386/kernel/traps.c, Line 522:
So it fills in a value with random data that should be zero. Ok thats
hardly "badly".
> Clearly, this is not correct. Considering how difficult the fix is (the
> kernel must disassemble the faulting instruction and use register
> information to determine the faulting address)
It would be a nice extension although it would break other OS's if it
used %cr2 for this since they use it for thread id.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PROBLEM: x86 alignment check bug
@ 2004-09-09 16:29 Petr Vandrovec
0 siblings, 0 replies; 6+ messages in thread
From: Petr Vandrovec @ 2004-09-09 16:29 UTC (permalink / raw)
To: Alan Cox; +Cc: Linux Kernel Mailing List, davej, hpa, bgerst, Riley, zach
On 8 Sep 04 at 14:26, Alan Cox wrote:
> On Mer, 2004-09-08 at 00:51, Zachary Amsden wrote:
> > Exception reporting for alignment check violations on x86 is broken
> > (unfortunately, rather badly, and rather hard to fix). Look at the trap
> > function which fills in the si_addr field during an unaligned memory
> > access, 2.6.8.1-mm4+, arch/i386/kernel/traps.c, Line 522:
>
> So it fills in a value with random data that should be zero. Ok thats
> hardly "badly".
These are not random data. It is old value of CR2, which happens to
be address of last page fault which occured on this CPU.
By artifically triggering alignment fault you can find at which virtual
address last pagefault on this CPU occured - so you can have some
additional information channel which can disclose information about
other processes running on your box. And although probably all security
related apps learned that page faults can be sensed from time taken to
answer request, and add random delays to their failure answers, this
additional channel could be used to more precisely determine where
failure occured.
Yes, likelihood that you can use it to hack passwords on your linux box
is zero, but given that currently si_addr reports garbage for alignment
faults (on all x86 processors), why not always report zero (or all F,
or any other constant value or eip) in si_addr? It has same relevance as
any other random value, and when compared with semi-random value it does
not provide an additional information about system behavior.
Best regards,
Petr Vandrovec
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2004-09-09 16:29 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-07 23:51 PROBLEM: x86 alignment check bug Zachary Amsden
2004-09-08 0:08 ` David S. Miller
2004-09-08 12:12 ` Gabriel Paubert
2004-09-08 18:26 ` David S. Miller
2004-09-08 13:26 ` Alan Cox
-- strict thread matches above, loose matches on Subject: below --
2004-09-09 16:29 Petr Vandrovec
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.