Commit 5fb4e288 authored by Christopher Oo's avatar Christopher Oo Committed by Steve French

cifs: Fix use-after-free on mid_q_entry

With CIFS_DEBUG_2 enabled, additional debug information is tracked inside each
mid_q_entry struct, however cifs_save_when_sent may use the mid_q_entry after it
has been freed from the appropriate callback if the transport layer has very low
latency. Holding the srv_mutex fixes this use-after-free, as cifs_save_when_sent
is called while the srv_mutex is held while the request is sent.
Signed-off-by: default avatarChristopher Oo <t-chriso@microsoft.com>
parent 0a6d0b64
...@@ -696,7 +696,9 @@ cifs_echo_callback(struct mid_q_entry *mid) ...@@ -696,7 +696,9 @@ cifs_echo_callback(struct mid_q_entry *mid)
{ {
struct TCP_Server_Info *server = mid->callback_data; struct TCP_Server_Info *server = mid->callback_data;
mutex_lock(&server->srv_mutex);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
mutex_unlock(&server->srv_mutex);
add_credits(server, 1, CIFS_ECHO_OP); add_credits(server, 1, CIFS_ECHO_OP);
} }
...@@ -1572,7 +1574,9 @@ cifs_readv_callback(struct mid_q_entry *mid) ...@@ -1572,7 +1574,9 @@ cifs_readv_callback(struct mid_q_entry *mid)
} }
queue_work(cifsiod_wq, &rdata->work); queue_work(cifsiod_wq, &rdata->work);
mutex_lock(&server->srv_mutex);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
mutex_unlock(&server->srv_mutex);
add_credits(server, 1, 0); add_credits(server, 1, 0);
} }
...@@ -2032,6 +2036,7 @@ cifs_writev_callback(struct mid_q_entry *mid) ...@@ -2032,6 +2036,7 @@ cifs_writev_callback(struct mid_q_entry *mid)
{ {
struct cifs_writedata *wdata = mid->callback_data; struct cifs_writedata *wdata = mid->callback_data;
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
struct TCP_Server_Info *server = tcon->ses->server;
unsigned int written; unsigned int written;
WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf; WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
...@@ -2068,7 +2073,9 @@ cifs_writev_callback(struct mid_q_entry *mid) ...@@ -2068,7 +2073,9 @@ cifs_writev_callback(struct mid_q_entry *mid)
} }
queue_work(cifsiod_wq, &wdata->work); queue_work(cifsiod_wq, &wdata->work);
mutex_lock(&server->srv_mutex);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
mutex_unlock(&server->srv_mutex);
add_credits(tcon->ses->server, 1, 0); add_credits(tcon->ses->server, 1, 0);
} }
......
...@@ -1626,7 +1626,9 @@ smb2_echo_callback(struct mid_q_entry *mid) ...@@ -1626,7 +1626,9 @@ smb2_echo_callback(struct mid_q_entry *mid)
if (mid->mid_state == MID_RESPONSE_RECEIVED) if (mid->mid_state == MID_RESPONSE_RECEIVED)
credits_received = le16_to_cpu(smb2->hdr.CreditRequest); credits_received = le16_to_cpu(smb2->hdr.CreditRequest);
mutex_lock(&server->srv_mutex);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
mutex_unlock(&server->srv_mutex);
add_credits(server, credits_received, CIFS_ECHO_OP); add_credits(server, credits_received, CIFS_ECHO_OP);
} }
...@@ -1810,7 +1812,9 @@ smb2_readv_callback(struct mid_q_entry *mid) ...@@ -1810,7 +1812,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
cifs_stats_fail_inc(tcon, SMB2_READ_HE); cifs_stats_fail_inc(tcon, SMB2_READ_HE);
queue_work(cifsiod_wq, &rdata->work); queue_work(cifsiod_wq, &rdata->work);
mutex_lock(&server->srv_mutex);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
mutex_unlock(&server->srv_mutex);
add_credits(server, credits_received, 0); add_credits(server, credits_received, 0);
} }
...@@ -1938,6 +1942,7 @@ smb2_writev_callback(struct mid_q_entry *mid) ...@@ -1938,6 +1942,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
{ {
struct cifs_writedata *wdata = mid->callback_data; struct cifs_writedata *wdata = mid->callback_data;
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
struct TCP_Server_Info *server = tcon->ses->server;
unsigned int written; unsigned int written;
struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf; struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
unsigned int credits_received = 1; unsigned int credits_received = 1;
...@@ -1977,7 +1982,9 @@ smb2_writev_callback(struct mid_q_entry *mid) ...@@ -1977,7 +1982,9 @@ smb2_writev_callback(struct mid_q_entry *mid)
cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
queue_work(cifsiod_wq, &wdata->work); queue_work(cifsiod_wq, &wdata->work);
mutex_lock(&server->srv_mutex);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
mutex_unlock(&server->srv_mutex);
add_credits(tcon->ses->server, credits_received, 0); add_credits(tcon->ses->server, credits_received, 0);
} }
......
...@@ -644,7 +644,9 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) ...@@ -644,7 +644,9 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
} }
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
mutex_lock(&server->srv_mutex);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
mutex_unlock(&server->srv_mutex);
return rc; return rc;
} }
......
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