Re: [PATCH] tracing/user_events: align uaddr on unsigned long alignment
From: Clément Léger <hidden>
Date: 2023-09-25 08:11:04
Also in:
lkml
On 22/09/2023 22:00, Beau Belgrave wrote:
On Tue, Sep 19, 2023 at 02:59:12PM +0200, Clément Léger wrote:quoted
On 14/09/2023 19:29, Steven Rostedt wrote:quoted
On Thu, 14 Sep 2023 13:17:00 -0400 Steven Rostedt [off-list ref] wrote:quoted
Now lets look at big endian layout: uaddr = 0xbeef0004 enabler = 1; memory at 0xbeef0000: 00 00 00 00 00 00 00 02 ^ addr: 0xbeef0004 (enabler is set ) bitoffset = uaddr & (sizeof(unsigned long) - 1); bitoffset = 4 bit_offset *= 8; bitoffset = 32 uaddr &= ~(sizeof(unsigned long) - 1); uaddr = 0xbeef0000 ptr = kaddr + (uaddr & ~PAGE_MASK); clear_bit(1 + 32, ptr); memory at 0xbeef0000: 00 00 00 00 00 00 00 02 ^ bit 33 of 0xbeef0000 I don't think that's what you expected!I believe the above can be fixed with: bit_offset = uaddr & (sizeof(unsigned long) - 1); if (bit_offset) { #ifdef CONFIG_CPU_BIG_ENDIAN bit_offest = 0; #else bit_offset *= BITS_PER_BYTE; #endif uaddr &= ~(sizeof(unsigned long) - 1); } -- SteveActually, after looking more in depth at that, it seems like there are actually 2 problems that can happen. First one is atomic access misalignment due to enable_size == 4 and uaddr not being aligned on a (long) boundary on 64 bits architecture. This can generate misaligned exceptions on various architectures. This can be fixed in a more general way according to Masami snippet. Second one that I can see is on 64 bits, big endian architectures with enable_size == 4. In that case, the bit provided by the userspace won't be correctly set since this code kind of assume that the atomic are done on 32bits value. Since the kernel assume long sized atomic operation, on big endian 64 bits architecture, the updated bit will actually be in the next 32 bits word. Can someone confirm my understanding ?Actually, I take back some of what I said [1]. If a 32-bit on a 64-bit kernel comes in on BE, and is aligned, we do need to offset the bits as well (just verified on my ppc64 BE VM).
Yes, that is what I meant in my previous comment. I'll resend my series which handles that properly (and which includes generic set_bit_unaligned()). Thanks, Clément
You should be able to use that patch as a base though and add a flag to struct user_event_enabler when this case occurs. Then in the align_addr_bit() adjust the bits as well upon aligned cases. Thanks, -Beau 1. https://lore.kernel.org/linux-trace-kernel/20230922192231.GA1828-beaub@linux.microsoft.com/ (local)quoted
Clément