From 810ec653fb3c4f9d74c9be74416c712bb63e9224 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 18 Oct 2012 14:45:33 +0200 Subject: [PATCH] ib_srp: Avoid use-after-free during module unload on pre-2.6.36 kernels Since ib_unregister_client() flushes ib_wq that workqueue must be destroyed after client unregistration instead of before. This patch has been tested on RHEL 6.3 and SLES 11 SP2. Signed-off-by: Bart Van Assche --- ...025-ib_srp-Backport-to-older-kernels.patch | 52 ++++++++++++++----- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/patches/0025-ib_srp-Backport-to-older-kernels.patch b/patches/0025-ib_srp-Backport-to-older-kernels.patch index d070430..50e0644 100644 --- a/patches/0025-ib_srp-Backport-to-older-kernels.patch +++ b/patches/0025-ib_srp-Backport-to-older-kernels.patch @@ -127,32 +127,56 @@ index bcbf22e..d42e9c4 100644 .queuecommand = srp_queuecommand, .eh_abort_handler = srp_abort, .eh_device_reset_handler = srp_reset_device, -@@ -2491,11 +2553,25 @@ static int __init srp_init_module(void) - return ret; +@@ -2468,15 +2530,28 @@ static int __init srp_init_module(void) + indirect_sg_entries = cmd_sg_entries; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) + srp_wq = create_workqueue("srp"); -+ if (IS_ERR(srp_wq)) { -+ ib_unregister_client(&srp_client); -+ ib_sa_unregister_client(&srp_sa_client); -+ class_unregister(&srp_class); -+ srp_release_transport(ib_srp_transport_template); ++ if (IS_ERR(srp_wq)) + return PTR_ERR(srp_wq); -+ } +#endif + - return 0; - } + ib_srp_transport_template = + srp_attach_transport(&ib_srp_transport_functions); +- if (!ib_srp_transport_template) ++ if (!ib_srp_transport_template) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++ destroy_workqueue(srp_wq); ++#endif + return -ENOMEM; ++ } - static void __exit srp_cleanup_module(void) - { + ret = class_register(&srp_class); + if (ret) { + pr_err("couldn't register class infiniband_srp\n"); + srp_release_transport(ib_srp_transport_template); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) -+ destroy_workqueue(srp_wq); ++ destroy_workqueue(srp_wq); +#endif - ib_unregister_client(&srp_client); + return ret; + } + +@@ -2488,6 +2563,9 @@ static int __init srp_init_module(void) + srp_release_transport(ib_srp_transport_template); + ib_sa_unregister_client(&srp_sa_client); + class_unregister(&srp_class); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++ destroy_workqueue(srp_wq); ++#endif + return ret; + } + +@@ -2500,6 +2578,9 @@ static void __exit srp_cleanup_module(void) ib_sa_unregister_client(&srp_sa_client); class_unregister(&srp_class); + srp_release_transport(ib_srp_transport_template); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ++ destroy_workqueue(srp_wq); ++#endif + } + + module_init(srp_init_module); -- 1.7.9.5 -- 2.46.0