mirror of
https://github.com/torvalds/linux.git
synced 2024-12-03 17:41:22 +00:00
Four smb3 fixes for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAl+9eV4ACgkQiiy9cAdy T1EXOAv+JF6QZiwB6TELiusDLw+6UWpT7CcT1guL+eSrFVYEPIhqF4V4QXY0oA0Y F8jTpHxEx8wdECAPPNGHh/a4E+Y1vV/W8Nv5DkglAwjeXAD2Y84VAp8hH890jnn0 M8I9qdnbfSodRueshpKScRPHbfp4Smlz1BR9R0syk7T7TmCy8aKNwYN1lBy5Nf9f ICMn1F5e9z4nX43NJIwzO+NSPehtLm8ULFZER/pQ+tGDhwXTdFc9HPzfu0ZoYbEO zADjmY4PItVYRINnWBntEBLYcAFeAB0finPTP2kCfXfRDF5cPgElp84F3Uro7se5 bioboePO+bUS0jigIiP3qZ7zTHEdJoICsiJzVGmDZYsawK3MAwamp2EH3axAr4B/ h4LULgN7nCatPW5lMo3/3EPZXVbXVTOYIB2REtqJugK8USQ9+v9SMLNT/qWn0GE5 bzZoZ22wkHEOn4EIxYSCX4tgj9cJ2v9B/0NMpTQLTECKBQi3iV32GxLglvMwZru6 eWKL5tZj =lxdD -----END PGP SIGNATURE----- Merge tag '5.10-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6 Pull cifs fixes from Steve French: "Four smb3 fixes for stable: one fixes a memleak, the other three address a problem found with decryption offload that can cause a use after free" * tag '5.10-rc5-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: smb3: Handle error case during offload read path smb3: Avoid Mid pending list corruption smb3: Call cifs reconnect from demultiplex thread cifs: fix a memleak with modefromsid
This commit is contained in:
commit
127c501a03
@ -1266,6 +1266,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
|||||||
cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
|
cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
|
||||||
} else if (mode_from_special_sid) {
|
} else if (mode_from_special_sid) {
|
||||||
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
|
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
|
||||||
|
kfree(pntsd);
|
||||||
} else {
|
} else {
|
||||||
/* get approximated mode from ACL */
|
/* get approximated mode from ACL */
|
||||||
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
|
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
|
||||||
|
@ -264,7 +264,7 @@ smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct mid_q_entry *
|
static struct mid_q_entry *
|
||||||
smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
|
||||||
{
|
{
|
||||||
struct mid_q_entry *mid;
|
struct mid_q_entry *mid;
|
||||||
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
|
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
|
||||||
@ -281,6 +281,10 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
|||||||
(mid->mid_state == MID_REQUEST_SUBMITTED) &&
|
(mid->mid_state == MID_REQUEST_SUBMITTED) &&
|
||||||
(mid->command == shdr->Command)) {
|
(mid->command == shdr->Command)) {
|
||||||
kref_get(&mid->refcount);
|
kref_get(&mid->refcount);
|
||||||
|
if (dequeue) {
|
||||||
|
list_del_init(&mid->qhead);
|
||||||
|
mid->mid_flags |= MID_DELETED;
|
||||||
|
}
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
return mid;
|
return mid;
|
||||||
}
|
}
|
||||||
@ -289,6 +293,18 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct mid_q_entry *
|
||||||
|
smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
||||||
|
{
|
||||||
|
return __smb2_find_mid(server, buf, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mid_q_entry *
|
||||||
|
smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
|
||||||
|
{
|
||||||
|
return __smb2_find_mid(server, buf, true);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
|
smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
@ -4356,7 +4372,8 @@ init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size,
|
|||||||
static int
|
static int
|
||||||
handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
||||||
char *buf, unsigned int buf_len, struct page **pages,
|
char *buf, unsigned int buf_len, struct page **pages,
|
||||||
unsigned int npages, unsigned int page_data_size)
|
unsigned int npages, unsigned int page_data_size,
|
||||||
|
bool is_offloaded)
|
||||||
{
|
{
|
||||||
unsigned int data_offset;
|
unsigned int data_offset;
|
||||||
unsigned int data_len;
|
unsigned int data_len;
|
||||||
@ -4378,7 +4395,8 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
|
|
||||||
if (server->ops->is_session_expired &&
|
if (server->ops->is_session_expired &&
|
||||||
server->ops->is_session_expired(buf)) {
|
server->ops->is_session_expired(buf)) {
|
||||||
cifs_reconnect(server);
|
if (!is_offloaded)
|
||||||
|
cifs_reconnect(server);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4402,7 +4420,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
cifs_dbg(FYI, "%s: server returned error %d\n",
|
cifs_dbg(FYI, "%s: server returned error %d\n",
|
||||||
__func__, rdata->result);
|
__func__, rdata->result);
|
||||||
/* normal error on read response */
|
/* normal error on read response */
|
||||||
dequeue_mid(mid, false);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_RECEIVED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4426,7 +4447,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
|
cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
|
||||||
__func__, data_offset);
|
__func__, data_offset);
|
||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4442,21 +4466,30 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
|
cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
|
||||||
__func__, data_offset);
|
__func__, data_offset);
|
||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_len > page_data_size - pad_len) {
|
if (data_len > page_data_size - pad_len) {
|
||||||
/* data_len is corrupt -- discard frame */
|
/* data_len is corrupt -- discard frame */
|
||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdata->result = init_read_bvec(pages, npages, page_data_size,
|
rdata->result = init_read_bvec(pages, npages, page_data_size,
|
||||||
cur_off, &bvec);
|
cur_off, &bvec);
|
||||||
if (rdata->result != 0) {
|
if (rdata->result != 0) {
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4471,7 +4504,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
/* read response payload cannot be in both buf and pages */
|
/* read response payload cannot be in both buf and pages */
|
||||||
WARN_ONCE(1, "buf can not contain only a part of read data");
|
WARN_ONCE(1, "buf can not contain only a part of read data");
|
||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4482,7 +4518,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
if (length < 0)
|
if (length < 0)
|
||||||
return length;
|
return length;
|
||||||
|
|
||||||
dequeue_mid(mid, false);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_RECEIVED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, false);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4511,15 +4550,34 @@ static void smb2_decrypt_offload(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dw->server->lstrp = jiffies;
|
dw->server->lstrp = jiffies;
|
||||||
mid = smb2_find_mid(dw->server, dw->buf);
|
mid = smb2_find_dequeue_mid(dw->server, dw->buf);
|
||||||
if (mid == NULL)
|
if (mid == NULL)
|
||||||
cifs_dbg(FYI, "mid not found\n");
|
cifs_dbg(FYI, "mid not found\n");
|
||||||
else {
|
else {
|
||||||
mid->decrypted = true;
|
mid->decrypted = true;
|
||||||
rc = handle_read_data(dw->server, mid, dw->buf,
|
rc = handle_read_data(dw->server, mid, dw->buf,
|
||||||
dw->server->vals->read_rsp_size,
|
dw->server->vals->read_rsp_size,
|
||||||
dw->ppages, dw->npages, dw->len);
|
dw->ppages, dw->npages, dw->len,
|
||||||
mid->callback(mid);
|
true);
|
||||||
|
if (rc >= 0) {
|
||||||
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
|
mid->when_received = jiffies;
|
||||||
|
#endif
|
||||||
|
mid->callback(mid);
|
||||||
|
} else {
|
||||||
|
spin_lock(&GlobalMid_Lock);
|
||||||
|
if (dw->server->tcpStatus == CifsNeedReconnect) {
|
||||||
|
mid->mid_state = MID_RETRY_NEEDED;
|
||||||
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
mid->callback(mid);
|
||||||
|
} else {
|
||||||
|
mid->mid_state = MID_REQUEST_SUBMITTED;
|
||||||
|
mid->mid_flags &= ~(MID_DELETED);
|
||||||
|
list_add_tail(&mid->qhead,
|
||||||
|
&dw->server->pending_mid_q);
|
||||||
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
cifs_mid_q_entry_release(mid);
|
cifs_mid_q_entry_release(mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4622,7 +4680,7 @@ non_offloaded_decrypt:
|
|||||||
(*mid)->decrypted = true;
|
(*mid)->decrypted = true;
|
||||||
rc = handle_read_data(server, *mid, buf,
|
rc = handle_read_data(server, *mid, buf,
|
||||||
server->vals->read_rsp_size,
|
server->vals->read_rsp_size,
|
||||||
pages, npages, len);
|
pages, npages, len, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_pages:
|
free_pages:
|
||||||
@ -4765,7 +4823,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|||||||
char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
|
char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
|
||||||
|
|
||||||
return handle_read_data(server, mid, buf, server->pdu_size,
|
return handle_read_data(server, mid, buf, server->pdu_size,
|
||||||
NULL, 0, 0);
|
NULL, 0, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
Loading…
Reference in New Issue
Block a user