Commit c78beed9 authored by Bart Van Assche's avatar Bart Van Assche Committed by Luis Henriques

libfc: Fix fc_exch_recv_req() error path

commit f6979ade upstream.

Due to patch "libfc: Do not invoke the response handler after
fc_exch_done()" (commit ID 7030fd62) the lport_recv() call
in fc_exch_recv_req() is passed a dangling pointer. Avoid this
by moving the fc_frame_free() call from fc_invoke_resp() to its
callers. This patch fixes the following crash:

general protection fault: 0000 [#3] PREEMPT SMP
RIP: fc_lport_recv_req+0x72/0x280 [libfc]
Call Trace:
 fc_exch_recv+0x642/0xde0 [libfc]
 fcoe_percpu_receive_thread+0x46a/0x5ed [fcoe]
 kthread+0x10a/0x120
 ret_from_fork+0x42/0x70
Signed-off-by: default avatarBart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: default avatarVasu Dev <vasu.dev@intel.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 77d9524f
...@@ -733,8 +733,6 @@ static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp, ...@@ -733,8 +733,6 @@ static bool fc_invoke_resp(struct fc_exch *ep, struct fc_seq *sp,
if (resp) { if (resp) {
resp(sp, fp, arg); resp(sp, fp, arg);
res = true; res = true;
} else if (!IS_ERR(fp)) {
fc_frame_free(fp);
} }
spin_lock_bh(&ep->ex_lock); spin_lock_bh(&ep->ex_lock);
...@@ -1596,7 +1594,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) ...@@ -1596,7 +1594,8 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
* If new exch resp handler is valid then call that * If new exch resp handler is valid then call that
* first. * first.
*/ */
fc_invoke_resp(ep, sp, fp); if (!fc_invoke_resp(ep, sp, fp))
fc_frame_free(fp);
fc_exch_release(ep); fc_exch_release(ep);
return; return;
...@@ -1695,7 +1694,8 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) ...@@ -1695,7 +1694,8 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)
fc_exch_hold(ep); fc_exch_hold(ep);
if (!rc) if (!rc)
fc_exch_delete(ep); fc_exch_delete(ep);
fc_invoke_resp(ep, sp, fp); if (!fc_invoke_resp(ep, sp, fp))
fc_frame_free(fp);
if (has_rec) if (has_rec)
fc_exch_timer_set(ep, ep->r_a_tov); fc_exch_timer_set(ep, ep->r_a_tov);
fc_exch_release(ep); fc_exch_release(ep);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment