Commit 5466f4df authored by Linus Torvalds's avatar Linus Torvalds

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
parents 82f1faa8 67dbea2c
...@@ -948,7 +948,6 @@ struct cifs_tcon { ...@@ -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); ...@@ -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 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, ...@@ -1400,9 +1400,9 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
* 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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) ...@@ -3753,6 +3753,9 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid) ...@@ -2221,7 +2221,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
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) ...@@ -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, ...@@ -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 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, ...@@ -1277,8 +1276,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
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) ...@@ -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) ...@@ -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 */
......
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