lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20211001144406.7719-4-kernelfans@gmail.com>
Date:   Fri,  1 Oct 2021 22:44:06 +0800
From:   Pingfan Liu <kernelfans@...il.com>
To:     linux-arm-kernel@...ts.infradead.org
Cc:     Pingfan Liu <kernelfans@...il.com>,
        Mark Rutland <mark.rutland@....com>,
        Marc Zyngier <maz@...nel.org>,
        "Paul E. McKenney" <paulmck@...nel.org>,
        Catalin Marinas <catalin.marinas@....com>,
        Will Deacon <will@...nel.org>, Joey Gouly <joey.gouly@....com>,
        Sami Tolvanen <samitolvanen@...gle.com>,
        Julien Thierry <julien.thierry@....com>,
        Thomas Gleixner <tglx@...utronix.de>,
        Yuichi Ito <ito-yuichi@...itsu.com>,
        linux-kernel@...r.kernel.org
Subject: [PATCHv4 3/3] arm64: entry: avoid double-accounting IRQ RCU entry

When an IRQ is taken, some accounting needs to be performed to enter and
exit IRQ context around the IRQ handler. On arm64 some of this
accounting is performed by both the architecture code and the IRQ domain
code, resulting in calling rcu_irq_enter() twice per exception entry,
violating the expectations of the core RCU code, and resulting in
failing to identify quiescent periods correctly (e.g. in
rcu_is_cpu_rrupt_from_idle()).

To fix this, we must perform all the accounting from the architecture
code. We prevent the IRQ domain code from performing any accounting by
selecting HAVE_ARCH_IRQENTRY, and must call irq_enter_rcu() and
irq_exit_rcu() around invoking the root IRQ handler.

When we take a pNMI from a context with IRQs disabled, we'll perform the
necessary accounting as part of arm64_enter_nmi() and arm64_exit_nmi(),
and should only call irq_enter_rcu() and irq_exit_rcu() when we may have
taken a regular interrupt.

Signed-off-by: Pingfan Liu <kernelfans@...il.com>
Reviewed-by: Mark Rutland <mark.rutland@....com>
Reviewed-by: Marc Zyngier <maz@...nel.org>
Cc: "Paul E. McKenney" <paulmck@...nel.org>
Cc: Catalin Marinas <catalin.marinas@....com>
Cc: Will Deacon <will@...nel.org>
Cc: Joey Gouly <joey.gouly@....com>
Cc: Sami Tolvanen <samitolvanen@...gle.com>
Cc: Julien Thierry <julien.thierry@....com>
Cc: Thomas Gleixner <tglx@...utronix.de>
Cc: Yuichi Ito <ito-yuichi@...itsu.com>
Cc: linux-kernel@...r.kernel.org
To: linux-arm-kernel@...ts.infradead.org
---
 arch/arm64/Kconfig               | 1 +
 arch/arm64/kernel/entry-common.c | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 5c7ae4c3954b..c0ba052116b2 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -144,6 +144,7 @@ config ARM64
 	select HAVE_ARCH_BITREVERSE
 	select HAVE_ARCH_COMPILER_H
 	select HAVE_ARCH_HUGE_VMAP
+	select HAVE_ARCH_IRQENTRY
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_JUMP_LABEL_RELATIVE
 	select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index fecf046f0708..af931e63dc59 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -428,7 +428,9 @@ static __always_inline void
 __el1_interrupt(struct pt_regs *regs, void (*handler)(struct pt_regs *))
 {
 	enter_from_kernel_mode(regs);
+	irq_enter_rcu();
 	do_interrupt_handler(regs, handler);
+	irq_exit_rcu();
 	/*
 	 * Note: thread_info::preempt_count includes both thread_info::count
 	 * and thread_info::need_resched, and is not equivalent to
@@ -666,7 +668,9 @@ static void noinstr el0_interrupt(struct pt_regs *regs,
 	if (regs->pc & BIT(55))
 		arm64_apply_bp_hardening();
 
+	irq_enter_rcu();
 	do_interrupt_handler(regs, handler);
+	irq_exit_rcu();
 
 	exit_to_user_mode(regs);
 }
-- 
2.31.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ