Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull more CIFS fixes from Steve French: "As promised, here is the remaining set of cifs/smb3 fixes for stable (and a fix for one regression) now that they have had additional review and testing" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: CIFS: Fix SMB3 mount without specifying a security mechanism CIFS: store results of cifs_reopen_file to avoid infinite wait CIFS: remove bad_network_name flag CIFS: reconnect thread reschedule itself CIFS: handle guest access errors to Windows shares CIFS: Fix null pointer deref during read resp processing
This commit is contained in:
commit
5466f4dfce
@ -948,7 +948,6 @@ struct cifs_tcon {
|
|||||||
bool use_persistent:1; /* use persistent instead of durable handles */
|
bool use_persistent:1; /* use persistent instead of durable handles */
|
||||||
#ifdef CONFIG_CIFS_SMB2
|
#ifdef CONFIG_CIFS_SMB2
|
||||||
bool print:1; /* set if connection to printer share */
|
bool print:1; /* set if connection to printer share */
|
||||||
bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */
|
|
||||||
__le32 capabilities;
|
__le32 capabilities;
|
||||||
__u32 share_flags;
|
__u32 share_flags;
|
||||||
__u32 maximal_access;
|
__u32 maximal_access;
|
||||||
|
@ -79,8 +79,7 @@ extern void cifs_delete_mid(struct mid_q_entry *mid);
|
|||||||
extern void cifs_wake_up_task(struct mid_q_entry *mid);
|
extern void cifs_wake_up_task(struct mid_q_entry *mid);
|
||||||
extern int cifs_handle_standard(struct TCP_Server_Info *server,
|
extern int cifs_handle_standard(struct TCP_Server_Info *server,
|
||||||
struct mid_q_entry *mid);
|
struct mid_q_entry *mid);
|
||||||
extern int cifs_discard_remaining_data(struct TCP_Server_Info *server,
|
extern int cifs_discard_remaining_data(struct TCP_Server_Info *server);
|
||||||
char *buf);
|
|
||||||
extern int cifs_call_async(struct TCP_Server_Info *server,
|
extern int cifs_call_async(struct TCP_Server_Info *server,
|
||||||
struct smb_rqst *rqst,
|
struct smb_rqst *rqst,
|
||||||
mid_receive_t *receive, mid_callback_t *callback,
|
mid_receive_t *receive, mid_callback_t *callback,
|
||||||
|
@ -1400,9 +1400,9 @@ openRetry:
|
|||||||
* current bigbuf.
|
* current bigbuf.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
cifs_discard_remaining_data(struct TCP_Server_Info *server, char *buf)
|
cifs_discard_remaining_data(struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
unsigned int rfclen = get_rfc1002_length(buf);
|
unsigned int rfclen = get_rfc1002_length(server->smallbuf);
|
||||||
int remaining = rfclen + 4 - server->total_read;
|
int remaining = rfclen + 4 - server->total_read;
|
||||||
|
|
||||||
while (remaining > 0) {
|
while (remaining > 0) {
|
||||||
@ -1426,8 +1426,10 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|||||||
int length;
|
int length;
|
||||||
struct cifs_readdata *rdata = mid->callback_data;
|
struct cifs_readdata *rdata = mid->callback_data;
|
||||||
|
|
||||||
length = cifs_discard_remaining_data(server, mid->resp_buf);
|
length = cifs_discard_remaining_data(server);
|
||||||
dequeue_mid(mid, rdata->result);
|
dequeue_mid(mid, rdata->result);
|
||||||
|
mid->resp_buf = server->smallbuf;
|
||||||
|
server->smallbuf = NULL;
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1459,7 +1461,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|||||||
|
|
||||||
if (server->ops->is_status_pending &&
|
if (server->ops->is_status_pending &&
|
||||||
server->ops->is_status_pending(buf, server, 0)) {
|
server->ops->is_status_pending(buf, server, 0)) {
|
||||||
cifs_discard_remaining_data(server, buf);
|
cifs_discard_remaining_data(server);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1519,9 +1521,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|||||||
cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
|
cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
|
||||||
rdata->iov[0].iov_base, server->total_read);
|
rdata->iov[0].iov_base, server->total_read);
|
||||||
|
|
||||||
mid->resp_buf = server->smallbuf;
|
|
||||||
server->smallbuf = NULL;
|
|
||||||
|
|
||||||
/* how much data is in the response? */
|
/* how much data is in the response? */
|
||||||
data_len = server->ops->read_data_length(buf);
|
data_len = server->ops->read_data_length(buf);
|
||||||
if (data_offset + data_len > buflen) {
|
if (data_offset + data_len > buflen) {
|
||||||
@ -1544,6 +1543,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|||||||
return cifs_readv_discard(server, mid);
|
return cifs_readv_discard(server, mid);
|
||||||
|
|
||||||
dequeue_mid(mid, false);
|
dequeue_mid(mid, false);
|
||||||
|
mid->resp_buf = server->smallbuf;
|
||||||
|
server->smallbuf = NULL;
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3753,6 +3753,9 @@ try_mount_again:
|
|||||||
if (IS_ERR(tcon)) {
|
if (IS_ERR(tcon)) {
|
||||||
rc = PTR_ERR(tcon);
|
rc = PTR_ERR(tcon);
|
||||||
tcon = NULL;
|
tcon = NULL;
|
||||||
|
if (rc == -EACCES)
|
||||||
|
goto mount_fail_check;
|
||||||
|
|
||||||
goto remote_path_check;
|
goto remote_path_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2597,7 +2597,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
|
|||||||
wdata->credits = credits;
|
wdata->credits = credits;
|
||||||
|
|
||||||
if (!wdata->cfile->invalidHandle ||
|
if (!wdata->cfile->invalidHandle ||
|
||||||
!cifs_reopen_file(wdata->cfile, false))
|
!(rc = cifs_reopen_file(wdata->cfile, false)))
|
||||||
rc = server->ops->async_writev(wdata,
|
rc = server->ops->async_writev(wdata,
|
||||||
cifs_uncached_writedata_release);
|
cifs_uncached_writedata_release);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@ -3022,7 +3022,7 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
|
|||||||
rdata->credits = credits;
|
rdata->credits = credits;
|
||||||
|
|
||||||
if (!rdata->cfile->invalidHandle ||
|
if (!rdata->cfile->invalidHandle ||
|
||||||
!cifs_reopen_file(rdata->cfile, true))
|
!(rc = cifs_reopen_file(rdata->cfile, true)))
|
||||||
rc = server->ops->async_readv(rdata);
|
rc = server->ops->async_readv(rdata);
|
||||||
error:
|
error:
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@ -3617,7 +3617,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!rdata->cfile->invalidHandle ||
|
if (!rdata->cfile->invalidHandle ||
|
||||||
!cifs_reopen_file(rdata->cfile, true))
|
!(rc = cifs_reopen_file(rdata->cfile, true)))
|
||||||
rc = server->ops->async_readv(rdata);
|
rc = server->ops->async_readv(rdata);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
add_credits_and_wake_if(server, rdata->credits, 0);
|
add_credits_and_wake_if(server, rdata->credits, 0);
|
||||||
|
@ -2195,7 +2195,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto free_pages;
|
goto free_pages;
|
||||||
|
|
||||||
rc = cifs_discard_remaining_data(server, buf);
|
rc = cifs_discard_remaining_data(server);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto free_pages;
|
goto free_pages;
|
||||||
|
|
||||||
@ -2221,7 +2221,7 @@ free_pages:
|
|||||||
kfree(pages);
|
kfree(pages);
|
||||||
return rc;
|
return rc;
|
||||||
discard_data:
|
discard_data:
|
||||||
cifs_discard_remaining_data(server, buf);
|
cifs_discard_remaining_data(server);
|
||||||
goto free_pages;
|
goto free_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,8 +562,10 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
|
|||||||
* but for time being this is our only auth choice so doesn't matter.
|
* but for time being this is our only auth choice so doesn't matter.
|
||||||
* We just found a server which sets blob length to zero expecting raw.
|
* We just found a server which sets blob length to zero expecting raw.
|
||||||
*/
|
*/
|
||||||
if (blob_length == 0)
|
if (blob_length == 0) {
|
||||||
cifs_dbg(FYI, "missing security blob on negprot\n");
|
cifs_dbg(FYI, "missing security blob on negprot\n");
|
||||||
|
server->sec_ntlmssp = true;
|
||||||
|
}
|
||||||
|
|
||||||
rc = cifs_enable_signing(server, ses->sign);
|
rc = cifs_enable_signing(server, ses->sign);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1171,9 +1173,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
|||||||
else
|
else
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (tcon && tcon->bad_network_name)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
|
unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
|
||||||
if (unc_path == NULL)
|
if (unc_path == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -1277,8 +1276,6 @@ tcon_exit:
|
|||||||
tcon_error_exit:
|
tcon_error_exit:
|
||||||
if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
|
if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
|
||||||
cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
|
cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
|
||||||
if (tcon)
|
|
||||||
tcon->bad_network_name = true;
|
|
||||||
}
|
}
|
||||||
goto tcon_exit;
|
goto tcon_exit;
|
||||||
}
|
}
|
||||||
@ -2181,6 +2178,9 @@ void smb2_reconnect_server(struct work_struct *work)
|
|||||||
struct cifs_tcon *tcon, *tcon2;
|
struct cifs_tcon *tcon, *tcon2;
|
||||||
struct list_head tmp_list;
|
struct list_head tmp_list;
|
||||||
int tcon_exist = false;
|
int tcon_exist = false;
|
||||||
|
int rc;
|
||||||
|
int resched = false;
|
||||||
|
|
||||||
|
|
||||||
/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
|
/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
|
||||||
mutex_lock(&server->reconnect_mutex);
|
mutex_lock(&server->reconnect_mutex);
|
||||||
@ -2208,13 +2208,18 @@ void smb2_reconnect_server(struct work_struct *work)
|
|||||||
spin_unlock(&cifs_tcp_ses_lock);
|
spin_unlock(&cifs_tcp_ses_lock);
|
||||||
|
|
||||||
list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
|
list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
|
||||||
if (!smb2_reconnect(SMB2_INTERNAL_CMD, tcon))
|
rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon);
|
||||||
|
if (!rc)
|
||||||
cifs_reopen_persistent_handles(tcon);
|
cifs_reopen_persistent_handles(tcon);
|
||||||
|
else
|
||||||
|
resched = true;
|
||||||
list_del_init(&tcon->rlist);
|
list_del_init(&tcon->rlist);
|
||||||
cifs_put_tcon(tcon);
|
cifs_put_tcon(tcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_dbg(FYI, "Reconnecting tcons finished\n");
|
cifs_dbg(FYI, "Reconnecting tcons finished\n");
|
||||||
|
if (resched)
|
||||||
|
queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ);
|
||||||
mutex_unlock(&server->reconnect_mutex);
|
mutex_unlock(&server->reconnect_mutex);
|
||||||
|
|
||||||
/* now we can safely release srv struct */
|
/* now we can safely release srv struct */
|
||||||
|
Loading…
Reference in New Issue
Block a user