All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch added to 3.12-stable] locking/rtmutex: Prevent dequeue vs. unlock race
@ 2017-01-02 12:45 Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] locking/rtmutex: Use READ_ONCE() in rt_mutex_owner() Jiri Slaby
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Jiri Slaby @ 2017-01-02 12:45 UTC (permalink / raw)
  To: stable
  Cc: Thomas Gleixner, Linus Torvalds, Mark Rutland, Peter Zijlstra,
	Sebastian Siewior, Will Deacon, Ingo Molnar, Jiri Slaby

From: Thomas Gleixner <tglx@linutronix.de>

This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.

===============

commit dbb26055defd03d59f678cb5f2c992abe05b064a upstream.

David reported a futex/rtmutex state corruption. It's caused by the
following problem:

CPU0		CPU1		CPU2

l->owner=T1
		rt_mutex_lock(l)
		lock(l->wait_lock)
		l->owner = T1 | HAS_WAITERS;
		enqueue(T2)
		boost()
		  unlock(l->wait_lock)
		schedule()

				rt_mutex_lock(l)
				lock(l->wait_lock)
				l->owner = T1 | HAS_WAITERS;
				enqueue(T3)
				boost()
				  unlock(l->wait_lock)
				schedule()
		signal(->T2)	signal(->T3)
		lock(l->wait_lock)
		dequeue(T2)
		deboost()
		  unlock(l->wait_lock)
				lock(l->wait_lock)
				dequeue(T3)
				  ===> wait list is now empty
				deboost()
				 unlock(l->wait_lock)
		lock(l->wait_lock)
		fixup_rt_mutex_waiters()
		  if (wait_list_empty(l)) {
		    owner = l->owner & ~HAS_WAITERS;
		    l->owner = owner
		     ==> l->owner = T1
		  }

				lock(l->wait_lock)
rt_mutex_unlock(l)		fixup_rt_mutex_waiters()
				  if (wait_list_empty(l)) {
				    owner = l->owner & ~HAS_WAITERS;
cmpxchg(l->owner, T1, NULL)
 ===> Success (l->owner = NULL)
				    l->owner = owner
				     ==> l->owner = T1
				  }

That means the problem is caused by fixup_rt_mutex_waiters() which does the
RMW to clear the waiters bit unconditionally when there are no waiters in
the rtmutexes rbtree.

This can be fatal: A concurrent unlock can release the rtmutex in the
fastpath because the waiters bit is not set. If the cmpxchg() gets in the
middle of the RMW operation then the previous owner, which just unlocked
the rtmutex is set as the owner again when the write takes place after the
successfull cmpxchg().

The solution is rather trivial: verify that the owner member of the rtmutex
has the waiters bit set before clearing it. This does not require a
cmpxchg() or other atomic operations because the waiters bit can only be
set and cleared with the rtmutex wait_lock held. It's also safe against the
fast path unlock attempt. The unlock attempt via cmpxchg() will either see
the bit set and take the slowpath or see the bit cleared and release it
atomically in the fastpath.

It's remarkable that the test program provided by David triggers on ARM64
and MIPS64 really quick, but it refuses to reproduce on x86-64, while the
problem exists there as well. That refusal might explain that this got not
discovered earlier despite the bug existing from day one of the rtmutex
implementation more than 10 years ago.

Thanks to David for meticulously instrumenting the code and providing the
information which allowed to decode this subtle problem.

Reported-by: David Daney <ddaney@caviumnetworks.com>
Tested-by: David Daney <david.daney@cavium.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sebastian Siewior <bigeasy@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Fixes: 23f78d4a03c5 ("[PATCH] pi-futex: rt mutex core")
Link: http://lkml.kernel.org/r/20161130210030.351136722@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 kernel/rtmutex.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 2 deletions(-)

diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index 51a83343df68..132c6a00e301 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -64,8 +64,72 @@ static inline void clear_rt_mutex_waiters(struct rt_mutex *lock)
 
 static void fixup_rt_mutex_waiters(struct rt_mutex *lock)
 {
-	if (!rt_mutex_has_waiters(lock))
-		clear_rt_mutex_waiters(lock);
+	unsigned long owner, *p = (unsigned long *) &lock->owner;
+
+	if (rt_mutex_has_waiters(lock))
+		return;
+
+	/*
+	 * The rbtree has no waiters enqueued, now make sure that the
+	 * lock->owner still has the waiters bit set, otherwise the
+	 * following can happen:
+	 *
+	 * CPU 0	CPU 1		CPU2
+	 * l->owner=T1
+	 *		rt_mutex_lock(l)
+	 *		lock(l->lock)
+	 *		l->owner = T1 | HAS_WAITERS;
+	 *		enqueue(T2)
+	 *		boost()
+	 *		  unlock(l->lock)
+	 *		block()
+	 *
+	 *				rt_mutex_lock(l)
+	 *				lock(l->lock)
+	 *				l->owner = T1 | HAS_WAITERS;
+	 *				enqueue(T3)
+	 *				boost()
+	 *				  unlock(l->lock)
+	 *				block()
+	 *		signal(->T2)	signal(->T3)
+	 *		lock(l->lock)
+	 *		dequeue(T2)
+	 *		deboost()
+	 *		  unlock(l->lock)
+	 *				lock(l->lock)
+	 *				dequeue(T3)
+	 *				 ==> wait list is empty
+	 *				deboost()
+	 *				 unlock(l->lock)
+	 *		lock(l->lock)
+	 *		fixup_rt_mutex_waiters()
+	 *		  if (wait_list_empty(l) {
+	 *		    l->owner = owner
+	 *		    owner = l->owner & ~HAS_WAITERS;
+	 *		      ==> l->owner = T1
+	 *		  }
+	 *				lock(l->lock)
+	 * rt_mutex_unlock(l)		fixup_rt_mutex_waiters()
+	 *				  if (wait_list_empty(l) {
+	 *				    owner = l->owner & ~HAS_WAITERS;
+	 * cmpxchg(l->owner, T1, NULL)
+	 *  ===> Success (l->owner = NULL)
+	 *
+	 *				    l->owner = owner
+	 *				      ==> l->owner = T1
+	 *				  }
+	 *
+	 * With the check for the waiter bit in place T3 on CPU2 will not
+	 * overwrite. All tasks fiddling with the waiters bit are
+	 * serialized by l->lock, so nothing else can modify the waiters
+	 * bit. If the bit is set then nothing can change l->owner either
+	 * so the simple RMW is safe. The cmpxchg() will simply fail if it
+	 * happens in the middle of the RMW because the waiters bit is
+	 * still set.
+	 */
+	owner = READ_ONCE(*p);
+	if (owner & RT_MUTEX_HAS_WAITERS)
+		WRITE_ONCE(*p, owner & ~RT_MUTEX_HAS_WAITERS);
 }
 
 /*
-- 
2.11.0


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

* [patch added to 3.12-stable] locking/rtmutex: Use READ_ONCE() in rt_mutex_owner()
  2017-01-02 12:45 [patch added to 3.12-stable] locking/rtmutex: Prevent dequeue vs. unlock race Jiri Slaby
@ 2017-01-02 12:45 ` Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] perf/x86: Fix full width counter, counter overflow Jiri Slaby
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jiri Slaby @ 2017-01-02 12:45 UTC (permalink / raw)
  To: stable
  Cc: Thomas Gleixner, David Daney, Linus Torvalds, Mark Rutland,
	Peter Zijlstra, Sebastian Siewior, Steven Rostedt, Ingo Molnar,
	Jiri Slaby

From: Thomas Gleixner <tglx@linutronix.de>

This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.

===============

commit 1be5d4fa0af34fb7bafa205aeb59f5c7cc7a089d upstream.

While debugging the rtmutex unlock vs. dequeue race Will suggested to use
READ_ONCE() in rt_mutex_owner() as it might race against the
cmpxchg_release() in unlock_rt_mutex_safe().

Will: "It's a minor thing which will most likely not matter in practice"

Careful search did not unearth an actual problem in todays code, but it's
better to be safe than surprised.

Suggested-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: David Daney <ddaney@caviumnetworks.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sebastian Siewior <bigeasy@linutronix.de>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/20161130210030.431379999@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 kernel/rtmutex_common.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
index 53a66c85261b..1823c094fe96 100644
--- a/kernel/rtmutex_common.h
+++ b/kernel/rtmutex_common.h
@@ -96,8 +96,9 @@ task_top_pi_waiter(struct task_struct *p)
 
 static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
 {
-	return (struct task_struct *)
-		((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL);
+	unsigned long owner = (unsigned long) READ_ONCE(lock->owner);
+
+	return (struct task_struct *) (owner & ~RT_MUTEX_OWNER_MASKALL);
 }
 
 /*
-- 
2.11.0


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

* [patch added to 3.12-stable] perf/x86: Fix full width counter, counter overflow
  2017-01-02 12:45 [patch added to 3.12-stable] locking/rtmutex: Prevent dequeue vs. unlock race Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] locking/rtmutex: Use READ_ONCE() in rt_mutex_owner() Jiri Slaby
@ 2017-01-02 12:45 ` Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] can: raw: raw_setsockopt: limit number of can_filter that can be set Jiri Slaby
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jiri Slaby @ 2017-01-02 12:45 UTC (permalink / raw)
  To: stable
  Cc: Peter Zijlstra (Intel),
	Alexander Shishkin, Arnaldo Carvalho de Melo, Jiri Olsa,
	Linus Torvalds, Stephane Eranian, Thomas Gleixner, Vince Weaver,
	Ingo Molnar, Jiri Slaby

From: "Peter Zijlstra (Intel)" <peterz@infradead.org>

This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.

===============

commit 7f612a7f0bc13a2361a152862435b7941156b6af upstream.

Lukasz reported that perf stat counters overflow handling is broken on KNL/SLM.

Both these parts have full_width_write set, and that does indeed have
a problem. In order to deal with counter wrap, we must sample the
counter at at least half the counter period (see also the sampling
theorem) such that we can unambiguously reconstruct the count.

However commit:

  069e0c3c4058 ("perf/x86/intel: Support full width counting")

sets the sampling interval to the full period, not half.

Fixing that exposes another issue, in that we must not sign extend the
delta value when we shift it right; the counter cannot have
decremented after all.

With both these issues fixed, counter overflow functions correctly
again.

Reported-by: Lukasz Odzioba <lukasz.odzioba@intel.com>
Tested-by: Liang, Kan <kan.liang@intel.com>
Tested-by: Odzioba, Lukasz <lukasz.odzioba@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Fixes: 069e0c3c4058 ("perf/x86/intel: Support full width counting")
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 arch/x86/kernel/cpu/perf_event.c       | 2 +-
 arch/x86/kernel/cpu/perf_event_intel.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 0271272d55d0..050784bcd71f 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -64,7 +64,7 @@ u64 x86_perf_event_update(struct perf_event *event)
 	int shift = 64 - x86_pmu.cntval_bits;
 	u64 prev_raw_count, new_raw_count;
 	int idx = hwc->idx;
-	s64 delta;
+	u64 delta;
 
 	if (idx == INTEL_PMC_IDX_FIXED_BTS)
 		return 0;
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 04e7df068f0e..0c6527a168f0 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2578,7 +2578,7 @@ __init int intel_pmu_init(void)
 
 	/* Support full width counters using alternative MSR range */
 	if (x86_pmu.intel_cap.full_width_write) {
-		x86_pmu.max_period = x86_pmu.cntval_mask;
+		x86_pmu.max_period = x86_pmu.cntval_mask >> 1;
 		x86_pmu.perfctr = MSR_IA32_PMC0;
 		pr_cont("full-width counters, ");
 	}
-- 
2.11.0


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

* [patch added to 3.12-stable] can: raw: raw_setsockopt: limit number of can_filter that can be set
  2017-01-02 12:45 [patch added to 3.12-stable] locking/rtmutex: Prevent dequeue vs. unlock race Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] locking/rtmutex: Use READ_ONCE() in rt_mutex_owner() Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] perf/x86: Fix full width counter, counter overflow Jiri Slaby
@ 2017-01-02 12:45 ` Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] can: peak: fix bad memory access and free sequence Jiri Slaby
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jiri Slaby @ 2017-01-02 12:45 UTC (permalink / raw)
  To: stable; +Cc: Marc Kleine-Budde, Jiri Slaby

From: Marc Kleine-Budde <mkl@pengutronix.de>

This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.

===============

commit 332b05ca7a438f857c61a3c21a88489a21532364 upstream.

This patch adds a check to limit the number of can_filters that can be
set via setsockopt on CAN_RAW sockets. Otherwise allocations > MAX_ORDER
are not prevented resulting in a warning.

Reference: https://lkml.org/lkml/2016/12/2/230

Reported-by: Andrey Konovalov <andreyknvl@google.com>
Tested-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 include/uapi/linux/can.h | 1 +
 net/can/raw.c            | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h
index e52958d7c2d1..3018528bd1bf 100644
--- a/include/uapi/linux/can.h
+++ b/include/uapi/linux/can.h
@@ -158,5 +158,6 @@ struct can_filter {
 };
 
 #define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
+#define CAN_RAW_FILTER_MAX 512 /* maximum number of can_filter set via setsockopt() */
 
 #endif /* CAN_H */
diff --git a/net/can/raw.c b/net/can/raw.c
index 641e1c895123..e10699cc72bd 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -470,6 +470,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
 		if (optlen % sizeof(struct can_filter) != 0)
 			return -EINVAL;
 
+		if (optlen > CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
+			return -EINVAL;
+
 		count = optlen / sizeof(struct can_filter);
 
 		if (count > 1) {
-- 
2.11.0


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

* [patch added to 3.12-stable] can: peak: fix bad memory access and free sequence
  2017-01-02 12:45 [patch added to 3.12-stable] locking/rtmutex: Prevent dequeue vs. unlock race Jiri Slaby
                   ` (2 preceding siblings ...)
  2017-01-02 12:45 ` [patch added to 3.12-stable] can: raw: raw_setsockopt: limit number of can_filter that can be set Jiri Slaby
@ 2017-01-02 12:45 ` Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] m68k: Fix ndelay() macro Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] hotplug: Make register and unregister notifier API symmetric Jiri Slaby
  5 siblings, 0 replies; 7+ messages in thread
From: Jiri Slaby @ 2017-01-02 12:45 UTC (permalink / raw)
  To: stable; +Cc: 추지호, Marc Kleine-Budde, Jiri Slaby

From: 추지호 <jiho.chu@samsung.com>

This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.

===============

commit b67d0dd7d0dc9e456825447bbeb935d8ef43ea7c upstream.

Fix for bad memory access while disconnecting. netdev is freed before
private data free, and dev is accessed after freeing netdev.

This makes a slub problem, and it raise kernel oops with slub debugger
config.

Signed-off-by: Jiho Chu <jiho.chu@samsung.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 drivers/net/can/usb/peak_usb/pcan_usb_core.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 03e7f0cbda8c..47f0dcbf42ca 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -824,23 +824,25 @@ lbl_free_candev:
 static void peak_usb_disconnect(struct usb_interface *intf)
 {
 	struct peak_usb_device *dev;
+	struct peak_usb_device *dev_prev_siblings;
 
 	/* unregister as many netdev devices as siblings */
-	for (dev = usb_get_intfdata(intf); dev; dev = dev->prev_siblings) {
+	for (dev = usb_get_intfdata(intf); dev; dev = dev_prev_siblings) {
 		struct net_device *netdev = dev->netdev;
 		char name[IFNAMSIZ];
 
+		dev_prev_siblings = dev->prev_siblings;
 		dev->state &= ~PCAN_USB_STATE_CONNECTED;
 		strncpy(name, netdev->name, IFNAMSIZ);
 
 		unregister_netdev(netdev);
-		free_candev(netdev);
 
 		kfree(dev->cmd_buf);
 		dev->next_siblings = NULL;
 		if (dev->adapter->dev_free)
 			dev->adapter->dev_free(dev);
 
+		free_candev(netdev);
 		dev_info(&intf->dev, "%s removed\n", name);
 	}
 
-- 
2.11.0


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

* [patch added to 3.12-stable] m68k: Fix ndelay() macro
  2017-01-02 12:45 [patch added to 3.12-stable] locking/rtmutex: Prevent dequeue vs. unlock race Jiri Slaby
                   ` (3 preceding siblings ...)
  2017-01-02 12:45 ` [patch added to 3.12-stable] can: peak: fix bad memory access and free sequence Jiri Slaby
@ 2017-01-02 12:45 ` Jiri Slaby
  2017-01-02 12:45 ` [patch added to 3.12-stable] hotplug: Make register and unregister notifier API symmetric Jiri Slaby
  5 siblings, 0 replies; 7+ messages in thread
From: Jiri Slaby @ 2017-01-02 12:45 UTC (permalink / raw)
  To: stable; +Cc: Boris Brezillon, Geert Uytterhoeven, Jiri Slaby

From: Boris Brezillon <boris.brezillon@free-electrons.com>

This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.

===============

commit 7e251bb21ae08ca2e4fb28cc0981fac2685a8efa upstream.

The current ndelay() macro definition has an extra semi-colon at the
end of the line thus leading to a compilation error when ndelay is used
in a conditional block without curly braces like this one:

	if (cond)
		ndelay(t);
	else
		...

which, after the preprocessor pass gives:

	if (cond)
		m68k_ndelay(t);;
	else
		...

thus leading to the following gcc error:

	error: 'else' without a previous 'if'

Remove this extra semi-colon.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Fixes: c8ee038bd1488 ("m68k: Implement ndelay() based on the existing udelay() logic")
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 arch/m68k/include/asm/delay.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h
index d28fa8fe26fe..c598d847d56b 100644
--- a/arch/m68k/include/asm/delay.h
+++ b/arch/m68k/include/asm/delay.h
@@ -114,6 +114,6 @@ static inline void __udelay(unsigned long usecs)
  */
 #define	HZSCALE		(268435456 / (1000000 / HZ))
 
-#define ndelay(n) __delay(DIV_ROUND_UP((n) * ((((HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6), 1000));
+#define ndelay(n) __delay(DIV_ROUND_UP((n) * ((((HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6), 1000))
 
 #endif /* defined(_M68K_DELAY_H) */
-- 
2.11.0


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

* [patch added to 3.12-stable] hotplug: Make register and unregister notifier API symmetric
  2017-01-02 12:45 [patch added to 3.12-stable] locking/rtmutex: Prevent dequeue vs. unlock race Jiri Slaby
                   ` (4 preceding siblings ...)
  2017-01-02 12:45 ` [patch added to 3.12-stable] m68k: Fix ndelay() macro Jiri Slaby
@ 2017-01-02 12:45 ` Jiri Slaby
  5 siblings, 0 replies; 7+ messages in thread
From: Jiri Slaby @ 2017-01-02 12:45 UTC (permalink / raw)
  To: stable
  Cc: Michal Hocko, linux-mm, Andrew Morton, Dan Streetman,
	Thomas Gleixner, Jiri Slaby

From: Michal Hocko <mhocko@suse.com>

This patch has been added to the 3.12 stable tree. If you have any
objections, please let us know.

===============

commit 777c6e0daebb3fcefbbd6f620410a946b07ef6d0 upstream.

Yu Zhao has noticed that __unregister_cpu_notifier only unregisters its
notifiers when HOTPLUG_CPU=y while the registration might succeed even
when HOTPLUG_CPU=n if MODULE is enabled. This means that e.g. zswap
might keep a stale notifier on the list on the manual clean up during
the pool tear down and thus corrupt the list. Resulting in the following

[  144.964346] BUG: unable to handle kernel paging request at ffff880658a2be78
[  144.971337] IP: [<ffffffffa290b00b>] raw_notifier_chain_register+0x1b/0x40
<snipped>
[  145.122628] Call Trace:
[  145.125086]  [<ffffffffa28e5cf8>] __register_cpu_notifier+0x18/0x20
[  145.131350]  [<ffffffffa2a5dd73>] zswap_pool_create+0x273/0x400
[  145.137268]  [<ffffffffa2a5e0fc>] __zswap_param_set+0x1fc/0x300
[  145.143188]  [<ffffffffa2944c1d>] ? trace_hardirqs_on+0xd/0x10
[  145.149018]  [<ffffffffa2908798>] ? kernel_param_lock+0x28/0x30
[  145.154940]  [<ffffffffa2a3e8cf>] ? __might_fault+0x4f/0xa0
[  145.160511]  [<ffffffffa2a5e237>] zswap_compressor_param_set+0x17/0x20
[  145.167035]  [<ffffffffa2908d3c>] param_attr_store+0x5c/0xb0
[  145.172694]  [<ffffffffa290848d>] module_attr_store+0x1d/0x30
[  145.178443]  [<ffffffffa2b2b41f>] sysfs_kf_write+0x4f/0x70
[  145.183925]  [<ffffffffa2b2a5b9>] kernfs_fop_write+0x149/0x180
[  145.189761]  [<ffffffffa2a99248>] __vfs_write+0x18/0x40
[  145.194982]  [<ffffffffa2a9a412>] vfs_write+0xb2/0x1a0
[  145.200122]  [<ffffffffa2a9a732>] SyS_write+0x52/0xa0
[  145.205177]  [<ffffffffa2ff4d97>] entry_SYSCALL_64_fastpath+0x12/0x17

This can be even triggered manually by changing
/sys/module/zswap/parameters/compressor multiple times.

Fix this issue by making unregister APIs symmetric to the register so
there are no surprises.

[js] backport to 3.12

Fixes: 47e627bc8c9a ("[PATCH] hotplug: Allow modules to use the cpu hotplug notifiers even if !CONFIG_HOTPLUG_CPU")
Reported-and-tested-by: Yu Zhao <yuzhao@google.com>
Signed-off-by: Michal Hocko <mhocko@suse.com>
Cc: linux-mm@kvack.org
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Dan Streetman <ddstreet@ieee.org>
Link: http://lkml.kernel.org/r/20161207135438.4310-1-mhocko@kernel.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 include/linux/cpu.h | 12 +++---------
 kernel/cpu.c        |  3 +--
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 801ff9e73679..d1fcdcbc01e4 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -119,22 +119,16 @@ enum {
 		{ .notifier_call = fn, .priority = pri };	\
 	register_cpu_notifier(&fn##_nb);			\
 }
-#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
-#define cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
-#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
-#ifdef CONFIG_HOTPLUG_CPU
 extern int register_cpu_notifier(struct notifier_block *nb);
 extern void unregister_cpu_notifier(struct notifier_block *nb);
-#else
 
-#ifndef MODULE
-extern int register_cpu_notifier(struct notifier_block *nb);
-#else
+#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
+#define cpu_notifier(fn, pri)	do { (void)(fn); } while (0)
+
 static inline int register_cpu_notifier(struct notifier_block *nb)
 {
 	return 0;
 }
-#endif
 
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 92599d897125..c1f258a0a10e 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -182,8 +182,6 @@ static int cpu_notify(unsigned long val, void *v)
 	return __cpu_notify(val, v, -1, NULL);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
 static void cpu_notify_nofail(unsigned long val, void *v)
 {
 	BUG_ON(cpu_notify(val, v));
@@ -198,6 +196,7 @@ void __ref unregister_cpu_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
+#ifdef CONFIG_HOTPLUG_CPU
 /**
  * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
  * @cpu: a CPU id
-- 
2.11.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

end of thread, other threads:[~2017-01-02 12:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-02 12:45 [patch added to 3.12-stable] locking/rtmutex: Prevent dequeue vs. unlock race Jiri Slaby
2017-01-02 12:45 ` [patch added to 3.12-stable] locking/rtmutex: Use READ_ONCE() in rt_mutex_owner() Jiri Slaby
2017-01-02 12:45 ` [patch added to 3.12-stable] perf/x86: Fix full width counter, counter overflow Jiri Slaby
2017-01-02 12:45 ` [patch added to 3.12-stable] can: raw: raw_setsockopt: limit number of can_filter that can be set Jiri Slaby
2017-01-02 12:45 ` [patch added to 3.12-stable] can: peak: fix bad memory access and free sequence Jiri Slaby
2017-01-02 12:45 ` [patch added to 3.12-stable] m68k: Fix ndelay() macro Jiri Slaby
2017-01-02 12:45 ` [patch added to 3.12-stable] hotplug: Make register and unregister notifier API symmetric Jiri Slaby

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.