Skip to contentSkip to conversation

kernel virtual memory access (from app) does not generate segfault

DISCUSSION Sasha Sirotkin 7 participants 30 messages Apr 20, 2010 – Jun 8, 2010 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

More specifically, writing from usermode application to a kernel virtual memory address on ARM does result in segmentation fault, however calling a function in this memory region for some reason does not.

For instance, this code generates a segfault allright

int * aa;
aa = 0xc0000000;
*aa=42;

However this code does not, instead the process simply hangs (and can be killed)

void (*func)(void);
func = 0xc0000000;
func();

I stumbled across this by accident. Just curious to understand why it happens. Isn't it a bug ?

P.S. My kernel is 2.6.32.7 and the CPU is ARM926EJ-S rev 5 (v5l)

#1 lore raw
Quoted 10 lines · Sasha Sirotkin

More specifically, writing from usermode application to a kernel virtual memory address on ARM does result in segmentation fault, however calling a function in this memory region for some reason does not.

For instance, this code generates a segfault allright

int * aa;
aa = 0xc0000000;
*aa=42;

Quoted 6 lines

However this code does not, instead the process simply hangs (and can be killed)

void (*func)(void);
func = 0xc0000000;
func();

Your first example writes to an area, your second is execution. IIRC, this version of the ARM architecture equates read and execute permission and so you may actually have permission to read this area and thus execute code in it.

Quoted 2 lines

I stumbled across this by accident. Just curious to understand why it happens. Isn't it a bug ?

Don't think so, other than you might not want that area to be readable by user space?

Signature · 4 lines
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.
#2 lore raw
Quoted 10 lines

-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm-kernel-bounces at lists.infradead.org] On Behalf Of Ben Dooks
Sent: 20 April 2010 10:35
To: Sasha Sirotkin
Cc: linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not

[..]

Quoted 20 lines
Quoted 7 lines

For instance, this code generates a segfault allright

int * aa;
aa = 0xc0000000;
*aa=42;

However this code does not, instead the process simply

hangs (and can

Quoted 6 lines

be
killed)

void (*func)(void);
func = 0xc0000000;
func();

Your first example writes to an area, your second is execution. IIRC, this version of the ARM architecture equates read and execute permission and so you may actually have permission to read this area and thus execute code in it.

Quoted 6 lines
Quoted 1 line

I stumbled across this by accident. Just curious to

understand why it

Quoted 1 line

happens. Isn't it a bug ?

Don't think so, other than you might not want that area to be readable by user space?

I tried reading that address (albeit on an old 2.6.28 kernel), and I get a segfault.

Trying to execute in kernel space is the only thing that appears to hang. Attaching to the process in gdb, I observed that pc is always 0xc0000000 when the process is stopped.

top accounts most of the CPU time as being consumed in the kernel.

I think what is going on here is that the kernel is catching the expected prefetch abort, but the handler fails to send SIGSEGV to the user process --- the process is resumed with the same pc and we end up in an endless spin.

This only appears to apply to certain address ranges: substituting some other random unmapped address for 0xc0000000 (0x48000000 worked for me), we get the expected segfault.

Does the prefetch abort handler assume that lr >= 0xc0000000 implies the fault came from inside the kernel? Should it?

arch/arm/mm/fault.c has:

/*
...
* If the address is in kernel space (>= TASK_SIZE), then we are
* probably faulting in the vmalloc() area.
...
*/
static int __kprobes
do_translation_fault(unsigned long addr, unsigned int fsr,
struct pt_regs *regs)
{
...
if (addr < TASK_SIZE)
return do_page_fault(addr, fsr, regs);

So the common case for userspace prefetch aborts is do_page_fault()

This suggests that the weirdness is caused by something in the remainder of do_translation_fault(), or something it calls.

The comment preceding do_translation_fault() suggests a possible unsafe assumption which could lead to a security hole... but it really depends on what the handler code is trying to do. Unfortunately, my understanding has broken down by this point.

Is someone else able to comment on how this code responds to a user fault >= TASK_SIZE?

Cheers
---Dave

#3 lore raw
Quoted 83 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm-kernel-bounces at lists.infradead.org] On Behalf Of Ben Dooks
Sent: 20 April 2010 10:35
To: Sasha Sirotkin
Cc: linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not

[..]

Quoted 20 lines
Quoted 7 lines

For instance, this code generates a segfault allright

int * aa;
aa = 0xc0000000;
*aa=42;

However this code does not, instead the process simply

hangs (and can

Quoted 6 lines

be
killed)

void (*func)(void);
func = 0xc0000000;
func();

Your first example writes to an area, your second is execution. IIRC, this version of the ARM architecture equates read and execute permission and so you may actually have permission to read this area and thus execute code in it.

Quoted 6 lines
Quoted 1 line

I stumbled across this by accident. Just curious to

understand why it

Quoted 1 line

happens. Isn't it a bug ?

Don't think so, other than you might not want that area to be readable by user space?

I tried reading that address (albeit on an old 2.6.28 kernel), and I get a segfault.

Trying to execute in kernel space is the only thing that appears to hang. Attaching to the process in gdb, I observed that pc is always 0xc0000000 when the process is stopped.

top accounts most of the CPU time as being consumed in the kernel.

I think what is going on here is that the kernel is catching the expected prefetch abort, but the handler fails to send SIGSEGV to the user process --- the process is resumed with the same pc and we end up in an endless spin.

This only appears to apply to certain address ranges: substituting some other random unmapped address for 0xc0000000 (0x48000000 worked for me), we get the expected segfault.

Does the prefetch abort handler assume that lr >= 0xc0000000 implies the fault came from inside the kernel? Should it?

arch/arm/mm/fault.c has:

/*
...
* If the address is in kernel space (>= TASK_SIZE), then we are
* probably faulting in the vmalloc() area.
...
*/
static int __kprobes
do_translation_fault(unsigned long addr, unsigned int fsr,
struct pt_regs *regs)
{
...
if (addr < TASK_SIZE)
return do_page_fault(addr, fsr, regs);

So the common case for userspace prefetch aborts is do_page_fault()

This suggests that the weirdness is caused by something in the remainder of do_translation_fault(), or something it calls.

Quoted 8 lines

The comment preceding do_translation_fault() suggests a possible unsafe assumption which could lead to a security hole... but it really depends on what the handler code is trying to do. Unfortunately, my understanding has broken down by this point.

Is someone else able to comment on how this code responds to a user fault >= TASK_SIZE?

I think something like this is needed:

arch/arm/mm/fault.c +3 -0
index 9d40c34..cd4d15c 100644
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs) && addr >= TASK_SIZE)
+		goto bad_area;
+
 	index = pgd_index(addr);
 
 	/*

Cheers,
Anfei.

Quoted 10 lines

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

#4 lore raw
Quoted 99 lines · anfei
Quoted 83 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm-kernel-bounces at lists.infradead.org] On Behalf Of Ben Dooks
Sent: 20 April 2010 10:35
To: Sasha Sirotkin
Cc: linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not

[..]

Quoted 20 lines
Quoted 7 lines

For instance, this code generates a segfault allright

int * aa;
aa = 0xc0000000;
*aa=42;

However this code does not, instead the process simply

hangs (and can

Quoted 6 lines

be
killed)

void (*func)(void);
func = 0xc0000000;
func();

Your first example writes to an area, your second is execution. IIRC, this version of the ARM architecture equates read and execute permission and so you may actually have permission to read this area and thus execute code in it.

Quoted 6 lines
Quoted 1 line

I stumbled across this by accident. Just curious to

understand why it

Quoted 1 line

happens. Isn't it a bug ?

Don't think so, other than you might not want that area to be readable by user space?

I tried reading that address (albeit on an old 2.6.28 kernel), and I get a segfault.

Trying to execute in kernel space is the only thing that appears to hang. Attaching to the process in gdb, I observed that pc is always 0xc0000000 when the process is stopped.

top accounts most of the CPU time as being consumed in the kernel.

I think what is going on here is that the kernel is catching the expected prefetch abort, but the handler fails to send SIGSEGV to the user process --- the process is resumed with the same pc and we end up in an endless spin.

This only appears to apply to certain address ranges: substituting some other random unmapped address for 0xc0000000 (0x48000000 worked for me), we get the expected segfault.

Does the prefetch abort handler assume that lr >= 0xc0000000 implies the fault came from inside the kernel? Should it?

arch/arm/mm/fault.c has:

/*
...
* If the address is in kernel space (>= TASK_SIZE), then we are
* probably faulting in the vmalloc() area.
...
*/
static int __kprobes
do_translation_fault(unsigned long addr, unsigned int fsr,
struct pt_regs *regs)
{
...
if (addr < TASK_SIZE)
return do_page_fault(addr, fsr, regs);

So the common case for userspace prefetch aborts is do_page_fault()

This suggests that the weirdness is caused by something in the remainder of do_translation_fault(), or something it calls.

Quoted 8 lines

The comment preceding do_translation_fault() suggests a possible unsafe assumption which could lead to a security hole... but it really depends on what the handler code is trying to do. Unfortunately, my understanding has broken down by this point.

Is someone else able to comment on how this code responds to a user fault >= TASK_SIZE?

I think something like this is needed:

arch/arm/mm/fault.c +0 -0
index 9d40c34..cd4d15c 100644

arch/arm/mm/fault.c do_translation_fault(unsigned long addr, unsigned int fsr, · line 398

Quoted 6 lines
arch/arm/mm/fault.c +3 -0
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs) && addr >= TASK_SIZE)
+		goto bad_area;
+

technically, addr >= TASK_SIZE was guaranteed by the previous test on addr. The user_mode(regs) may well be a good idea, although I'm not sure if we get entered here if the kernel is attempting to access user-mode memory by forcing unpriveldged accesses.

probably best to get Russell's opinion.

Signature · 4 lines
Ben

Q:      What's a light-year?
A:      One-third less calories than a regular year.
#5 lore raw
Quoted 26 lines · Ben Dooks
Quoted 25 lines · anfei
Quoted 24 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm-kernel-bounces at lists.infradead.org] On Behalf Of Ben Dooks
Sent: 20 April 2010 10:35
To: Sasha Sirotkin
Cc: linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not

[..]

Quoted 11 lines
Quoted 7 lines

For instance, this code generates a segfault allright

int * aa;
aa = 0xc0000000;
*aa=42;

However this code does not, instead the process simply

hangs (and can

Quoted 3 lines

be
killed)

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 3 lines

void (*func)(void);
func = 0xc0000000;
func();

Your first example writes to an area, your second is execution. IIRC, this version of the ARM architecture equates read and execute permission and so you may actually have permission to read this area and thus execute code in it.

User programs do not have permission to read kernel addresses. Trying to do so _should_ generate a permission fault.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

I tried reading that address (albeit on an old 2.6.28 kernel), and I get a segfault.

... which is correct behaviour.

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines

Trying to execute in kernel space is the only thing that appears to hang. Attaching to the process in gdb, I observed that pc is always 0xc0000000 when the process is stopped.

top accounts most of the CPU time as being consumed in the kernel.

I think what is going on here is that the kernel is catching the expected prefetch abort, but the handler fails to send SIGSEGV to the user process --- the process is resumed with the same pc and we end up in an endless spin.

Yes, that'd make sense.

Quoted 17 lines

arch/arm/mm/fault.c do_translation_fault(unsigned long addr, unsigned int fsr, · line 398

Quoted 11 lines
arch/arm/mm/fault.c +3 -0
index 9d40c34..cd4d15c 100644
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs) && addr >= TASK_SIZE)
+		goto bad_area;
+

technically, addr >= TASK_SIZE was guaranteed by the previous test on addr. The user_mode(regs) may well be a good idea, although I'm not sure if we get entered here if the kernel is attempting to access user-mode memory by forcing unpriveldged accesses.

Quoted 1 line

probably best to get Russell's opinion.

	if (user_mode(regs))
		goto bad_area;

should be sufficient, since userspace should not be accessing anything above TASK_SIZE, except for the exception page, which will always be mapped.

Reviewed-by
#6 lore raw
Quoted 14 lines · Russell King - ARM Linux
Quoted 9 lines · Ben Dooks
Quoted 8 lines · anfei
Quoted 7 lines · Dave P. Martin
Quoted 7 lines

From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm-kernel-bounces at lists.infradead.org] On Behalf Of Ben Dooks
Your first example writes to an area, your second is execution. IIRC, this version of the ARM architecture equates read and execute permission and so you may actually have permission to read this area and thus execute code in it.

User programs do not have permission to read kernel addresses. Trying to do so _should_ generate a permission fault.

Quoted 8 lines
Quoted 1 line

probably best to get Russell's opinion.

	if (user_mode(regs))
		goto bad_area;

should be sufficient, since userspace should not be accessing anything above TASK_SIZE, except for the exception page, which will always be mapped.

Those two lines look good to me, or alternatively change

if (addr < TASK_SIZE)
to

        if (addr < TASK_SIZE || user_mode(regs))

which lead to the same SIGSEGV by a more complicated route. That will continue to work if user-accessible pages are ever mapped using the vmalloc lazy method. Currently not, and I'm sure if that's ever done it will be noticed quickly :-)

But a possible NAK: What happens when the kernel does get/put_user() on an address > TASK_SIZE with kernel-only mapping? user_mode() returns 0, so the LDRT will loop in the kernel, won't it?

-- Jamie

#7 lore raw
Quoted 15 lines · Jamie Lokier
Quoted 11 lines · Russell King - ARM Linux

User programs do not have permission to read kernel addresses. Trying to do so _should_ generate a permission fault.

Quoted 1 line

probably best to get Russell's opinion.

	if (user_mode(regs))
		goto bad_area;

should be sufficient, since userspace should not be accessing anything above TASK_SIZE, except for the exception page, which will always be mapped.

Those two lines look good to me, or alternatively change

Quoted 7 lines

if (addr < TASK_SIZE)
to

        if (addr < TASK_SIZE || user_mode(regs))

which lead to the same SIGSEGV by a more complicated route. That will continue to work if user-accessible pages are ever mapped using the vmalloc lazy method.

That'd be very disgusting if it ever happened.

Quoted 3 lines

But a possible NAK: What happens when the kernel does get/put_user() on an address > TASK_SIZE with kernel-only mapping? user_mode() returns 0, so the LDRT will loop in the kernel, won't it?

No - the first data fault will cause the pgd entry to be copied, and then the subsequent data fault will be a permission fault.

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

#8 lore raw
Quoted 5 lines · Russell King - ARM Linux
Quoted 3 lines · Jamie Lokier

But a possible NAK: What happens when the kernel does get/put_user() on an address > TASK_SIZE with kernel-only mapping? user_mode() returns 0, so the LDRT will loop in the kernel, won't it?

Quoted 7 lines

No - the first data fault will cause the pgd entry to be copied, and then the subsequent data fault will be a permission fault.

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

Subtle, but nice.

So are the ifar_info and ifsr_info tables completely redundant pre-ARMv6, or is it just ifsr_info?

-- Jamie

#9 lore raw

kernel virtual memory access (from app) does not generatesegfault

In reply to Russell King - ARM Linux
Quoted 10 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin;
linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 4 lines

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I misdiagnosed the problem?

Cheers
---Dave

#10 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 13 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin;
linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 8 lines
Quoted 4 lines

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I misdiagnosed the problem?

You said your kernel is .28, so it seems too old and this commit may fix it:
commit d25ef8b86e6a58f5476bf6e4a8da730b335f68fa
ARM: 5728/1: Proper prefetch abort handling on ARMv6 and ARMv7

Cheers,
Anfei.

Quoted 5 lines

Cheers
---Dave

#11 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 10 lines

-----Original Message-----
From: anfei [mailto:anfei.zhou at gmail.com]
Sent: 21 April 2010 13:43
To: Dave P Martin
Cc: 'Russell King - ARM Linux'; Jamie Lokier; Ben Dooks; linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 9 lines
Quoted 1 line
Quoted 1 line

The difference between instruction faults and data faults

is that we

Quoted 2 lines
Quoted 2 lines

always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since

they can't

Quoted 4 lines
Quoted 1 line

tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I

Quoted 8 lines

misdiagnosed the problem?

Quoted 1 line

You said your kernel is .28, so it seems too old and this commit may fix
it:
commit d25ef8b86e6a58f5476bf6e4a8da730b335f68fa
ARM: 5728/1: Proper prefetch abort handling on ARMv6 and ARMv7

Just to clarify, this problem was not specific to 2.6.28. I also see the same issue on the 2.6.31 Ubuntu lucid kernel.

So I guess I did misdiagnose the problem, though the affected code did look worth tweaking anyway--- the suggested fixes looked sensible to me.

I see this patch didn't hit mainline before 2.6.32; I'll suggest to the Ubuntu folks that they merge this, but I guess it's not critical for them --- I don't think they've seen any real-life instances of this problem yet.

Cheers
---Dave

#12 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 34 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: anfei [mailto:anfei.zhou at gmail.com]
Sent: 21 April 2010 13:43
To: Dave P Martin
Cc: 'Russell King - ARM Linux'; Jamie Lokier; Ben Dooks; linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 9 lines
Quoted 1 line
Quoted 1 line

The difference between instruction faults and data faults

is that we

Quoted 2 lines
Quoted 2 lines

always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since

they can't

Quoted 4 lines
Quoted 1 line

tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I

Quoted 8 lines

misdiagnosed the problem?

Quoted 1 line

You said your kernel is .28, so it seems too old and this commit may fix
it:
commit d25ef8b86e6a58f5476bf6e4a8da730b335f68fa
ARM: 5728/1: Proper prefetch abort handling on ARMv6 and ARMv7

Just to clarify, this problem was not specific to 2.6.28. I also see the same issue on the 2.6.31 Ubuntu lucid kernel.

Quoted 6 lines

So I guess I did misdiagnose the problem, though the affected code did look worth tweaking anyway--- the suggested fixes looked sensible to me.

I see this patch didn't hit mainline before 2.6.32; I'll suggest to the Ubuntu folks that they merge this, but I guess it's not critical for them --- I don't think they've seen any real-life instances of this problem yet.

The two-liner proposed earlier should fix all ARMs doing userspace execution > TASK_SIZE - the problem which started this thread. But not kernel space accidentally executing an NX page > TASK_SIZE due to some bug, which can only occur on ARMv6/v7 due to NX.

The above patch addresses ARMv6/v7 with NX mappings - and probably only those > TASK_SIZE; NX mappings < TASK_SIZE should have been caught by the PROT_EXEC check already in fault.c.

If I'm right, the NX one is more serious if you can trip a kernel bug into doing this, because it'll result in an unkillable process, stuck in kernel mode and spinning. But only if you trip a kernel bug.

So both patches look useful.

-- Jamie

#13 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 4 lines · Jamie Lokier

The two-liner proposed earlier should fix all ARMs doing userspace execution > TASK_SIZE - the problem which started this thread. But not kernel space accidentally executing an NX page > TASK_SIZE due to some bug, which can only occur on ARMv6/v7 due to NX.

Sorry James, that's wrong. ARMv6 and ARMv7 use the IFSR, which gives us the error code - and that distinguishes between a translation fault and a permission fault. An attempt to execute a NX page generates a permission fault, and therefore we end up calling do_page_fault() rather than indirecting via do_translation_fault().

#14 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 7 lines · Russell King - ARM Linux
Quoted 4 lines · Jamie Lokier

The two-liner proposed earlier should fix all ARMs doing userspace execution > TASK_SIZE - the problem which started this thread. But not kernel space accidentally executing an NX page > TASK_SIZE due to some bug, which can only occur on ARMv6/v7 due to NX.

Sorry James, that's wrong.

It's Jamie, btw. Always has been.

Quoted 5 lines

ARMv6 and ARMv7 use the IFSR, which gives us the error code - and that distinguishes between a translation fault and a permission fault. An attempt to execute a NX page generates a permission fault, and therefore we end up calling do_page_fault() rather than indirecting via do_translation_fault().

That's a fine explanation, but I'd already grokked it, thanks to your earlier hint. So what's wrong about what I said above? Rephrased as:

Kernel executes NX page > TASK_SIZE:

Without patch, loops calling do_translation_fault() which just returns because the pte is already mapped and valid. With patch, goes to do_page_fault().

-> Fixed by the IFSR patch.

User executes NX page > TASK_SIZE

-> Fixed by the two-liner or IFSR patch, it doesn't matter.
Either one directs these to do_page_fault().

Kernel executes NX page < TASK_SIZE:

    -> Already caught by PROT_EXEC + FSR_LNF_PX check in
       do_translation_fault -> do_page-fault -> access_error.

User executes NX page < TASK_SIZE:

    -> Already caught by PROT_EXEC + FSR_LNF_PX check in
       do_translation_fault -> do_page-fault -> access_error.

-- Jamie

#15 lore raw

kernel virtual memory access (from app) does not generatesegfault

In reply to anfei
Quoted 8 lines · anfei
Quoted 3 lines · Dave P. Martin

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I misdiagnosed the problem?

You said your kernel is .28, so it seems too old and this commit may fix it:
commit d25ef8b86e6a58f5476bf6e4a8da730b335f68fa
ARM: 5728/1: Proper prefetch abort handling on ARMv6 and ARMv7

Indeed, yes. However, I think the fix is still value for older CPUs.

#16 lore raw

kernel virtual memory access (from app) does not generatesegfault

In reply to Dave P. Martin
Quoted 13 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin;
linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 7 lines
Quoted 4 lines

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I misdiagnosed the problem?

If it was ARMv7, we should be reading the IFSR, which should be telling us that there's a permission fault trying to read instructions from 0xc0000000.

If changing do_translation_fault() on a recent kernel fixes your problem, something's going wrong. Any chance you could add some debugging to do_PrefetchAbort() so that when you see your test program running (eg, if (strcmp(current->comm, "progname") == 0) { ... }) you could dump out the values of ifsr and addr please?

#17 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 26 lines · Russell King - ARM Linux
Quoted 13 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin;
linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 7 lines
Quoted 4 lines

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I misdiagnosed the problem?

If it was ARMv7, we should be reading the IFSR, which should be telling us that there's a permission fault trying to read instructions from 0xc0000000.

Quoted 5 lines

If changing do_translation_fault() on a recent kernel fixes your problem, something's going wrong. Any chance you could add some debugging to do_PrefetchAbort() so that when you see your test program running (eg, if (strcmp(current->comm, "progname") == 0) { ... }) you could dump out the values of ifsr and addr please?

If I remember right, the original bug report mentioned ARM926.

Nicolas

#18 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 28 lines · Nicolas Pitre
Quoted 26 lines · Russell King - ARM Linux
Quoted 13 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin;
linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 7 lines
Quoted 4 lines

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I misdiagnosed the problem?

If it was ARMv7, we should be reading the IFSR, which should be telling us that there's a permission fault trying to read instructions from 0xc0000000.

Quoted 7 lines
Quoted 5 lines

If changing do_translation_fault() on a recent kernel fixes your problem, something's going wrong. Any chance you could add some debugging to do_PrefetchAbort() so that when you see your test program running (eg, if (strcmp(current->comm, "progname") == 0) { ... }) you could dump out the values of ifsr and addr please?

If I remember right, the original bug report mentioned ARM926.

So here we go again with confusion raining.

Someone please tell me _definitively_ _what_ is being seen on _what_ CPU, and separate the two issues into two different threads. I'm going to ignore any further comments on this issue until that's done. Life is too short to try to work this out on my own.

#19 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 35 lines · Russell King - ARM Linux
Quoted 34 lines · Nicolas Pitre
Quoted 31 lines · Russell King - ARM Linux
Quoted 13 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin;
linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 7 lines
Quoted 4 lines

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I misdiagnosed the problem?

If it was ARMv7, we should be reading the IFSR, which should be telling us that there's a permission fault trying to read instructions from 0xc0000000.

If changing do_translation_fault() on a recent kernel fixes your problem, something's going wrong. Any chance you could add some debugging to do_PrefetchAbort() so that when you see your test program running (eg, if (strcmp(current->comm, "progname") == 0) { ... }) you could dump out the values of ifsr and addr please?

Quoted 8 lines
Quoted 1 line

If I remember right, the original bug report mentioned ARM926.

So here we go again with confusion raining.

Someone please tell me _definitively_ _what_ is being seen on _what_ CPU, and separate the two issues into two different threads. I'm going to ignore any further comments on this issue until that's done. Life is too short to try to work this out on my own.

Actually, no, you're creating the confusion; this sub-thread is about the behaviour on ARMv7, as a completely separate subject from ARM926.

#20 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 40 lines · Russell King - ARM Linux
Quoted 39 lines · Russell King - ARM Linux
Quoted 28 lines · Nicolas Pitre
Quoted 26 lines · Russell King - ARM Linux
Quoted 13 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin;
linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

[...]

Quoted 7 lines
Quoted 4 lines

The difference between instruction faults and data faults is that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a permission fault since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel. Should we still hit the same bit of code in this case, or have I misdiagnosed the problem?

If it was ARMv7, we should be reading the IFSR, which should be telling us that there's a permission fault trying to read instructions from 0xc0000000.

Quoted 7 lines
Quoted 5 lines

If changing do_translation_fault() on a recent kernel fixes your problem, something's going wrong. Any chance you could add some debugging to do_PrefetchAbort() so that when you see your test program running (eg, if (strcmp(current->comm, "progname") == 0) { ... }) you could dump out the values of ifsr and addr please?

If I remember right, the original bug report mentioned ARM926.

So here we go again with confusion raining.

Quoted 7 lines
Quoted 4 lines

Someone please tell me _definitively_ _what_ is being seen on _what_ CPU, and separate the two issues into two different threads. I'm going to ignore any further comments on this issue until that's done. Life is too short to try to work this out on my own.

Actually, no, you're creating the confusion; this sub-thread is about the behaviour on ARMv7, as a completely separate subject from ARM926.

It is well possible that I missed the subject transition.

The only person who provided a test program is Sasha Sirotkin who said:

Quoted 1 line · Sasha Sirotkin

P.S. My kernel is 2.6.32.7 and the CPU is ARM926EJ-S rev 5 (v5l)

Message-id: <[email protected]>

Only later did Dave P. Martin mention having made similar observations on an ARMv7.

Nicolas

#21 lore raw

kernel virtual memory access (from app) does not generatesegfault

Hi there,

Quoted 79 lines

-----Original Message-----
From: Nicolas Pitre [mailto:nico at fluxnic.net]
Sent: 21 April 2010 23:59
To: Russell King - ARM Linux
Cc: linux-arm-kernel at lists.infradead.org; anfei; Jamie Lokier; Dave P Martin; Ben Dooks
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

Quoted 1 line · Russell King - ARM Linux

On Wed, Apr 21, 2010 at 10:44:47PM +0100, Russell King -

Quoted 4 lines · ARM Linux
Quoted 4 lines · Nicolas Pitre
Quoted 3 lines · Russell King - ARM Linux
Quoted 2 lines

On Wed, Apr 21, 2010 at 12:17:41PM +0100, Dave P.

Quoted 12 lines · Martin
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines

-----Original Message-----
From: Russell King - ARM Linux
[mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin; linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

[...]

Quoted 1 line

The difference between instruction faults and

data faults is

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a

permission fault

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel.

Should we

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

still hit the same bit of code in this case, or

have I misdiagnosed the problem?

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

If it was ARMv7, we should be reading the IFSR, which

should be

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

telling us that there's a permission fault trying to read instructions from 0xc0000000.

If changing do_translation_fault() on a recent kernel

fixes your

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

problem, something's going wrong. Any chance you

could add some

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

debugging to
do_PrefetchAbort() so that when you see your test program running (eg, if (strcmp(current->comm, "progname") ==

0) { ...

Quoted 7 lines
Quoted 7 lines
Quoted 3 lines
Quoted 1 line

}) you could dump out the values of ifsr and addr please?

If I remember right, the original bug report mentioned ARM926.

So here we go again with confusion raining.

Someone please tell me _definitively_ _what_ is being

seen on _what_

Quoted 5 lines
Quoted 3 lines

CPU, and separate the two issues into two different threads. I'm going to ignore any further comments on this issue until that's done. Life is too short to try to work this out on my own.

Actually, no, you're creating the confusion; this

sub-thread is about

Quoted 1 line

the behaviour on ARMv7, as a completely separate subject

from ARM926.

It is well possible that I missed the subject transition.

The only person who provided a test program is Sasha Sirotkin who said:

Quoted 8 lines
Quoted 1 line · Sasha Sirotkin

P.S. My kernel is 2.6.32.7 and the CPU is ARM926EJ-S rev 5 (v5l)

Message-id: <[email protected]>

Only later did Dave P. Martin mention having made similar observations on an ARMv7.

To clarify:

* I haven't tested this on 926 myself
* On armv7, I have observed the problem only on *old* kernels
(<2.6.32; which lack any of the patches under discussion)
* Using 2.6.34-rc1 (from rmk's versatile branch) on armv7, I get the
expected SEGV when userspace tries to execute >= TASK_SIZE

so...
* Sasha's problem is caused by a problem in the current kernel on
926.
* My problem relates to v7 and has already been fixed (but isn't
fixed in the Ubuntu kernels yet)

The test case was

int main(void)

{
	((void (*)(void))0xc0000000)();
	return 0;
}

Hope this makes things clearer.

Cheers
---Dave

#22 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 104 lines · Dave P. Martin

Hi there,

Quoted 79 lines

-----Original Message-----
From: Nicolas Pitre [mailto:nico at fluxnic.net]
Sent: 21 April 2010 23:59
To: Russell King - ARM Linux
Cc: linux-arm-kernel at lists.infradead.org; anfei; Jamie Lokier; Dave P Martin; Ben Dooks
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

Quoted 1 line · Russell King - ARM Linux

On Wed, Apr 21, 2010 at 10:44:47PM +0100, Russell King -

Quoted 4 lines · ARM Linux
Quoted 4 lines · Nicolas Pitre
Quoted 3 lines · Russell King - ARM Linux
Quoted 2 lines

On Wed, Apr 21, 2010 at 12:17:41PM +0100, Dave P.

Quoted 12 lines · Martin
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines

-----Original Message-----
From: Russell King - ARM Linux
[mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin; linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

[...]

Quoted 1 line

The difference between instruction faults and

data faults is

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

that we always interpret instruction faults on pre-ARMv6 CPUs as a 'translation fault' rather than a

permission fault

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel.

Should we

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

still hit the same bit of code in this case, or

have I misdiagnosed the problem?

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

If it was ARMv7, we should be reading the IFSR, which

should be

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

telling us that there's a permission fault trying to read instructions from 0xc0000000.

If changing do_translation_fault() on a recent kernel

fixes your

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

problem, something's going wrong. Any chance you

could add some

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

debugging to
do_PrefetchAbort() so that when you see your test program running (eg, if (strcmp(current->comm, "progname") ==

0) { ...

Quoted 7 lines
Quoted 7 lines
Quoted 3 lines
Quoted 1 line

}) you could dump out the values of ifsr and addr please?

If I remember right, the original bug report mentioned ARM926.

So here we go again with confusion raining.

Someone please tell me _definitively_ _what_ is being

seen on _what_

Quoted 5 lines
Quoted 3 lines

CPU, and separate the two issues into two different threads. I'm going to ignore any further comments on this issue until that's done. Life is too short to try to work this out on my own.

Actually, no, you're creating the confusion; this

sub-thread is about

Quoted 1 line

the behaviour on ARMv7, as a completely separate subject

from ARM926.

It is well possible that I missed the subject transition.

The only person who provided a test program is Sasha Sirotkin who said:

Quoted 8 lines
Quoted 1 line · Sasha Sirotkin

P.S. My kernel is 2.6.32.7 and the CPU is ARM926EJ-S rev 5 (v5l)

Message-id: <[email protected]>

Only later did Dave P. Martin mention having made similar observations on an ARMv7.

To clarify:

* I haven't tested this on 926 myself
* On armv7, I have observed the problem only on *old* kernels
(<2.6.32; which lack any of the patches under discussion)
* Using 2.6.34-rc1 (from rmk's versatile branch) on armv7, I get the
expected SEGV when userspace tries to execute >= TASK_SIZE

so...
* Sasha's problem is caused by a problem in the current kernel on
926.
* My problem relates to v7 and has already been fixed (but isn't
fixed in the Ubuntu kernels yet)

Quoted 8 lines

The test case was

int main(void)

{
	((void (*)(void))0xc0000000)();
	return 0;
}

I did a test on arm926 using QEMU with the latest kernel (just pull from git.kernel.org). Without checking user_mode, this test case will continue to trigger do_translation_fault with address 0xc0000000, so I think that two-liner patch is necessary. With it, the case will get SIGSEGV, and the system seems running well.

Regards,
Anfei.

Quoted 6 lines

Hope this makes things clearer.

Cheers
---Dave

#23 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 138 lines

-----Original Message-----
From: anfei [mailto:anfei.zhou at gmail.com]
Sent: 22 April 2010 13:29
To: Dave P Martin
Cc: 'Nicolas Pitre'; Russell King - ARM Linux; linux-arm-kernel at lists.infradead.org; Jamie Lokier; Ben Dooks
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

Quoted 7 lines · Dave P. Martin

Hi there,

Quoted 5 lines

-----Original Message-----
From: Nicolas Pitre [mailto:nico at fluxnic.net]
Sent: 21 April 2010 23:59
To: Russell King - ARM Linux
Cc: linux-arm-kernel at lists.infradead.org; anfei; Jamie

Lokier; Dave

Quoted 25 lines
Quoted 25 lines

P Martin; Ben Dooks
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

Quoted 1 line · Russell King - ARM Linux

On Wed, Apr 21, 2010 at 10:44:47PM +0100, Russell King -

Quoted 4 lines · ARM Linux
Quoted 4 lines · Nicolas Pitre
Quoted 3 lines · Russell King - ARM Linux
Quoted 2 lines

On Wed, Apr 21, 2010 at 12:17:41PM +0100, Dave P.

Quoted 12 lines · Martin
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines

-----Original Message-----
From: Russell King - ARM Linux
[mailto:linux at arm.linux.org.uk]
Sent: 20 April 2010 23:41
To: Jamie Lokier
Cc: Ben Dooks; anfei; Dave P Martin; linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not generatesegfault

Quoted 5 lines
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

[...]

Quoted 1 line

The difference between instruction faults and

data faults is

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

that we always interpret instruction faults

on pre-ARMv6

Quoted 17 lines
Quoted 17 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

CPUs as a 'translation fault' rather than a

permission fault

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

since they can't tell us what the problem was.

Note that my observations were on an armv7 kernel.

Should we

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

still hit the same bit of code in this case, or

have I misdiagnosed the problem?

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

If it was ARMv7, we should be reading the IFSR, which

should be

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

telling us that there's a permission fault trying to read instructions from 0xc0000000.

If changing do_translation_fault() on a recent kernel

fixes your

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

problem, something's going wrong. Any chance you

Quoted 8 lines
Quoted 8 lines

could add some

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

debugging to
do_PrefetchAbort() so that when you see your test program running (eg, if (strcmp(current->comm, "progname") ==

0) { ...

Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

}) you could dump out the values of ifsr and addr please?

If I remember right, the original bug report

mentioned ARM926.

Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines

So here we go again with confusion raining.

Someone please tell me _definitively_ _what_ is being

seen on _what_

Quoted 3 lines
Quoted 3 lines

CPU, and separate the two issues into two different threads. I'm going to ignore any further comments on this issue until that's done. Life is too short to try to work this

out on my own.

Quoted 20 lines
Quoted 11 lines
Quoted 2 lines

Actually, no, you're creating the confusion; this

sub-thread is about

Quoted 1 line

the behaviour on ARMv7, as a completely separate subject

from ARM926.

It is well possible that I missed the subject transition.

The only person who provided a test program is Sasha Sirotkin who said:

Quoted 8 lines
Quoted 1 line · Sasha Sirotkin

P.S. My kernel is 2.6.32.7 and the CPU is ARM926EJ-S rev 5 (v5l)

Message-id: <[email protected]>

Only later did Dave P. Martin mention having made similar observations on an ARMv7.

Quoted 6 lines

To clarify:

* I haven't tested this on 926 myself
* On armv7, I have observed the problem only on *old* kernels
(<2.6.32; which lack any of the patches under discussion)
* Using 2.6.34-rc1 (from rmk's versatile branch) on

armv7, I get the

Quoted 4 lines

expected SEGV when userspace tries to execute >= TASK_SIZE

so...
* Sasha's problem is caused by a problem in the current

kernel on

Quoted 2 lines

926.
* My problem relates to v7 and has already been fixed

(but isn't

Quoted 10 lines

fixed in the Ubuntu kernels yet)

The test case was

int main(void)

{
	((void (*)(void))0xc0000000)();
	return 0;
}

I did a test on arm926 using QEMU with the latest kernel (just pull from git.kernel.org). Without checking user_mode, this test case will continue to trigger do_translation_fault with address 0xc0000000, so I think that two-liner patch is necessary. With it, the case will get SIGSEGV, and the system seems running well.

Quoted 2 lines

Regards,
Anfei.

That matches my understanding--- it sounds like the two-liner is relevant for all pre-v6 platforms (including ARM926), so it probably makes sense to merge it.

---Dave

Reviewed-by
#24 lore raw

kernel virtual memory access (from app) does not generatesegfault

Quoted 30 lines · Dave P. Martin

From: anfei [mailto:anfei.zhou at gmail.com]

Quoted 22 lines · Dave P. Martin
Quoted 4 lines

* I haven't tested this on 926 myself
* On armv7, I have observed the problem only on *old* kernels
(<2.6.32; which lack any of the patches under discussion)
* Using 2.6.34-rc1 (from rmk's versatile branch) on

armv7, I get the

Quoted 8 lines

expected SEGV when userspace tries to execute >= TASK_SIZE

so...
* Sasha's problem is caused by a problem in the current kernel on 926.
* My problem relates to v7 and has already been fixed (but isn't
fixed in the Ubuntu kernels yet)

Quoted 8 lines

The test case was

int main(void)
{
((void (*)(void))0xc0000000)();
return 0;
}

Quoted 6 lines

I did a test on arm926 using QEMU with the latest kernel (just pull from git.kernel.org). Without checking user_mode, this test case will continue to trigger do_translation_fault with address 0xc0000000, so I think that two-liner patch is necessary. With it, the case will get SIGSEGV, and the system seems running well.

Quoted 3 lines

That matches my understanding--- it sounds like the two-liner is relevant for all pre-v6 platforms (including ARM926), so it probably makes sense to merge it.

Good. Both results are consistent with the earlier discussion about the two patches (one already committed).

There are two different bugs with the same symptom on different devices. No wonder Russell's confused by this thread.

The two-liner is the least complicated solution for pre-v6. Commit the damn thing already ;-)

-- Jamie

#25 lore raw
In reply to Russell King - ARM Linux
Quoted 74 lines · Russell King - ARM Linux
Quoted 26 lines · Ben Dooks
Quoted 25 lines · anfei
Quoted 24 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm-kernel-bounces at lists.infradead.org] On Behalf Of Ben Dooks
Sent: 20 April 2010 10:35
To: Sasha Sirotkin
Cc: linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not

[..]

Quoted 11 lines
Quoted 7 lines

For instance, this code generates a segfault allright

int * aa;
aa = 0xc0000000;
*aa=42;

However this code does not, instead the process simply

hangs (and can

Quoted 3 lines

be
killed)

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 3 lines

void (*func)(void);
func = 0xc0000000;
func();

Your first example writes to an area, your second is execution. IIRC, this version of the ARM architecture equates read and execute permission and so you may actually have permission to read this area and thus execute code in it.

User programs do not have permission to read kernel addresses. Trying to do so _should_ generate a permission fault.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

I tried reading that address (albeit on an old 2.6.28 kernel), and I get a segfault.

... which is correct behaviour.

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines

Trying to execute in kernel space is the only thing that appears to hang. Attaching to the process in gdb, I observed that pc is always 0xc0000000 when the process is stopped.

top accounts most of the CPU time as being consumed in the kernel.

I think what is going on here is that the kernel is catching the expected prefetch abort, but the handler fails to send SIGSEGV to the user process --- the process is resumed with the same pc and we end up in an endless spin.

Yes, that'd make sense.

Quoted 17 lines

arch/arm/mm/fault.c do_translation_fault(unsigned long addr, unsigned int fsr, · line 398

Quoted 11 lines
arch/arm/mm/fault.c +3 -0
index 9d40c34..cd4d15c 100644
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs) && addr >= TASK_SIZE)
+		goto bad_area;
+

technically, addr >= TASK_SIZE was guaranteed by the previous test on addr. The user_mode(regs) may well be a good idea, although I'm not sure if we get entered here if the kernel is attempting to access user-mode memory by forcing unpriveldged accesses.

Quoted 8 lines
Quoted 1 line

probably best to get Russell's opinion.

	if (user_mode(regs))
		goto bad_area;

should be sufficient, since userspace should not be accessing anything above TASK_SIZE, except for the exception page, which will always be mapped.

Patch updated, and with comment log.

===
ARM: Proper prefetch abort handling on pre-ARMv6

Instruction faults on pre-ARMv6 CPUs are interpreted as a 'translation fault', but do_translation_fault doesn't handle well if user mode trying to run instruction above TASK_SIZE, and result in the infinite retry of that instruction.

---
 arch/arm/mm/fault.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
arch/arm/mm/fault.c +3 -0
index 9d40c34..8ad75e9 100644
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs))
+		goto bad_area;
+
 	index = pgd_index(addr);
 
 	/*
Signature · 1 line
1.6.4.rc1
Reviewed-by
#26 lore raw
Quoted 18 lines · anfei

ARM: Proper prefetch abort handling on pre-ARMv6

Instruction faults on pre-ARMv6 CPUs are interpreted as a 'translation fault', but do_translation_fault doesn't handle well if user mode trying to run instruction above TASK_SIZE, and result in the infinite retry of that instruction.

---
 arch/arm/mm/fault.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
arch/arm/mm/fault.c +0 -0
index 9d40c34..8ad75e9 100644

arch/arm/mm/fault.c do_translation_fault(unsigned long addr, unsigned int fsr, · line 401

Quoted 9 lines
arch/arm/mm/fault.c +3 -0
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs))
+		goto bad_area;
+
 	index = pgd_index(addr);
 
 	/*

Looks good to me.

-- Jamie

#27 lore raw
In reply to anfei

Hi Russell,

Quoted 105 lines · anfei
Quoted 74 lines · Russell King - ARM Linux
Quoted 26 lines · Ben Dooks
Quoted 25 lines · anfei
Quoted 24 lines · Dave P. Martin
Quoted 10 lines

-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm-kernel-bounces at lists.infradead.org] On Behalf Of Ben Dooks
Sent: 20 April 2010 10:35
To: Sasha Sirotkin
Cc: linux-arm-kernel at lists.infradead.org
Subject: Re: kernel virtual memory access (from app) does not

[..]

Quoted 11 lines
Quoted 7 lines

For instance, this code generates a segfault allright

int * aa;
aa = 0xc0000000;
*aa=42;

However this code does not, instead the process simply

hangs (and can

Quoted 3 lines

be
killed)

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 3 lines

void (*func)(void);
func = 0xc0000000;
func();

Your first example writes to an area, your second is execution. IIRC, this version of the ARM architecture equates read and execute permission and so you may actually have permission to read this area and thus execute code in it.

User programs do not have permission to read kernel addresses. Trying to do so _should_ generate a permission fault.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines

I tried reading that address (albeit on an old 2.6.28 kernel), and I get a segfault.

... which is correct behaviour.

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines

Trying to execute in kernel space is the only thing that appears to hang. Attaching to the process in gdb, I observed that pc is always 0xc0000000 when the process is stopped.

top accounts most of the CPU time as being consumed in the kernel.

I think what is going on here is that the kernel is catching the expected prefetch abort, but the handler fails to send SIGSEGV to the user process --- the process is resumed with the same pc and we end up in an endless spin.

Yes, that'd make sense.

Quoted 17 lines

arch/arm/mm/fault.c do_translation_fault(unsigned long addr, unsigned int fsr, · line 398

Quoted 11 lines
arch/arm/mm/fault.c +3 -0
index 9d40c34..cd4d15c 100644
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs) && addr >= TASK_SIZE)
+		goto bad_area;
+

technically, addr >= TASK_SIZE was guaranteed by the previous test on addr. The user_mode(regs) may well be a good idea, although I'm not sure if we get entered here if the kernel is attempting to access user-mode memory by forcing unpriveldged accesses.

Quoted 8 lines
Quoted 1 line

probably best to get Russell's opinion.

	if (user_mode(regs))
		goto bad_area;

should be sufficient, since userspace should not be accessing anything above TASK_SIZE, except for the exception page, which will always be mapped.

Patch updated, and with comment log.

===
ARM: Proper prefetch abort handling on pre-ARMv6

Instruction faults on pre-ARMv6 CPUs are interpreted as a 'translation fault', but do_translation_fault doesn't handle well if user mode trying to run instruction above TASK_SIZE, and result in the infinite retry of that instruction.

---
 arch/arm/mm/fault.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
arch/arm/mm/fault.c +0 -0
index 9d40c34..8ad75e9 100644

arch/arm/mm/fault.c do_translation_fault(unsigned long addr, unsigned int fsr, · line 401

Quoted 9 lines
arch/arm/mm/fault.c +3 -0
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
+	if (user_mode(regs))
+		goto bad_area;
+
 	index = pgd_index(addr);
 
 	/*

This patch is still not into the mainline, will you plan to apply it?

Thanks,
Anfei.

Quoted 3 lines
Signature · 1 line
1.6.4.rc1
#28 lore raw
Quoted 27 lines · anfei

Hi Russell,

Quoted 24 lines · anfei

Patch updated, and with comment log.

===
ARM: Proper prefetch abort handling on pre-ARMv6

Instruction faults on pre-ARMv6 CPUs are interpreted as a 'translation fault', but do_translation_fault doesn't handle well if user mode trying to run instruction above TASK_SIZE, and result in the infinite retry of that instruction.

---
 arch/arm/mm/fault.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
arch/arm/mm/fault.c +0 -0
index 9d40c34..8ad75e9 100644
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
Quoted 8 lines

arch/arm/mm/fault.c do_translation_fault(unsigned long addr, unsigned int fsr, · line 401

Quoted 6 lines
arch/arm/mm/fault.c +3 -0
+	if (user_mode(regs))
+		goto bad_area;
+
 	index = pgd_index(addr);
 
 	/*

This patch is still not into the mainline, will you plan to apply it?

I had, but as it isn't in the patch system, it got buried and forgotten. Could you submit it to the patch system please? Just emailing it in a similar manner to that above, but with a subject of "Proper prefetch abort handling on pre-ARMv6" and an additional "KernelVersion: 2.6.whatever" line to the patch system should suffice.

#29 lore raw
Quoted 37 lines · Russell King - ARM Linux
Quoted 27 lines · anfei

Hi Russell,

Quoted 24 lines · anfei

Patch updated, and with comment log.

===
ARM: Proper prefetch abort handling on pre-ARMv6

Instruction faults on pre-ARMv6 CPUs are interpreted as a 'translation fault', but do_translation_fault doesn't handle well if user mode trying to run instruction above TASK_SIZE, and result in the infinite retry of that instruction.

---
 arch/arm/mm/fault.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
arch/arm/mm/fault.c +0 -0
index 9d40c34..8ad75e9 100644
@@ -393,6 +393,9 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	if (addr < TASK_SIZE)
 		return do_page_fault(addr, fsr, regs);
 
Quoted 8 lines

arch/arm/mm/fault.c do_translation_fault(unsigned long addr, unsigned int fsr, · line 401

Quoted 6 lines
arch/arm/mm/fault.c +3 -0
+	if (user_mode(regs))
+		goto bad_area;
+
 	index = pgd_index(addr);
 
 	/*

This patch is still not into the mainline, will you plan to apply it?

Quoted 5 lines

I had, but as it isn't in the patch system, it got buried and forgotten. Could you submit it to the patch system please? Just emailing it in a similar manner to that above, but with a subject of "Proper prefetch abort handling on pre-ARMv6" and an additional "KernelVersion: 2.6.whatever" line to the patch system should suffice.

Done, thanks!
Anfei.