From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794064834; b=dffK2qsGwPtWjxiqNvzy+EBZjC+BCn4k6E7Dwh3jkRqn1sVP7zH+VdS4WcTS4WtikmQu +40TCHfWf2ykBG/D9TZEgwwmvdMmL2XrwVZUUhgHwOf9cMS3GV5ge5zxfE6PFKxSpchUE K6OYMJuNDzjmZgv3eVFJWbnef7k23P5z1B0nMx8go/P+u/v7JA8qZWi3Lon9qpWQ1qk5R A9+m1WA5TZUMb7n4Kns5S4KdA9ymn29eH4vNtSA/psSTtNe3t3p4kv4W4bZErkRz2iGMh +ol2xLn06knxIMPzzvuYMkakuyes4TzatvoZ2/yR1vW/n5UfibzEVRYjo6Wwf8Nj10w== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794064834; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=3KvOjTrk4nz7fdFP21LfdJKisJ2adsNffewnsN+lXds=; b=QM/6wynDVfExuumg84H3u6nsyKKmWdLwQcKL5dC9ewp+TSHSwCp6pN3ePllrYqo2Q7gH YcWtJLugfinmxqR8LnJMlZckwggKpGpg3539YhXcEp0bMclnSn4zQrwg6CJcFM5KC2ay+ 1qHk8WQ8WldAEB//9IvuH9L9RD/pnrCQ7hMLapnhSDtxyaSEmepl2W0QhIfqYUm/YVVi8 i1A9CSHjGIZSRsnTTzGcH7HU11NWvaPamx6yxwAUAXkRa3K6PC8ynAFgbDRZ+aYBlayF7 fHQ+bI8iCym2yU3k0HUynz1f9jGN+ydo542Q2zkcHGSMZvtgqcUhkgZaV1kKsuZAbsg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b="NO7D/GWN"; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F9D2606A32C; Sat, 7 Nov 2026 15:20:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=NO7D/GWN Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1A4E91F008A6; Sat, 7 Nov 2026 15:20:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1794064834; bh=3KvOjTrk4nz7fdFP21LfdJKisJ2adsNffewnsN+lXds=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=NO7D/GWNWz6D/BI139LfzlhG3OWslBA60HJeQnSsBBpEl9iX1qb4oEyhkvov4MVOS PtjKyD4lcmIarsC1m1VmaNA/u4MGMQqsTcBrRDdTyLnSnzGeUMyN6k8e1frJM5pfxf vH4GFYIfB8pHYfArdR1ZnlmatK0PTQcUjgr7IV5k= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Linus Walleij , Karl Mehltretter , Russell King , Sasha Levin Subject: [PATCH 7.3 0765/1257] ARM: 9491/1: alignment: restore uaccess state on emulation fault Date: Sat, 7 Nov 2026 08:51:01 -0500 Message-ID: <20261107135000.421201535@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261107134939.434104957@linuxfoundation.org> References: <20261107134939.434104957@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 7.3-stable review patch. If anyone has any objections, please let me know. ------------------ From: Karl Mehltretter [ Upstream commit 80dafbcb705cead6d25cb821cf29c47da8860c8c ] The alignment handlers enable access to user memory while emulating unaligned instructions. If a checked access faults, its exception table fixup jumps to the handler's fault label and bypasses uaccess_restore(). This leaves DOMAIN_USER as DOMAIN_CLIENT with SW domain PAN, or leaves TTBR0 page table walks enabled with TTBR0 PAN, while the fault is handled. An ARM926 QEMU test using LDMIA across an unmapped page boundary reports DOMAIN_USER=1 at TYPE_FAULT before this change and DOMAIN_USER=0 after it. SW domain PAN is the default on ARMv5, ARMv6, and non-LPAE ARMv7 builds. Keep the saved uaccess state at function scope and track whether it was saved. Restore it at the fault label only when needed. Paths that did not enable user access continue to skip the restore. Assisted-by: Codex:gpt-5.6-sol Fixes: 274e91b81ed2 ("ARM: alignment: fix alignment handling for uaccess changes") Cc: stable@vger.kernel.org Reviewed-by: Linus Walleij Signed-off-by: Karl Mehltretter Signed-off-by: Russell King Signed-off-by: Sasha Levin --- arch/arm/mm/alignment.c | 51 ++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 812380f30ae36..2b470a419dda3 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -341,6 +341,8 @@ static int do_alignment_ldrhstrh(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); + unsigned int ua_flags; + bool ua_saved = false; ai_half += 1; @@ -364,10 +366,11 @@ do_alignment_ldrhstrh(unsigned long addr, u32 instr, struct pt_regs *regs) user: if (LDST_L_BIT(instr)) { unsigned long val; - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; get16t_unaligned_check(val, addr); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); /* signed half-word? */ if (instr & 0x40) @@ -375,14 +378,17 @@ do_alignment_ldrhstrh(unsigned long addr, u32 instr, struct pt_regs *regs) regs->uregs[rd] = val; } else { - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; put16t_unaligned_check(regs->uregs[rd], addr); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); } return TYPE_LDST; fault: + if (ua_saved) + uaccess_restore(ua_flags); return TYPE_FAULT; } @@ -391,6 +397,8 @@ do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); unsigned int rd2; + unsigned int ua_flags; + bool ua_saved = false; int load; if ((instr & 0xfe000000) == 0xe8000000) { @@ -425,26 +433,30 @@ do_alignment_ldrdstrd(unsigned long addr, u32 instr, struct pt_regs *regs) user: if (load) { unsigned long val, val2; - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; get32t_unaligned_check(val, addr); get32t_unaligned_check(val2, addr + 4); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); regs->uregs[rd] = val; regs->uregs[rd2] = val2; } else { - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; put32t_unaligned_check(regs->uregs[rd], addr); put32t_unaligned_check(regs->uregs[rd2], addr + 4); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); } return TYPE_LDST; bad: return TYPE_ERROR; fault: + if (ua_saved) + uaccess_restore(ua_flags); return TYPE_FAULT; } @@ -452,6 +464,8 @@ static int do_alignment_ldrstr(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd = RD_BITS(instr); + unsigned int ua_flags; + bool ua_saved = false; ai_word += 1; @@ -469,18 +483,22 @@ do_alignment_ldrstr(unsigned long addr, u32 instr, struct pt_regs *regs) trans: if (LDST_L_BIT(instr)) { unsigned int val; - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; get32t_unaligned_check(val, addr); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); regs->uregs[rd] = val; } else { - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; put32t_unaligned_check(regs->uregs[rd], addr); - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); } return TYPE_LDST; fault: + if (ua_saved) + uaccess_restore(ua_flags); return TYPE_FAULT; } @@ -502,6 +520,8 @@ do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) { unsigned int rd, rn, correction, nr_regs, regbits; unsigned long eaddr, newaddr; + unsigned int ua_flags; + bool ua_saved = false; if (LDM_S_BIT(instr)) goto bad; @@ -547,7 +567,8 @@ do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) #endif if (user_mode(regs)) { - unsigned int __ua_flags = uaccess_save_and_enable(); + ua_flags = uaccess_save_and_enable(); + ua_saved = true; for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1) if (regbits & 1) { @@ -559,7 +580,7 @@ do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) put32t_unaligned_check(regs->uregs[rd], eaddr); eaddr += 4; } - uaccess_restore(__ua_flags); + uaccess_restore(ua_flags); } else { for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1) @@ -581,6 +602,8 @@ do_alignment_ldmstm(unsigned long addr, u32 instr, struct pt_regs *regs) return TYPE_DONE; fault: + if (ua_saved) + uaccess_restore(ua_flags); regs->ARM_pc -= correction; return TYPE_FAULT; -- 2.53.0