From: Karl Mehltretter <kmehltretter@gmail.com>
To: Arnd Bergmann <arnd@arndb.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Ard Biesheuvel <ardb@kernel.org>,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] arm64: compat: Keep alignment address arithmetic 32-bit
Date: Wed, 19 Aug 2026 06:56:56 +0200 [thread overview]
Message-ID: <aoU2ezSYVbOw0hun@gmail.com> (raw)
In-Reply-To: <e3c463a1-81ae-4bef-b65b-fea1a4eda5bc@app.fastmail.com>
On Tue, Aug 18, 2026 at 09:31:14AM +0100, Arnd Bergmann wrote:
> On Tue, Aug 18, 2026, at 05:22, Karl Mehltretter wrote:
> > On Mon, Aug 17, 2026 at 11:15:33AM +0100, Arnd Bergmann wrote:
> <
> > The 4 GiB wraparound case is possible with a rather unusual arm64
> > kernel configuration, and correctly handling an individual word
> > crossing the boundary would require byte accesses. That seems too
> > contrived to justify the extra complexity here.
>
> I don't understand, what is special about the configuration?
> Isn't this exactly the case you were trying to address with
> the compat_ptr() hack?
>
Your first reply also made me realize my patch was too complicated
for the original bug.
I now used:
CONFIG_EXPERT=y
CONFIG_ARM64_64K_PAGES=y
CONFIG_COMPAT=y
CONFIG_KUSER_HELPERS=y
CONFIG_COMPAT_ALIGNMENT_FIXUPS=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=0
With 64K pages and KUSER_HELPERS, compat TASK_SIZE is 4 GiB. The last
64K is the kuser mapping. The test maps the first 64K at zero, so memory
exists on both sides of the wrap.
This does not work with the normal 4K-page config because the top page is
outside the compat user space. EXPERT is needed for COMPAT with 64K
pages.
On native ARM32, the kernel is mapped at the top of the address space.
Userspace cannot reach the 4 GiB wrap.
I tested three versions:
v1: with u32 addresses and compat_ptr() (this patch)
v1+: v1 plus byte reads for a word crossing 4 GiB
v2: only make nr_regs unsigned long (as you suggested)
The results on the Pi 400 were:
v1 v1+ v2
ordinary decrementing LDMDB PASS PASS PASS
hardware LDR at 0xfffffffd PASS PASS PASS
hardware LDRD at 0xfffffffc PASS PASS PASS
emulated LDRD word straddles 4 GiB SIGBUS PASS SIGBUS
emulated LDMIA word straddles 4 GiB SIGBUS PASS SIGBUS
emulated LDMDB underflow and straddle SIGBUS PASS SIGBUS
LDRD post-index writeback wrap PASS PASS PASS
QEMU gives the same results.
The hardware LDR test does not use compat_alignment.c. The Cortex-A72
runs the LDR at 0xfffffffd directly. It reads 0xfffffffd, 0xfffffffe,
0xffffffff and zero successfully.
For example, LDMDB with two registers and a base of 5 starts at:
5 - 8 modulo 2^32 = 0xfffffffd
v1 calculates this address. v2 calculates 0xfffffffffffffffd instead.
compat_ptr() fixes the start address, but not the whole access. A
get_user(u32) at 0xfffffffd still tries to read four continuous bytes up
to 0x100000000, so access_ok() rejects it.
This is why v1 also gets SIGBUS. It has the correct start address, but
still uses one get_user(u32). v1+ reads the four bytes separately and
wraps the last byte to zero.
The LDRD at 0xfffffffc wraps between its two words. But it is 4-byte
aligned and runs directly, so it does not test the alignment handler.
Any multiword access going through the handler is not 4-byte aligned. If
it crosses 4 GiB, at least one u32 access also crosses it. So v1 gets the
address calculation right, but get_user(u32) or put_user(u32) still
fails.
I am not sure who would use an unaligned multiword access wrapping
at 4 GiB and expect the compat alignment handler to fix it.
v2 still keeps the normal fixup path. Successful fixups are counted by
the perf alignment-faults event. If a fixup fails, the task gets SIGBUS
and the normal arm64 fault logging can report it.
So v2 is enough for the original decrementing LDM/STM bug. v1 does not
add a working wrap case by itself. I think the small v2 fix makes more
sense. v1+ would be the theoretically complete version for AArch32 wrap
handling...
Am I getting this right now, or am I still missing a case?
Karl
next prev parent reply other threads:[~2026-08-19 4:57 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-17 0:02 [PATCH] arm64: compat: Keep alignment address arithmetic 32-bit Karl Mehltretter
2026-08-17 9:15 ` Arnd Bergmann
2026-08-18 3:22 ` Karl Mehltretter
2026-08-18 7:31 ` Arnd Bergmann
2026-08-19 4:56 ` Karl Mehltretter [this message]
2026-08-19 11:19 ` Arnd Bergmann
2026-08-19 18:55 ` Karl Mehltretter
2026-08-19 20:27 ` Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aoU2ezSYVbOw0hun@gmail.com \
--to=kmehltretter@gmail.com \
--cc=ardb@kernel.org \
--cc=arnd@arndb.de \
--cc=catalin.marinas@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.