diff options
author | Krishna Kumar <krkumar2@in.ibm.com> | 2006-11-08 23:00:34 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-11-29 18:33:07 -0500 |
commit | 33ba0fa9f315ce32fbb86fa671c131f5355b52a1 (patch) | |
tree | 3b6bd7f9efe82fe4e7298497c312b9ee71f4911c /drivers/infiniband | |
parent | e54f81889cd5228e7087637c377d76301c7c5663 (diff) |
RDMA/iwcm: Fix memory corruption bug in cm_work_handler()
Possible memory corruption scenario: after putting the work entry back
on the work_free_list, we call process_event() which dereferences
work->event, which could have been modified to another value
meanwhile.
Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
Acked-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/iwcm.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 2bbcfa5c6e27..22d498c9a68b 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c | |||
@@ -829,7 +829,8 @@ static int process_event(struct iwcm_id_private *cm_id_priv, | |||
829 | */ | 829 | */ |
830 | static void cm_work_handler(void *arg) | 830 | static void cm_work_handler(void *arg) |
831 | { | 831 | { |
832 | struct iwcm_work *work = arg, lwork; | 832 | struct iwcm_work *work = arg; |
833 | struct iw_cm_event levent; | ||
833 | struct iwcm_id_private *cm_id_priv = work->cm_id; | 834 | struct iwcm_id_private *cm_id_priv = work->cm_id; |
834 | unsigned long flags; | 835 | unsigned long flags; |
835 | int empty; | 836 | int empty; |
@@ -842,11 +843,11 @@ static void cm_work_handler(void *arg) | |||
842 | struct iwcm_work, list); | 843 | struct iwcm_work, list); |
843 | list_del_init(&work->list); | 844 | list_del_init(&work->list); |
844 | empty = list_empty(&cm_id_priv->work_list); | 845 | empty = list_empty(&cm_id_priv->work_list); |
845 | lwork = *work; | 846 | levent = work->event; |
846 | put_work(work); | 847 | put_work(work); |
847 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); | 848 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); |
848 | 849 | ||
849 | ret = process_event(cm_id_priv, &work->event); | 850 | ret = process_event(cm_id_priv, &levent); |
850 | if (ret) { | 851 | if (ret) { |
851 | set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags); | 852 | set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags); |
852 | destroy_cm_id(&cm_id_priv->id); | 853 | destroy_cm_id(&cm_id_priv->id); |