public inbox for linux-arm-kernel@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH] ARM: plug a race with the alignment trap handler
@ 2010-09-15  3:35 Nicolas Pitre
  2010-09-20 14:51 ` Russell King - ARM Linux
  0 siblings, 1 reply; 3+ messages in thread
From: Nicolas Pitre @ 2010-09-15  3:35 UTC (permalink / raw)
  To: linux-arm-kernel


When the policy for user space is to ignore misaligned accesses from user
space, the processor then performs a documented rotation on the accessed
data.  This is the result of the access being trapped, and the kernel
disabling the alignment trap before returning to user space again.

In kernel space we always want misaligned accesses to be fixed up.  This
is enforced by always re-enabling the alignment trap on every entry into
kernel space from user space.  No such re-enabling is performed when an
exception occurs while already in kernel space as the alignment trap is
always supposed to be enabled in that case.

There is however a small race window when a misaligned access in user
space is trapped and the alignment trap disabled, but the CPU didn't
return to user space just yet.  Any exception would be entered from kernel
space at that point and the kernel would then execute with the alignment
trap disabled.

Thanks to Maxime Bizon <mbizon@freebox.fr> for providing a test module
that made this issue reproducible.

Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>

diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index d073b64..724ba3b 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -885,8 +885,23 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 
 	if (ai_usermode & UM_SIGNAL)
 		force_sig(SIGBUS, current);
-	else
-		set_cr(cr_no_alignment);
+	else {
+		/*
+		 * We're about to disable the alignment trap and return to
+		 * user space.  But if an interrupt occurs before actually
+		 * reaching user space, then the IRQ vector entry code will
+		 * notice that we were still in kernel space and therefore
+		 * the alignment trap won't be re-enabled in that case as it
+		 * is presumed to be always on from kernel space.
+		 * Let's prevent that race by disabling interrupts here (they
+		 * are disabled on the way back to user space anyway in
+		 * entry-common.S) and disable the alignment trap only if
+		 * there is no work pending for this thread.
+		 */
+		raw_local_irq_disable();
+		if (!(current_thread_info()->flags & _TIF_WORK_MASK))
+			set_cr(cr_no_alignment);
+	}
 
 	return 0;
 }

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH] ARM: plug a race with the alignment trap handler
  2010-09-15  3:35 [PATCH] ARM: plug a race with the alignment trap handler Nicolas Pitre
@ 2010-09-20 14:51 ` Russell King - ARM Linux
  2010-09-20 15:33   ` Nicolas Pitre
  0 siblings, 1 reply; 3+ messages in thread
From: Russell King - ARM Linux @ 2010-09-20 14:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Sep 14, 2010 at 11:35:27PM -0400, Nicolas Pitre wrote:
> There is however a small race window when a misaligned access in user
> space is trapped and the alignment trap disabled, but the CPU didn't
> return to user space just yet.  Any exception would be entered from kernel
> space at that point and the kernel would then execute with the alignment
> trap disabled.

This isn't good enough - you can't just disable interrupts and hope
that they'll remain that way.

Consider what happens if the threads time slice has expired, and
TIF_NEED_RESCHED is set - the result will be that we call schedule()
and possibly switch to another thread with alignment faults disabled.

I keep on toying with an idea to use prctl() for alignment faults,
and whether to revamp this code to interact with that - which means
programs can on an individual basis decide how they want alignment
faults to be dealt with.

This would mean storing a per-thread copy of the control register,
which means that the entry*.S code can deal with updating the A bit.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH] ARM: plug a race with the alignment trap handler
  2010-09-20 14:51 ` Russell King - ARM Linux
@ 2010-09-20 15:33   ` Nicolas Pitre
  0 siblings, 0 replies; 3+ messages in thread
From: Nicolas Pitre @ 2010-09-20 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 20 Sep 2010, Russell King - ARM Linux wrote:

> On Tue, Sep 14, 2010 at 11:35:27PM -0400, Nicolas Pitre wrote:
> > There is however a small race window when a misaligned access in user
> > space is trapped and the alignment trap disabled, but the CPU didn't
> > return to user space just yet.  Any exception would be entered from kernel
> > space at that point and the kernel would then execute with the alignment
> > trap disabled.
> 
> This isn't good enough - you can't just disable interrupts and hope
> that they'll remain that way.
> 
> Consider what happens if the threads time slice has expired, and
> TIF_NEED_RESCHED is set - the result will be that we call schedule()
> and possibly switch to another thread with alignment faults disabled.

No. This is covered in my patch, which is essentially:

	raw_local_irq_disable();
	if (!(current_thread_info()->flags & _TIF_WORK_MASK))
		set_cr(cr_no_alignment);

So if we are going to schedule or whatever, then the alignment trap 
remains active, and the user misaligned access will trap again later.

> I keep on toying with an idea to use prctl() for alignment faults,
> and whether to revamp this code to interact with that - which means
> programs can on an individual basis decide how they want alignment
> faults to be dealt with.

Altough this looks nice, I doubt this would be useful in practice.  
Most of the universe is expecting misaligned accesses to be fixed up.  
So if the fixup has to be enabled on a per application basis that would 
make things really awkward, and a real PITA if that has to be 
accomplished in the form of source code modification.  That goes without 
saying that nothing compiled for EABI expects the non fixed up 
misaligned access behavior.

If, instead, the default is to have the fixup active by default and that 
applications that doesn't want it would have to disable it explicitly 
then I agree that this would be more useful.  However my understanding 
is that the only case where disabling the fixup is needed is for legacy 
binaries and that may prove difficult to recompile them to add this 
prctl() call.


Nicolas

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-09-20 15:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-15  3:35 [PATCH] ARM: plug a race with the alignment trap handler Nicolas Pitre
2010-09-20 14:51 ` Russell King - ARM Linux
2010-09-20 15:33   ` Nicolas Pitre

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox