From 57c7d01d2fef086cccb3650a7dfeb5004bbee0fd Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mon, 5 Oct 2015 08:19:05 -0400 Subject: [PATCH] Add patch to fix soft lockups in network stack (rhbz 1266691) --- ...ntial-deadlock-in-reqsk_queue_unlink.patch | 40 ++++++++++++ inet-fix-race-in-reqsk_queue_unlink.patch | 63 +++++++++++++++++++ kernel.spec | 11 +++- sources | 1 - 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 inet-fix-potential-deadlock-in-reqsk_queue_unlink.patch create mode 100644 inet-fix-race-in-reqsk_queue_unlink.patch diff --git a/inet-fix-potential-deadlock-in-reqsk_queue_unlink.patch b/inet-fix-potential-deadlock-in-reqsk_queue_unlink.patch new file mode 100644 index 000000000..b6c9f34dc --- /dev/null +++ b/inet-fix-potential-deadlock-in-reqsk_queue_unlink.patch @@ -0,0 +1,40 @@ +From 05676fe53c9f26fe703c57b14bdd0807e23cc33b Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 13 Aug 2015 15:44:51 -0700 +Subject: [PATCH 1/2] inet: fix potential deadlock in reqsk_queue_unlink() + +When replacing del_timer() with del_timer_sync(), I introduced +a deadlock condition : + +reqsk_queue_unlink() is called from inet_csk_reqsk_queue_drop() + +inet_csk_reqsk_queue_drop() can be called from many contexts, +one being the timer handler itself (reqsk_timer_handler()). + +In this case, del_timer_sync() loops forever. + +Simple fix is to test if timer is pending. + +Fixes: 2235f2ac75fd ("inet: fix races with reqsk timers") +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +--- + net/ipv4/inet_connection_sock.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index b27fc401c6a9..e664706b350c 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -584,7 +584,7 @@ static bool reqsk_queue_unlink(struct request_sock_queue *queue, + } + + spin_unlock(&queue->syn_wait_lock); +- if (del_timer_sync(&req->rsk_timer)) ++ if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer)) + reqsk_put(req); + return found; + } +-- +2.4.3 + diff --git a/inet-fix-race-in-reqsk_queue_unlink.patch b/inet-fix-race-in-reqsk_queue_unlink.patch new file mode 100644 index 000000000..c5c766990 --- /dev/null +++ b/inet-fix-race-in-reqsk_queue_unlink.patch @@ -0,0 +1,63 @@ +From 8f6a05588928ef61e751ca3cb008b9847fb6b83d Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 1 Oct 2015 05:39:26 -0700 +Subject: [PATCH] inet: fix race in reqsk_queue_unlink() + +reqsk_timer_handler() tests if icsk_accept_queue.listen_opt +is NULL at its beginning. + +By the time it calls inet_csk_reqsk_queue_drop() and +reqsk_queue_unlink(), listener might have been closed and +inet_csk_listen_stop() had called reqsk_queue_yank_acceptq() +which sets icsk_accept_queue.listen_opt to NULL + +We therefore need to correctly check listen_opt being NULL +after holding syn_wait_lock for proper synchronization. + +Fixes: fa76ce7328b2 ("inet: get rid of central tcp/dccp listener timer") +Fixes: b357a364c57c ("inet: fix possible panic in reqsk_queue_unlink()") +Signed-off-by: Eric Dumazet +Cc: Yuchung Cheng +--- + net/ipv4/inet_connection_sock.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index e664706b350c..37c8b45af44b 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -568,21 +568,22 @@ EXPORT_SYMBOL(inet_rtx_syn_ack); + static bool reqsk_queue_unlink(struct request_sock_queue *queue, + struct request_sock *req) + { +- struct listen_sock *lopt = queue->listen_opt; + struct request_sock **prev; ++ struct listen_sock *lopt; + bool found = false; + + spin_lock(&queue->syn_wait_lock); +- +- for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL; +- prev = &(*prev)->dl_next) { +- if (*prev == req) { +- *prev = req->dl_next; +- found = true; +- break; ++ lopt = queue->listen_opt; ++ if (lopt) { ++ for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL; ++ prev = &(*prev)->dl_next) { ++ if (*prev == req) { ++ *prev = req->dl_next; ++ found = true; ++ break; ++ } + } + } +- + spin_unlock(&queue->syn_wait_lock); + if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer)) + reqsk_put(req); +-- +2.4.3 + diff --git a/kernel.spec b/kernel.spec index 0e37fccd5..499ccd2f3 100644 --- a/kernel.spec +++ b/kernel.spec @@ -666,6 +666,10 @@ Patch529: vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch #CVE-2015-7613 rhbz 1268270 1268273 Patch532: Initialize-msg-shm-IPC-objects-before-doing-ipc_addi.patch +#rhbz 1266691 +Patch534: inet-fix-potential-deadlock-in-reqsk_queue_unlink.patch +Patch535: inet-fix-race-in-reqsk_queue_unlink.patch + # END OF PATCH DEFINITIONS %endif @@ -1438,6 +1442,10 @@ ApplyPatch vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch #CVE-2015-7613 rhbz 1268270 1268273 ApplyPatch Initialize-msg-shm-IPC-objects-before-doing-ipc_addi.patch +#rhbz 1266691 +ApplyPatch inet-fix-potential-deadlock-in-reqsk_queue_unlink.patch +ApplyPatch inet-fix-race-in-reqsk_queue_unlink.patch + # END OF PATCH APPLICATIONS %endif @@ -2297,8 +2305,9 @@ fi # ||----w | # || || %changelog -* Mon Oct 05 2015 Josh Boyer +* Mon Oct 05 2015 Josh Boyer - 4.1.10-100 - Linxu v4.1.10 +- Add patch to fix soft lockups in network stack (rhbz 1266691) * Fri Oct 02 2015 Josh Boyer - CVE-2015-7613 Unauthorized access to IPC via SysV shm (rhbz 1268270 1268273) diff --git a/sources b/sources index 6ca2dde98..b5be23250 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ fe9dc0f6729f36400ea81aa41d614c37 linux-4.1.tar.xz 5b4d0e18c713a479a7b4c1aa53a7432b perf-man-4.1.tar.gz -8e94d47fb46f0fc5962c65dd1ed0e79c patch-4.1.9.xz 599cb082ef44d8fb76ad8fd49d1b50fc patch-4.1.10.xz