futex: Don't enable IRQs unconditionally in put_pi_state()
Subsystems (2)
PATCH 1/1 futex: Don't enable IRQs unconditionally in put_pi_state()
The exit_pi_state_list() function calls put_pi_state() with IRQs disabled and is not expecting that IRQs will be enabled inside the function. Use the _irqsave() so that IRQs are restored to the original state instead of enabled unconditionally.
---
This is from static analysis and not tested. I am not very familiar with futex code.
kernel/futex.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/futex.c +3 -2
@@ -788,8 +788,9 @@ static void put_pi_state(struct futex_pi_state *pi_state)*/ if (pi_state->owner) {struct task_struct *owner; +unsigned long flags; -raw_spin_lock_irq (&pi_state->pi_mutex.wait_lock); +raw_spin_lock_irqsave (&pi_state->pi_mutex.wait_lock, flags); owner = pi_state->owner;if (owner) {raw_spin_lock (&owner->pi_lock);
@@ -797,7 +798,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)raw_spin_unlock (&owner->pi_lock); }rt_mutex_proxy_unlock (&pi_state->pi_mutex, owner); -raw_spin_unlock_irq (&pi_state->pi_mutex.wait_lock); +raw_spin_unlock_irqrestore (&pi_state->pi_mutex.wait_lock, flags); }if (current->pi_state_cache) {
Signature · 1 line
2.28.0
Quoted 10 lines · Dan Carpenter
The
exit_pi_state_list()function callsput_pi_state()with IRQs disabled and is not expecting that IRQs will be enabled inside the function. Use the_irqsave()so that IRQs are restored to the original state instead of enabled unconditionally.Fixes 153fbd1226fb ("futex: Fix more put_pi_state() vs. exit_pi_state_list() races")Signed-off-by Dan Carpenter <[email protected]>---
This is from static analysis and not tested. I am not very familiar with futex code.
It it exceedingly rare if at all possible to trigger this, but yes, your patch is correct.
Quoted 31 lines
kernel/futex.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)kernel/futex.c +3
-2@@ -788,8 +788,9 @@ static void put_pi_state(struct futex_pi_state *pi_state)*/ if (pi_state->owner) {struct task_struct *owner; +unsigned long flags; -raw_spin_lock_irq (&pi_state->pi_mutex.wait_lock); +raw_spin_lock_irqsave (&pi_state->pi_mutex.wait_lock, flags); owner = pi_state->owner;if (owner) {raw_spin_lock (&owner->pi_lock);@@ -797,7 +798,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)raw_spin_unlock (&owner->pi_lock); }rt_mutex_proxy_unlock (&pi_state->pi_mutex, owner); -raw_spin_unlock_irq (&pi_state->pi_mutex.wait_lock); +raw_spin_unlock_irqrestore (&pi_state->pi_mutex.wait_lock, flags); }if (current->pi_state_cache) {Signature · 1 line
2.28.0
The following commit has been merged into the locking/urgent branch of tip:
The following commit has been merged into the locking/urgent branch of tip:
Commit-ID: 1e106aa3509b86738769775969822ffc1ec21bf4 Gitweb: https://git.kernel.org/tip/1e106aa3509b86738769775969822ffc1ec21bf4 Author: Dan Carpenter <[email protected]> AuthorDate: Fri, 06 Nov 2020 11:52:05 +03:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Mon, 09 Nov 2020 14:30:30 +01:00
futex: Don't enable IRQs unconditionally in put_pi_state()
The exit_pi_state_list() function calls put_pi_state() with IRQs disabled and is not expecting that IRQs will be enabled inside the function.
Use the _irqsave() variant so that IRQs are restored to the original state instead of being enabled unconditionally.
--- kernel/futex.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/futex.c +3 -2
@@ -788,8 +788,9 @@ static void put_pi_state(struct futex_pi_state *pi_state)*/ if (pi_state->owner) {struct task_struct *owner; +unsigned long flags; -raw_spin_lock_irq (&pi_state->pi_mutex.wait_lock); +raw_spin_lock_irqsave (&pi_state->pi_mutex.wait_lock, flags); owner = pi_state->owner;if (owner) {raw_spin_lock (&owner->pi_lock);
@@ -797,7 +798,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)raw_spin_unlock (&owner->pi_lock); }rt_mutex_proxy_unlock (&pi_state->pi_mutex, owner); -raw_spin_unlock_irq (&pi_state->pi_mutex.wait_lock); +raw_spin_unlock_irqrestore (&pi_state->pi_mutex.wait_lock, flags); }if (current->pi_state_cache) {