"David Laight" [off-list ref] writes:
quoted
Not exactly. It is asked to to perform 2 32-bit loads which are combined
into a single ldm (load multiple) which cannot handle unaligned
accesses. Here's a simple example that does the same thing:
void test(char * buf)
{
printf("%d, %d\n", *((unsigned int *)&buf[0]), *((unsigned int *)&buf[4]));
}
Have you actually looked at what an ARM processor traditionally did
with misaligned memory reads?
While useful, it probably wasn't what was intended.
Actually, and IIRC, some very recent ARM cpus will do the 'expected'
thing for single-word loads from misaligned addesses.
What various CPUs do with unaligned accesses is not the issue here. The
casts in the code above act as a promise to the compiler that the
address is in fact properly align for the pointer type.
However they almost certainly won't for ldm/stm.
The 'ldm' optimisation for adjacent memory loads is also dubious.
There is nothing whatsoever dubious about the compiler using the most
efficient instruction sequence to accomplish what the code asks for.
On at least some ARMs it is very slow (might only be strongarms).
The compiler will pick instructions suitable for the CPU you specify.
quoted
So I guess the only ABI legal unaligned access is in a packed struct.
Correct. And you mustn't try casting the address, the compiler is
allowed to remember where it came from.
(This causes a lot of grief...)
It is only a problem when you try to outsmart the compiler.
If you are targeting the ARM cpu that can do misaligned transfers,
then gcc should generate single instructions for misaligned structure
members, and never do the 'ldm' optimisations.
That is exactly how gcc works.
But, the IP header is expected to be aligned.
Everything tells the compiler the struct is perfectly aligned. When the
buggy driver passes a misaligned pointer, bad things happen.
--
Måns Rullgård
mans@mansr.com
On Thursday 11 October 2012, Måns Rullgård wrote:
quoted
But, the IP header is expected to be aligned.
Everything tells the compiler the struct is perfectly aligned. When the
buggy driver passes a misaligned pointer, bad things happen.
Would it be appropriate to add a WARN_ON_ONCE() in the alignment fault path
then? If all alignment faults in the kernel are caused by broken drivers,
that would at least give us some hope of finding those drivers while at the
same time not causing much overhead in the case where we need to do the
fixup in the meantime.
Arnd
On Fri, Oct 12, 2012 at 08:11:42AM +0000, Arnd Bergmann wrote:
On Thursday 11 October 2012, Måns Rullgård wrote:
quoted
quoted
But, the IP header is expected to be aligned.
Everything tells the compiler the struct is perfectly aligned. When the
buggy driver passes a misaligned pointer, bad things happen.
Would it be appropriate to add a WARN_ON_ONCE() in the alignment fault path
then? If all alignment faults in the kernel are caused by broken drivers,
that would at least give us some hope of finding those drivers while at the
same time not causing much overhead in the case where we need to do the
fixup in the meantime.
No. It is my understanding that various IP option processing can also
cause the alignment fault handler to be invoked, even when the packet is
properly aligned, and then there's jffs2/mtd which also relies upon
alignment faults being fixed up.
On Fri, 2012-10-12 at 10:03 +0100, Russell King - ARM Linux wrote:
No. It is my understanding that various IP option processing can also
cause the alignment fault handler to be invoked, even when the packet is
properly aligned, and then there's jffs2/mtd which also relies upon
alignment faults being fixed up.
Oh well.
We normally make sure we dont have alignment faults on arches that dont
have CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS (or a non null NET_IP_ALIGN)
So if you find an offender, please report a bug, because I can guarantee
you we will _fix_ it.
One example of a fix was the following subtle one.
commit 117632e64d2a5f464e491fe221d7169a3814a77b
tcp: take care of misalignments
We discovered that TCP stack could retransmit misaligned skbs if a
malicious peer acknowledged sub MSS frame. This currently can happen
only if output interface is non SG enabled : If SG is enabled, tcp
builds headless skbs (all payload is included in fragments), so the tcp
trimming process only removes parts of skb fragments, header stay
aligned.
Some arches cant handle misalignments, so force a head reallocation and
shrink headroom to MAX_TCP_HEADER.
Dont care about misaligments on x86 and PPC (or other arches setting
NET_IP_ALIGN to 0)
This patch introduces __pskb_copy() which can specify the headroom of
new head, and pskb_copy() becomes a wrapper on top of __pskb_copy()
On Fri, Oct 12, 2012 at 12:04:23PM +0200, Eric Dumazet wrote:
On Fri, 2012-10-12 at 10:03 +0100, Russell King - ARM Linux wrote:
quoted
No. It is my understanding that various IP option processing can also
cause the alignment fault handler to be invoked, even when the packet is
properly aligned, and then there's jffs2/mtd which also relies upon
alignment faults being fixed up.
Oh well.
We normally make sure we dont have alignment faults on arches that dont
have CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS (or a non null NET_IP_ALIGN)
So if you find an offender, please report a bug, because I can guarantee
you we will _fix_ it.
I think one change I will make to the ARM alignment fixup is to get it
to record the last PC where a misaligned kernel fault occurred, and
report it via our statistics procfs file. That should allow us to
track down where some of these occur.
They aren't anywhere near regular though - looking at the statistics, my
firewall seems to do an average of around 2-3 a day, and a web server
around 7-8 a day.