From 22e5741a09615244870f7730b0f5515e7f5efd2c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 19 Nov 2012 15:30:52 -0800 Subject: [PATCH] 3.0-stable patches added patches: crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch fanotify-fix-missing-break.patch pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch --- ...ue_worker-to-prevent-data-corruption.patch | 53 ++++++ queue-3.0/fanotify-fix-missing-break.patch | 41 +++++ ...unbinding-device-if-parent-in-d3cold.patch | 156 ++++++++++++++++++ queue-3.0/series | 3 + 4 files changed, 253 insertions(+) create mode 100644 queue-3.0/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch create mode 100644 queue-3.0/fanotify-fix-missing-break.patch create mode 100644 queue-3.0/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch diff --git a/queue-3.0/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch b/queue-3.0/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch new file mode 100644 index 00000000000..8151a7aaa69 --- /dev/null +++ b/queue-3.0/crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch @@ -0,0 +1,53 @@ +From 9efade1b3e981f5064f9db9ca971b4dc7557ae42 Mon Sep 17 00:00:00 2001 +From: Jussi Kivilinna +Date: Sun, 21 Oct 2012 20:42:28 +0300 +Subject: crypto: cryptd - disable softirqs in cryptd_queue_worker to prevent data corruption + +From: Jussi Kivilinna + +commit 9efade1b3e981f5064f9db9ca971b4dc7557ae42 upstream. + +cryptd_queue_worker attempts to prevent simultaneous accesses to crypto +workqueue by cryptd_enqueue_request using preempt_disable/preempt_enable. +However cryptd_enqueue_request might be called from softirq context, +so add local_bh_disable/local_bh_enable to prevent data corruption and +panics. + +Bug report at http://marc.info/?l=linux-crypto-vger&m=134858649616319&w=2 + +v2: + - Disable software interrupts instead of hardware interrupts + +Reported-by: Gurucharan Shetty +Signed-off-by: Jussi Kivilinna +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/cryptd.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct w + struct crypto_async_request *req, *backlog; + + cpu_queue = container_of(work, struct cryptd_cpu_queue, work); +- /* Only handle one request at a time to avoid hogging crypto +- * workqueue. preempt_disable/enable is used to prevent +- * being preempted by cryptd_enqueue_request() */ ++ /* ++ * Only handle one request at a time to avoid hogging crypto workqueue. ++ * preempt_disable/enable is used to prevent being preempted by ++ * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent ++ * cryptd_enqueue_request() being accessed from software interrupts. ++ */ ++ local_bh_disable(); + preempt_disable(); + backlog = crypto_get_backlog(&cpu_queue->queue); + req = crypto_dequeue_request(&cpu_queue->queue); + preempt_enable(); ++ local_bh_enable(); + + if (!req) + return; diff --git a/queue-3.0/fanotify-fix-missing-break.patch b/queue-3.0/fanotify-fix-missing-break.patch new file mode 100644 index 00000000000..ff57c4214f8 --- /dev/null +++ b/queue-3.0/fanotify-fix-missing-break.patch @@ -0,0 +1,41 @@ +From 848561d368751a1c0f679b9f045a02944506a801 Mon Sep 17 00:00:00 2001 +From: Eric Paris +Date: Thu, 8 Nov 2012 15:53:37 -0800 +Subject: fanotify: fix missing break + +From: Eric Paris + +commit 848561d368751a1c0f679b9f045a02944506a801 upstream. + +Anders Blomdell noted in 2010 that Fanotify lost events and provided a +test case. Eric Paris confirmed it was a bug and posted a fix to the +list + + https://groups.google.com/forum/?fromgroups=#!topic/linux.kernel/RrJfTfyW2BE + +but never applied it. Repeated attempts over time to actually get him +to apply it have never had a reply from anyone who has raised it + +So apply it anyway + +Signed-off-by: Alan Cox +Reported-by: Anders Blomdell +Cc: Eric Paris +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/notify/fanotify/fanotify.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/notify/fanotify/fanotify.c ++++ b/fs/notify/fanotify/fanotify.c +@@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify + if ((old->path.mnt == new->path.mnt) && + (old->path.dentry == new->path.dentry)) + return true; ++ break; + case (FSNOTIFY_EVENT_NONE): + return true; + default: diff --git a/queue-3.0/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch b/queue-3.0/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch new file mode 100644 index 00000000000..af83b898cbf --- /dev/null +++ b/queue-3.0/pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch @@ -0,0 +1,156 @@ +From 90b5c1d7c45eeb622302680ff96ed30c1a2b6f0e Mon Sep 17 00:00:00 2001 +From: Huang Ying +Date: Wed, 24 Oct 2012 14:54:13 +0800 +Subject: PCI/PM: Fix deadlock when unbinding device if parent in D3cold + +From: Huang Ying + +commit 90b5c1d7c45eeb622302680ff96ed30c1a2b6f0e upstream. + +If a PCI device and its parents are put into D3cold, unbinding the +device will trigger deadlock as follow: + +- driver_unbind + - device_release_driver + - device_lock(dev) <--- previous lock here + - __device_release_driver + - pm_runtime_get_sync + ... + - rpm_resume(dev) + - rpm_resume(dev->parent) + ... + - pci_pm_runtime_resume + ... + - pci_set_power_state + - __pci_start_power_transition + - pci_wakeup_bus(dev->parent->subordinate) + - pci_walk_bus + - device_lock(dev) <--- deadlock here + + +If we do not do device_lock in pci_walk_bus, we can avoid deadlock. +Device_lock in pci_walk_bus is introduced in commit: +d71374dafbba7ec3f67371d3b7e9f6310a588808, corresponding email thread +is: https://lkml.org/lkml/2006/5/26/38. The patch author Zhang Yanmin +said device_lock is added to pci_walk_bus because: + + Some error handling functions call pci_walk_bus. For example, PCIe + aer. Here we lock the device, so the driver wouldn't detach from the + device, as the cb might call driver's callback function. + +So I fixed the deadlock as follows: + +- remove device_lock from pci_walk_bus +- add device_lock into callback if callback will call driver's callback + +I checked pci_walk_bus users one by one, and found only PCIe aer needs +device lock. + +Signed-off-by: Huang Ying +Signed-off-by: Bjorn Helgaas +Acked-by: Rafael J. Wysocki +CC: Zhang Yanmin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/bus.c | 3 --- + drivers/pci/pcie/aer/aerdrv_core.c | 20 ++++++++++++++++---- + 2 files changed, 16 insertions(+), 7 deletions(-) + +--- a/drivers/pci/bus.c ++++ b/drivers/pci/bus.c +@@ -284,10 +284,7 @@ void pci_walk_bus(struct pci_bus *top, i + } else + next = dev->bus_list.next; + +- /* Run device routines with the device locked */ +- device_lock(&dev->dev); + retval = cb(dev, userdata); +- device_unlock(&dev->dev); + if (retval) + break; + } +--- a/drivers/pci/pcie/aer/aerdrv_core.c ++++ b/drivers/pci/pcie/aer/aerdrv_core.c +@@ -243,6 +243,7 @@ static int report_error_detected(struct + struct aer_broadcast_data *result_data; + result_data = (struct aer_broadcast_data *) data; + ++ device_lock(&dev->dev); + dev->error_state = result_data->state; + + if (!dev->driver || +@@ -261,12 +262,14 @@ static int report_error_detected(struct + dev->driver ? + "no AER-aware driver" : "no driver"); + } +- return 0; ++ goto out; + } + + err_handler = dev->driver->err_handler; + vote = err_handler->error_detected(dev, result_data->state); + result_data->result = merge_result(result_data->result, vote); ++out: ++ device_unlock(&dev->dev); + return 0; + } + +@@ -277,14 +280,17 @@ static int report_mmio_enabled(struct pc + struct aer_broadcast_data *result_data; + result_data = (struct aer_broadcast_data *) data; + ++ device_lock(&dev->dev); + if (!dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->mmio_enabled) +- return 0; ++ goto out; + + err_handler = dev->driver->err_handler; + vote = err_handler->mmio_enabled(dev); + result_data->result = merge_result(result_data->result, vote); ++out: ++ device_unlock(&dev->dev); + return 0; + } + +@@ -295,14 +301,17 @@ static int report_slot_reset(struct pci_ + struct aer_broadcast_data *result_data; + result_data = (struct aer_broadcast_data *) data; + ++ device_lock(&dev->dev); + if (!dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->slot_reset) +- return 0; ++ goto out; + + err_handler = dev->driver->err_handler; + vote = err_handler->slot_reset(dev); + result_data->result = merge_result(result_data->result, vote); ++out: ++ device_unlock(&dev->dev); + return 0; + } + +@@ -310,15 +319,18 @@ static int report_resume(struct pci_dev + { + struct pci_error_handlers *err_handler; + ++ device_lock(&dev->dev); + dev->error_state = pci_channel_io_normal; + + if (!dev->driver || + !dev->driver->err_handler || + !dev->driver->err_handler->resume) +- return 0; ++ goto out; + + err_handler = dev->driver->err_handler; + err_handler->resume(dev); ++out: ++ device_unlock(&dev->dev); + return 0; + } + diff --git a/queue-3.0/series b/queue-3.0/series index 32b3a24649b..907518dccf6 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -1 +1,4 @@ mm-bugfix-set-current-reclaim_state-to-null-while-returning-from-kswapd.patch +pci-pm-fix-deadlock-when-unbinding-device-if-parent-in-d3cold.patch +fanotify-fix-missing-break.patch +crypto-cryptd-disable-softirqs-in-cryptd_queue_worker-to-prevent-data-corruption.patch -- 2.47.3