mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [GIT pull] locking/urgent for 5.7-rc1
@ 2020-04-12 14:18 Thomas Gleixner
  2020-04-12 14:18 ` [GIT pull] perf/urgent " Thomas Gleixner
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Thomas Gleixner @ 2020-04-12 14:18 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, x86

Linus,

please pull the latest locking/urgent branch from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking-urgent-2020-04-12

up to:  9a019db0b6be: locking/lockdep: Improve 'invalid wait context' splat


Three small fixes/updates for the locking core code:

 - Plug a task struct reference leak in the percpu rswem implementation.

 - Document the refcount interaction with PID_MAX_LIMIT

 - Improve the 'invalid wait context' data dump in lockdep so it contains
   all information which is required to decode the problem


Thanks,

	tglx

------------------>
Jann Horn (1):
      locking/refcount: Document interaction with PID_MAX_LIMIT

Peter Zijlstra (1):
      locking/lockdep: Improve 'invalid wait context' splat

Qian Cai (1):
      locking/percpu-rwsem: Fix a task_struct refcount


 include/linux/refcount.h      | 23 ++++++++++++++-----
 kernel/locking/lockdep.c      | 51 ++++++++++++++++++++++++++-----------------
 kernel/locking/percpu-rwsem.c |  3 ++-
 3 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/include/linux/refcount.h b/include/linux/refcount.h
index 0ac50cf62d06..0e3ee25eb156 100644
--- a/include/linux/refcount.h
+++ b/include/linux/refcount.h
@@ -38,11 +38,24 @@
  * atomic operations, then the count will continue to edge closer to 0. If it
  * reaches a value of 1 before /any/ of the threads reset it to the saturated
  * value, then a concurrent refcount_dec_and_test() may erroneously free the
- * underlying object. Given the precise timing details involved with the
- * round-robin scheduling of each thread manipulating the refcount and the need
- * to hit the race multiple times in succession, there doesn't appear to be a
- * practical avenue of attack even if using refcount_add() operations with
- * larger increments.
+ * underlying object.
+ * Linux limits the maximum number of tasks to PID_MAX_LIMIT, which is currently
+ * 0x400000 (and can't easily be raised in the future beyond FUTEX_TID_MASK).
+ * With the current PID limit, if no batched refcounting operations are used and
+ * the attacker can't repeatedly trigger kernel oopses in the middle of refcount
+ * operations, this makes it impossible for a saturated refcount to leave the
+ * saturation range, even if it is possible for multiple uses of the same
+ * refcount to nest in the context of a single task:
+ *
+ *     (UINT_MAX+1-REFCOUNT_SATURATED) / PID_MAX_LIMIT =
+ *     0x40000000 / 0x400000 = 0x100 = 256
+ *
+ * If hundreds of references are added/removed with a single refcounting
+ * operation, it may potentially be possible to leave the saturation range; but
+ * given the precise timing details involved with the round-robin scheduling of
+ * each thread manipulating the refcount and the need to hit the race multiple
+ * times in succession, there doesn't appear to be a practical avenue of attack
+ * even if using refcount_add() operations with larger increments.
  *
  * Memory ordering
  * ===============
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 1511690e4de7..ac10db66cc63 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -3952,10 +3952,36 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
 	return ret;
 }
 
+static inline short task_wait_context(struct task_struct *curr)
+{
+	/*
+	 * Set appropriate wait type for the context; for IRQs we have to take
+	 * into account force_irqthread as that is implied by PREEMPT_RT.
+	 */
+	if (curr->hardirq_context) {
+		/*
+		 * Check if force_irqthreads will run us threaded.
+		 */
+		if (curr->hardirq_threaded || curr->irq_config)
+			return LD_WAIT_CONFIG;
+
+		return LD_WAIT_SPIN;
+	} else if (curr->softirq_context) {
+		/*
+		 * Softirqs are always threaded.
+		 */
+		return LD_WAIT_CONFIG;
+	}
+
+	return LD_WAIT_MAX;
+}
+
 static int
 print_lock_invalid_wait_context(struct task_struct *curr,
 				struct held_lock *hlock)
 {
+	short curr_inner;
+
 	if (!debug_locks_off())
 		return 0;
 	if (debug_locks_silent)
@@ -3971,6 +3997,10 @@ print_lock_invalid_wait_context(struct task_struct *curr,
 	print_lock(hlock);
 
 	pr_warn("other info that might help us debug this:\n");
+
+	curr_inner = task_wait_context(curr);
+	pr_warn("context-{%d:%d}\n", curr_inner, curr_inner);
+
 	lockdep_print_held_locks(curr);
 
 	pr_warn("stack backtrace:\n");
@@ -4017,26 +4047,7 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next)
 	}
 	depth++;
 
-	/*
-	 * Set appropriate wait type for the context; for IRQs we have to take
-	 * into account force_irqthread as that is implied by PREEMPT_RT.
-	 */
-	if (curr->hardirq_context) {
-		/*
-		 * Check if force_irqthreads will run us threaded.
-		 */
-		if (curr->hardirq_threaded || curr->irq_config)
-			curr_inner = LD_WAIT_CONFIG;
-		else
-			curr_inner = LD_WAIT_SPIN;
-	} else if (curr->softirq_context) {
-		/*
-		 * Softirqs are always threaded.
-		 */
-		curr_inner = LD_WAIT_CONFIG;
-	} else {
-		curr_inner = LD_WAIT_MAX;
-	}
+	curr_inner = task_wait_context(curr);
 
 	for (; depth < curr->lockdep_depth; depth++) {
 		struct held_lock *prev = curr->held_locks + depth;
diff --git a/kernel/locking/percpu-rwsem.c b/kernel/locking/percpu-rwsem.c
index a008a1ba21a7..8bbafe3e5203 100644
--- a/kernel/locking/percpu-rwsem.c
+++ b/kernel/locking/percpu-rwsem.c
@@ -118,14 +118,15 @@ static int percpu_rwsem_wake_function(struct wait_queue_entry *wq_entry,
 				      unsigned int mode, int wake_flags,
 				      void *key)
 {
-	struct task_struct *p = get_task_struct(wq_entry->private);
 	bool reader = wq_entry->flags & WQ_FLAG_CUSTOM;
 	struct percpu_rw_semaphore *sem = key;
+	struct task_struct *p;
 
 	/* concurrent against percpu_down_write(), can get stolen */
 	if (!__percpu_rwsem_trylock(sem, reader))
 		return 1;
 
+	p = get_task_struct(wq_entry->private);
 	list_del_init(&wq_entry->entry);
 	smp_store_release(&wq_entry->private, NULL);
 


^ permalink raw reply	[flat|nested] 12+ messages in thread
* [GIT pull] irq/urgent for 5.7-rc1
@ 2020-04-05 13:41 Thomas Gleixner
  2020-04-05 13:41 ` [GIT pull] perf/urgent " Thomas Gleixner
  0 siblings, 1 reply; 12+ messages in thread
From: Thomas Gleixner @ 2020-04-05 13:41 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel, x86

Linus,

please pull the latest irq/urgent fixes from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-urgent-2020-04-05

up to:  a67cd1fb660d: Merge tag 'irqchip-fixes-5.7-1' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core


Two reverts addressing regressions of the Xilinx interrupt controller
driver which affected the PPC users.

Thanks,

	tglx

------------------>
Marc Zyngier (2):
      Revert "irqchip/xilinx: Do not call irq_set_default_host()"
      Revert "irqchip/xilinx: Enable generic irq multi handler"


 arch/microblaze/Kconfig           |  2 --
 arch/microblaze/include/asm/irq.h |  3 +++
 arch/microblaze/kernel/irq.c      | 21 ++++++++++++++++++++-
 drivers/irqchip/irq-xilinx-intc.c | 35 +++++++++++++++--------------------
 4 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 242f58ec086b..6a331bd57ea8 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -47,8 +47,6 @@ config MICROBLAZE
 	select CPU_NO_EFFICIENT_FFS
 	select MMU_GATHER_NO_RANGE if MMU
 	select SPARSE_IRQ
-	select GENERIC_IRQ_MULTI_HANDLER
-	select HANDLE_DOMAIN_IRQ
 
 # Endianness selection
 choice
diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h
index 5166f0893e2b..eac2fb4b3fb9 100644
--- a/arch/microblaze/include/asm/irq.h
+++ b/arch/microblaze/include/asm/irq.h
@@ -14,4 +14,7 @@
 struct pt_regs;
 extern void do_IRQ(struct pt_regs *regs);
 
+/* should be defined in each interrupt controller driver */
+extern unsigned int xintc_get_irq(void);
+
 #endif /* _ASM_MICROBLAZE_IRQ_H */
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index 0b37dde60a1e..903dad822fad 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -20,10 +20,29 @@
 #include <linux/irqchip.h>
 #include <linux/of_irq.h>
 
+static u32 concurrent_irq;
+
 void __irq_entry do_IRQ(struct pt_regs *regs)
 {
+	unsigned int irq;
+	struct pt_regs *old_regs = set_irq_regs(regs);
 	trace_hardirqs_off();
-	handle_arch_irq(regs);
+
+	irq_enter();
+	irq = xintc_get_irq();
+next_irq:
+	BUG_ON(!irq);
+	generic_handle_irq(irq);
+
+	irq = xintc_get_irq();
+	if (irq != -1U) {
+		pr_debug("next irq: %d\n", irq);
+		++concurrent_irq;
+		goto next_irq;
+	}
+
+	irq_exit();
+	set_irq_regs(old_regs);
 	trace_hardirqs_on();
 }
 
diff --git a/drivers/irqchip/irq-xilinx-intc.c b/drivers/irqchip/irq-xilinx-intc.c
index 7f811fe5bf69..1d3d273309bd 100644
--- a/drivers/irqchip/irq-xilinx-intc.c
+++ b/drivers/irqchip/irq-xilinx-intc.c
@@ -124,6 +124,20 @@ static unsigned int xintc_get_irq_local(struct xintc_irq_chip *irqc)
 	return irq;
 }
 
+unsigned int xintc_get_irq(void)
+{
+	unsigned int irq = -1;
+	u32 hwirq;
+
+	hwirq = xintc_read(primary_intc, IVR);
+	if (hwirq != -1U)
+		irq = irq_find_mapping(primary_intc->root_domain, hwirq);
+
+	pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
+
+	return irq;
+}
+
 static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 {
 	struct xintc_irq_chip *irqc = d->host_data;
@@ -163,25 +177,6 @@ static void xil_intc_irq_handler(struct irq_desc *desc)
 	chained_irq_exit(chip, desc);
 }
 
-static void xil_intc_handle_irq(struct pt_regs *regs)
-{
-	u32 hwirq;
-	struct xintc_irq_chip *irqc = primary_intc;
-
-	do {
-		hwirq = xintc_read(irqc, IVR);
-		if (likely(hwirq != -1U)) {
-			int ret;
-
-			ret = handle_domain_irq(irqc->root_domain, hwirq, regs);
-			WARN_ONCE(ret, "Unhandled HWIRQ %d\n", hwirq);
-			continue;
-		}
-
-		break;
-	} while (1);
-}
-
 static int __init xilinx_intc_of_init(struct device_node *intc,
 					     struct device_node *parent)
 {
@@ -250,7 +245,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc,
 		}
 	} else {
 		primary_intc = irqc;
-		set_handle_irq(xil_intc_handle_irq);
+		irq_set_default_host(primary_intc->root_domain);
 	}
 
 	return 0;


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2020-04-12 17:35 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-12 14:18 [GIT pull] locking/urgent for 5.7-rc1 Thomas Gleixner
2020-04-12 14:18 ` [GIT pull] perf/urgent " Thomas Gleixner
2020-04-12 17:25   ` pr-tracker-bot
2020-04-12 14:18 ` [GIT pull] sched/urgent " Thomas Gleixner
2020-04-12 17:25   ` pr-tracker-bot
2020-04-12 14:18 ` [GIT pull] timers/urgent " Thomas Gleixner
2020-04-12 17:25   ` pr-tracker-bot
2020-04-12 14:18 ` [GIT pull] x86/urgent " Thomas Gleixner
2020-04-12 17:25   ` pr-tracker-bot
2020-04-12 17:25 ` [GIT pull] locking/urgent " pr-tracker-bot
  -- strict thread matches above, loose matches on Subject: below --
2020-04-05 13:41 [GIT pull] irq/urgent " Thomas Gleixner
2020-04-05 13:41 ` [GIT pull] perf/urgent " Thomas Gleixner
2020-04-05 19:45   ` pr-tracker-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®