| From stable-bounces@linux.kernel.org Wed Aug 13 20:55:31 2008 |
| From: Sven Wegener <sven.wegener@stealer.net> |
| Date: Thu, 14 Aug 2008 03:55:22 GMT |
| Subject: ipvs: Fix possible deadlock in estimator code |
| To: jejb@kernel.org, stable@kernel.org |
| Message-ID: <200808140355.m7E3tMD6011966@hera.kernel.org> |
| |
| From: Sven Wegener <sven.wegener@stealer.net> |
| |
| commit 8ab19ea36c5c5340ff598e4d15fc084eb65671dc upstream |
| |
| There is a slight chance for a deadlock in the estimator code. We can't call |
| del_timer_sync() while holding our lock, as the timer might be active and |
| spinning for the lock on another cpu. Work around this issue by using |
| try_to_del_timer_sync() and releasing the lock. We could actually delete the |
| timer outside of our lock, as the add and kill functions are only every called |
| from userspace via [gs]etsockopt() and are serialized by a mutex, but better |
| make this explicit. |
| |
| Signed-off-by: Sven Wegener <sven.wegener@stealer.net> |
| Acked-by: Simon Horman <horms@verge.net.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| net/ipv4/ipvs/ip_vs_est.c | 7 +++++-- |
| 1 file changed, 5 insertions(+), 2 deletions(-) |
| |
| --- a/net/ipv4/ipvs/ip_vs_est.c |
| +++ b/net/ipv4/ipvs/ip_vs_est.c |
| @@ -172,8 +172,11 @@ void ip_vs_kill_estimator(struct ip_vs_s |
| kfree(est); |
| killed++; |
| } |
| - if (killed && est_list == NULL) |
| - del_timer_sync(&est_timer); |
| + while (killed && !est_list && try_to_del_timer_sync(&est_timer) < 0) { |
| + write_unlock_bh(&est_lock); |
| + cpu_relax(); |
| + write_lock_bh(&est_lock); |
| + } |
| write_unlock_bh(&est_lock); |
| } |
| |