public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/4] use rcu_read_lock() during module list walk
@ 2015-07-31 17:08 Sebastian Andrzej Siewior
  2015-07-31 17:08 ` [RFC 1/4] module: use rcu_read_lock() while walking over a RCU protected list Sebastian Andrzej Siewior
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-07-31 17:08 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, Rusty Russell, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, tglx

Hi Peter,

this series was made before I noticed that you introduced a RB tree for
lookup but the old way still remains under !CONFIG_MODULES_TREE_LOOKUP.
In the old way the caller had preempt_disable() while invoking
list_for_each_safe_rcu() which is (according to the RCU checklist) not a
substitute for rcu_readlock().
With your CONFIG_MODULES_TREE_LOOKUP I fail to understand what blocks
free_module() until all mod_find() callers have dropped their refrence to
the obtained struct mod. We had synchronize_sched() in RCU case.

Sebastian


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

* [RFC 1/4] module: use rcu_read_lock() while walking over a RCU protected list
  2015-07-31 17:08 [RFC 0/4] use rcu_read_lock() during module list walk Sebastian Andrzej Siewior
@ 2015-07-31 17:08 ` Sebastian Andrzej Siewior
  2015-07-31 17:14   ` Peter Zijlstra
  2015-07-31 17:08 ` [RFC 2/4] jump_label: use rcu_read_lock() while accessing __module_*() Sebastian Andrzej Siewior
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-07-31 17:08 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, Rusty Russell, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, tglx, Sebastian Andrzej Siewior

The `modules' list uses list_for_each_entry_rcu() itarator.
rcu_readlock() protects here against against module removal invoked from
another CPU while preempt_disable() does not.

I don't understand what syncs in CONFIG_MODULES_TREE_LOOKUP against
module removal. In the other (RCU) case there is synchronize_sched().

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/module.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/module.c b/kernel/module.c
index 4d2b82e610e2..a62d2d48cd63 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3979,9 +3979,9 @@ bool is_module_address(unsigned long addr)
 {
 	bool ret;
 
-	preempt_disable();
+	rcu_read_lock();
 	ret = __module_address(addr) != NULL;
-	preempt_enable();
+	rcu_read_unlock();
 
 	return ret;
 }
@@ -3990,7 +3990,7 @@ bool is_module_address(unsigned long addr)
  * __module_address - get the module which contains an address.
  * @addr: the address.
  *
- * Must be called with preempt disabled or module mutex held so that
+ * Must be called with RCU read or module mutex held so that
  * module doesn't get freed during this.
  */
 struct module *__module_address(unsigned long addr)
@@ -4024,9 +4024,9 @@ bool is_module_text_address(unsigned long addr)
 {
 	bool ret;
 
-	preempt_disable();
+	rcu_read_lock();
 	ret = __module_text_address(addr) != NULL;
-	preempt_enable();
+	rcu_read_unlock();
 
 	return ret;
 }
@@ -4035,7 +4035,7 @@ bool is_module_text_address(unsigned long addr)
  * __module_text_address - get the module whose code contains an address.
  * @addr: the address.
  *
- * Must be called with preempt disabled or module mutex held so that
+ * Must be called with RCU read lock or module mutex held so that
  * module doesn't get freed during this.
  */
 struct module *__module_text_address(unsigned long addr)
-- 
2.4.6


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

* [RFC 2/4] jump_label: use rcu_read_lock() while accessing __module_*()
  2015-07-31 17:08 [RFC 0/4] use rcu_read_lock() during module list walk Sebastian Andrzej Siewior
  2015-07-31 17:08 ` [RFC 1/4] module: use rcu_read_lock() while walking over a RCU protected list Sebastian Andrzej Siewior
@ 2015-07-31 17:08 ` Sebastian Andrzej Siewior
  2015-07-31 17:16   ` Peter Zijlstra
  2015-07-31 17:08 ` [RFC 3/4] kprobes: Add a RCU lock while invoking __module_text_address() Sebastian Andrzej Siewior
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-07-31 17:08 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, Rusty Russell, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, tglx, Sebastian Andrzej Siewior

__jump_label_mod_text_reserved() should most likely use rcu_read_lock()
while invoking __module_text_address(). I'm not sure there is anything
to protect the module pointed by `start' and `end' from removal.
I *think* the protection is based on the preempt_disable() in
check_kprobe_address_safe(). That preempt_disable however does not
protect from module removal on a SMP machine.

Same goes for jump_label_update(). I think it is safe here to avoid the
read lock since the caller is the module so it can't go away at the same
time. However it might get a problem if the key reference here is shared
across modules for some reason with no module dependency.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/jump_label.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 52ebaca1b9fc..8aa9e0fce92e 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -231,16 +231,21 @@ struct static_key_mod {
 static int __jump_label_mod_text_reserved(void *start, void *end)
 {
 	struct module *mod;
+	int ret = 0;
 
+	rcu_read_lock();
 	mod = __module_text_address((unsigned long)start);
 	if (!mod)
-		return 0;
+		goto out;
 
 	WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
 
-	return __jump_label_text_reserved(mod->jump_entries,
+	ret = __jump_label_text_reserved(mod->jump_entries,
 				mod->jump_entries + mod->num_jump_entries,
 				start, end);
+out:
+	rcu_read_unlock();
+	return ret;
 }
 
 static void __jump_label_mod_update(struct static_key *key, int enable)
@@ -448,11 +453,11 @@ static void jump_label_update(struct static_key *key, int enable)
 
 	__jump_label_mod_update(key, enable);
 
-	preempt_disable();
+	rcu_read_lock();
 	mod = __module_address((unsigned long)key);
 	if (mod)
 		stop = mod->jump_entries + mod->num_jump_entries;
-	preempt_enable();
+	rcu_read_unlock();
 #endif
 	/* if there are no users, entry can be NULL */
 	if (entry)
-- 
2.4.6


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

* [RFC 3/4] kprobes: Add a RCU lock while invoking __module_text_address()
  2015-07-31 17:08 [RFC 0/4] use rcu_read_lock() during module list walk Sebastian Andrzej Siewior
  2015-07-31 17:08 ` [RFC 1/4] module: use rcu_read_lock() while walking over a RCU protected list Sebastian Andrzej Siewior
  2015-07-31 17:08 ` [RFC 2/4] jump_label: use rcu_read_lock() while accessing __module_*() Sebastian Andrzej Siewior
@ 2015-07-31 17:08 ` Sebastian Andrzej Siewior
  2015-07-31 17:08 ` [RFC 4/4] kprobe: remove preempt_disable() from check_kprobe_address_safe() Sebastian Andrzej Siewior
  2015-07-31 17:22 ` [RFC 0/4] use rcu_read_lock() during module list walk Peter Zijlstra
  4 siblings, 0 replies; 8+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-07-31 17:08 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, Rusty Russell, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, tglx, Sebastian Andrzej Siewior

delete_module() first sets the module's state to MODULE_STATE_GOING
which means further try_module_get() invocations will fail. However
without a RCU readlock there is nothing that ensures that the pointer
returned by __module_text_address() is still valid in try_module_get().
The preempt_disable() does not protect here against module removal from
another CPU.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/kprobes.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index c90e417bb963..a2d4e5164d7d 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1449,6 +1449,7 @@ static int check_kprobe_address_safe(struct kprobe *p,
 	}
 
 	/* Check if are we probing a module */
+	rcu_read_lock();
 	*probed_mod = __module_text_address((unsigned long) p->addr);
 	if (*probed_mod) {
 		/*
@@ -1457,7 +1458,7 @@ static int check_kprobe_address_safe(struct kprobe *p,
 		 */
 		if (unlikely(!try_module_get(*probed_mod))) {
 			ret = -ENOENT;
-			goto out;
+			goto out_rcu_unlock;
 		}
 
 		/*
@@ -1471,6 +1472,8 @@ static int check_kprobe_address_safe(struct kprobe *p,
 			ret = -ENOENT;
 		}
 	}
+out_rcu_unlock:
+	rcu_read_unlock();
 out:
 	preempt_enable();
 	jump_label_unlock();
-- 
2.4.6


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

* [RFC 4/4] kprobe: remove preempt_disable() from check_kprobe_address_safe()
  2015-07-31 17:08 [RFC 0/4] use rcu_read_lock() during module list walk Sebastian Andrzej Siewior
                   ` (2 preceding siblings ...)
  2015-07-31 17:08 ` [RFC 3/4] kprobes: Add a RCU lock while invoking __module_text_address() Sebastian Andrzej Siewior
@ 2015-07-31 17:08 ` Sebastian Andrzej Siewior
  2015-07-31 17:22 ` [RFC 0/4] use rcu_read_lock() during module list walk Peter Zijlstra
  4 siblings, 0 replies; 8+ messages in thread
From: Sebastian Andrzej Siewior @ 2015-07-31 17:08 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-kernel, Rusty Russell, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, tglx, Sebastian Andrzej Siewior

It should be safe to remove preempt_disable() here. It was introduced in
commit a189d0350f387 ("kprobes: disable preempt for module_text_address()
and kernel_text_address()") to protect against module removal. This is
however wrong (now) because the RCU list which is used requires a RCU
readlock. The comment in __module_text_address() has been updated and the
caller, too.
I *think* this preempt_disable() may go now.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 kernel/kprobes.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index a2d4e5164d7d..92d50ea83564 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1438,7 +1438,6 @@ static int check_kprobe_address_safe(struct kprobe *p,
 	if (ret)
 		return ret;
 	jump_label_lock();
-	preempt_disable();
 
 	/* Ensure it is not in reserved area nor out of text */
 	if (!kernel_text_address((unsigned long) p->addr) ||
@@ -1475,7 +1474,6 @@ static int check_kprobe_address_safe(struct kprobe *p,
 out_rcu_unlock:
 	rcu_read_unlock();
 out:
-	preempt_enable();
 	jump_label_unlock();
 
 	return ret;
-- 
2.4.6


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

* Re: [RFC 1/4] module: use rcu_read_lock() while walking over a RCU protected list
  2015-07-31 17:08 ` [RFC 1/4] module: use rcu_read_lock() while walking over a RCU protected list Sebastian Andrzej Siewior
@ 2015-07-31 17:14   ` Peter Zijlstra
  0 siblings, 0 replies; 8+ messages in thread
From: Peter Zijlstra @ 2015-07-31 17:14 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-kernel, Rusty Russell, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, tglx

On Fri, Jul 31, 2015 at 07:08:05PM +0200, Sebastian Andrzej Siewior wrote:
> The `modules' list uses list_for_each_entry_rcu() itarator.
> rcu_readlock() protects here against against module removal invoked from
> another CPU while preempt_disable() does not.

Not so, it does in fact.

> I don't understand what syncs in CONFIG_MODULES_TREE_LOOKUP against
> module removal. In the other (RCU) case there is synchronize_sched().

Its using rcu-sched aka preempt_disable.

if you want to use rcu primitives, use rcu_read_lock_sched(), but that
is in fact identical to preempt_disable().

Your patch breaks things.

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

* Re: [RFC 2/4] jump_label: use rcu_read_lock() while accessing __module_*()
  2015-07-31 17:08 ` [RFC 2/4] jump_label: use rcu_read_lock() while accessing __module_*() Sebastian Andrzej Siewior
@ 2015-07-31 17:16   ` Peter Zijlstra
  0 siblings, 0 replies; 8+ messages in thread
From: Peter Zijlstra @ 2015-07-31 17:16 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-kernel, Rusty Russell, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, tglx

On Fri, Jul 31, 2015 at 07:08:06PM +0200, Sebastian Andrzej Siewior wrote:
> __jump_label_mod_text_reserved() should most likely use rcu_read_lock()
> while invoking __module_text_address(). I'm not sure there is anything
> to protect the module pointed by `start' and `end' from removal.
> I *think* the protection is based on the preempt_disable() in
> check_kprobe_address_safe(). That preempt_disable however does not
> protect from module removal on a SMP machine.

Yes it does, seeing how it uses sync_sched().

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

* Re: [RFC 0/4] use rcu_read_lock() during module list walk
  2015-07-31 17:08 [RFC 0/4] use rcu_read_lock() during module list walk Sebastian Andrzej Siewior
                   ` (3 preceding siblings ...)
  2015-07-31 17:08 ` [RFC 4/4] kprobe: remove preempt_disable() from check_kprobe_address_safe() Sebastian Andrzej Siewior
@ 2015-07-31 17:22 ` Peter Zijlstra
  4 siblings, 0 replies; 8+ messages in thread
From: Peter Zijlstra @ 2015-07-31 17:22 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-kernel, Rusty Russell, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, tglx

On Fri, Jul 31, 2015 at 07:08:04PM +0200, Sebastian Andrzej Siewior wrote:
> Hi Peter,
> 
> this series was made before I noticed that you introduced a RB tree for
> lookup but the old way still remains under !CONFIG_MODULES_TREE_LOOKUP.

> In the old way the caller had preempt_disable() while invoking
> list_for_each_safe_rcu() which is (according to the RCU checklist) not a
> substitute for rcu_readlock().

This is true. preempt_disable() != rcu_read_lock().

> With your CONFIG_MODULES_TREE_LOOKUP I fail to understand what blocks
> free_module() until all mod_find() callers have dropped their refrence to
> the obtained struct mod. We had synchronize_sched() in RCU case.

We still have synchronize_sched(), but that is not RCU, that is
RCU-sched, and rcu_read_lock_sched() == preempt_disable() (+- some
debugging bits).

The code used to be broken in this regard, see 0be964be0d45 ("module:
Sanitize RCU usage and locking"), that fixed things to be consistent.

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

end of thread, other threads:[~2015-07-31 17:22 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-31 17:08 [RFC 0/4] use rcu_read_lock() during module list walk Sebastian Andrzej Siewior
2015-07-31 17:08 ` [RFC 1/4] module: use rcu_read_lock() while walking over a RCU protected list Sebastian Andrzej Siewior
2015-07-31 17:14   ` Peter Zijlstra
2015-07-31 17:08 ` [RFC 2/4] jump_label: use rcu_read_lock() while accessing __module_*() Sebastian Andrzej Siewior
2015-07-31 17:16   ` Peter Zijlstra
2015-07-31 17:08 ` [RFC 3/4] kprobes: Add a RCU lock while invoking __module_text_address() Sebastian Andrzej Siewior
2015-07-31 17:08 ` [RFC 4/4] kprobe: remove preempt_disable() from check_kprobe_address_safe() Sebastian Andrzej Siewior
2015-07-31 17:22 ` [RFC 0/4] use rcu_read_lock() during module list walk Peter Zijlstra

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