Commit 33640d71 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.0-rc4-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb3 fixes from Steve French:
 "SMB3 fixes, some from this week's SMB3 test evemt, 5 for stable and a
  particularly important one for queryxattr (see xfstests 70 and 117)"

* tag '5.0-rc4-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update internal module version number
  CIFS: fix use-after-free of the lease keys
  CIFS: Do not consider -ENODATA as stat failure for reads
  CIFS: Do not count -ENODATA as failure for query directory
  CIFS: Fix trace command logging for SMB2 reads and writes
  CIFS: Fix possible oops and memory leaks in async IO
  cifs: limit amount of data we request for xattrs to CIFSMaxBufSize
  cifs: fix computation for MAX_SMB2_HDR_SIZE
parents b7bd29b5 b9b9378b
...@@ -150,5 +150,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); ...@@ -150,5 +150,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops; extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */ #endif /* CONFIG_CIFS_NFSD_EXPORT */
#define CIFS_VERSION "2.16" #define CIFS_VERSION "2.17"
#endif /* _CIFSFS_H */ #endif /* _CIFSFS_H */
...@@ -2696,6 +2696,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, ...@@ -2696,6 +2696,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
rc = cifs_write_allocate_pages(wdata->pages, nr_pages); rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
if (rc) { if (rc) {
kvfree(wdata->pages);
kfree(wdata); kfree(wdata);
add_credits_and_wake_if(server, credits, 0); add_credits_and_wake_if(server, credits, 0);
break; break;
...@@ -2707,6 +2708,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, ...@@ -2707,6 +2708,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
if (rc) { if (rc) {
for (i = 0; i < nr_pages; i++) for (i = 0; i < nr_pages; i++)
put_page(wdata->pages[i]); put_page(wdata->pages[i]);
kvfree(wdata->pages);
kfree(wdata); kfree(wdata);
add_credits_and_wake_if(server, credits, 0); add_credits_and_wake_if(server, credits, 0);
break; break;
...@@ -3386,8 +3388,12 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, ...@@ -3386,8 +3388,12 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
} }
rc = cifs_read_allocate_pages(rdata, npages); rc = cifs_read_allocate_pages(rdata, npages);
if (rc) if (rc) {
goto error; kvfree(rdata->pages);
kfree(rdata);
add_credits_and_wake_if(server, credits, 0);
break;
}
rdata->tailsz = PAGE_SIZE; rdata->tailsz = PAGE_SIZE;
} }
...@@ -3407,7 +3413,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, ...@@ -3407,7 +3413,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
if (!rdata->cfile->invalidHandle || if (!rdata->cfile->invalidHandle ||
!(rc = 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:
if (rc) { if (rc) {
add_credits_and_wake_if(server, rdata->credits, 0); add_credits_and_wake_if(server, rdata->credits, 0);
kref_put(&rdata->refcount, kref_put(&rdata->refcount,
......
...@@ -866,7 +866,9 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -866,7 +866,9 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
FILE_READ_EA, FILE_READ_EA,
FILE_FULL_EA_INFORMATION, FILE_FULL_EA_INFORMATION,
SMB2_O_INFO_FILE, SMB2_O_INFO_FILE,
SMB2_MAX_EA_BUF, CIFSMaxBufSize -
MAX_SMB2_CREATE_RESPONSE_SIZE -
MAX_SMB2_CLOSE_RESPONSE_SIZE,
&rsp_iov, &buftype, cifs_sb); &rsp_iov, &buftype, cifs_sb);
if (rc) { if (rc) {
/* /*
......
...@@ -3241,8 +3241,17 @@ smb2_readv_callback(struct mid_q_entry *mid) ...@@ -3241,8 +3241,17 @@ smb2_readv_callback(struct mid_q_entry *mid)
rdata->mr = NULL; rdata->mr = NULL;
} }
#endif #endif
if (rdata->result) if (rdata->result && rdata->result != -ENODATA) {
cifs_stats_fail_inc(tcon, SMB2_READ_HE); cifs_stats_fail_inc(tcon, SMB2_READ_HE);
trace_smb3_read_err(0 /* xid */,
rdata->cfile->fid.persistent_fid,
tcon->tid, tcon->ses->Suid, rdata->offset,
rdata->bytes, rdata->result);
} else
trace_smb3_read_done(0 /* xid */,
rdata->cfile->fid.persistent_fid,
tcon->tid, tcon->ses->Suid,
rdata->offset, rdata->got_bytes);
queue_work(cifsiod_wq, &rdata->work); queue_work(cifsiod_wq, &rdata->work);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
...@@ -3317,13 +3326,11 @@ smb2_async_readv(struct cifs_readdata *rdata) ...@@ -3317,13 +3326,11 @@ smb2_async_readv(struct cifs_readdata *rdata)
if (rc) { if (rc) {
kref_put(&rdata->refcount, cifs_readdata_release); kref_put(&rdata->refcount, cifs_readdata_release);
cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE); cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
trace_smb3_read_err(rc, 0 /* xid */, io_parms.persistent_fid, trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
io_parms.tcon->tid, io_parms.tcon->ses->Suid, io_parms.tcon->tid,
io_parms.offset, io_parms.length); io_parms.tcon->ses->Suid,
} else io_parms.offset, io_parms.length, rc);
trace_smb3_read_done(0 /* xid */, io_parms.persistent_fid, }
io_parms.tcon->tid, io_parms.tcon->ses->Suid,
io_parms.offset, io_parms.length);
cifs_small_buf_release(buf); cifs_small_buf_release(buf);
return rc; return rc;
...@@ -3367,10 +3374,11 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, ...@@ -3367,10 +3374,11 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
if (rc != -ENODATA) { if (rc != -ENODATA) {
cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE); cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
cifs_dbg(VFS, "Send error in read = %d\n", rc); cifs_dbg(VFS, "Send error in read = %d\n", rc);
} trace_smb3_read_err(xid, req->PersistentFileId,
trace_smb3_read_err(rc, xid, req->PersistentFileId,
io_parms->tcon->tid, ses->Suid, io_parms->tcon->tid, ses->Suid,
io_parms->offset, io_parms->length); io_parms->offset, io_parms->length,
rc);
}
free_rsp_buf(resp_buftype, rsp_iov.iov_base); free_rsp_buf(resp_buftype, rsp_iov.iov_base);
return rc == -ENODATA ? 0 : rc; return rc == -ENODATA ? 0 : rc;
} else } else
...@@ -3459,8 +3467,17 @@ smb2_writev_callback(struct mid_q_entry *mid) ...@@ -3459,8 +3467,17 @@ smb2_writev_callback(struct mid_q_entry *mid)
wdata->mr = NULL; wdata->mr = NULL;
} }
#endif #endif
if (wdata->result) if (wdata->result) {
cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
trace_smb3_write_err(0 /* no xid */,
wdata->cfile->fid.persistent_fid,
tcon->tid, tcon->ses->Suid, wdata->offset,
wdata->bytes, wdata->result);
} else
trace_smb3_write_done(0 /* no xid */,
wdata->cfile->fid.persistent_fid,
tcon->tid, tcon->ses->Suid,
wdata->offset, wdata->bytes);
queue_work(cifsiod_wq, &wdata->work); queue_work(cifsiod_wq, &wdata->work);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
...@@ -3602,10 +3619,7 @@ smb2_async_writev(struct cifs_writedata *wdata, ...@@ -3602,10 +3619,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
wdata->bytes, rc); wdata->bytes, rc);
kref_put(&wdata->refcount, release); kref_put(&wdata->refcount, release);
cifs_stats_fail_inc(tcon, SMB2_WRITE_HE); cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
} else }
trace_smb3_write_done(0 /* no xid */, req->PersistentFileId,
tcon->tid, tcon->ses->Suid, wdata->offset,
wdata->bytes);
async_writev_out: async_writev_out:
cifs_small_buf_release(req); cifs_small_buf_release(req);
...@@ -3831,7 +3845,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3831,7 +3845,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) { rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
srch_inf->endOfSearch = true; srch_inf->endOfSearch = true;
rc = 0; rc = 0;
} } else
cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE); cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
goto qdir_exit; goto qdir_exit;
} }
...@@ -4427,8 +4441,8 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4427,8 +4441,8 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov); rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
cifs_small_buf_release(req); cifs_small_buf_release(req);
please_key_low = (__u64 *)req->LeaseKey; please_key_low = (__u64 *)lease_key;
please_key_high = (__u64 *)(req->LeaseKey+8); please_key_high = (__u64 *)(lease_key+8);
if (rc) { if (rc) {
cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE); cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid, trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,
......
...@@ -84,8 +84,9 @@ ...@@ -84,8 +84,9 @@
#define NUMBER_OF_SMB2_COMMANDS 0x0013 #define NUMBER_OF_SMB2_COMMANDS 0x0013
/* 4 len + 52 transform hdr + 64 hdr + 56 create rsp */ /* 52 transform hdr + 64 hdr + 88 create rsp */
#define MAX_SMB2_HDR_SIZE 0x00b0 #define SMB2_TRANSFORM_HEADER_SIZE 52
#define MAX_SMB2_HDR_SIZE 204
#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
#define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd) #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
...@@ -648,6 +649,13 @@ struct smb2_create_req { ...@@ -648,6 +649,13 @@ struct smb2_create_req {
__u8 Buffer[0]; __u8 Buffer[0];
} __packed; } __packed;
/*
* Maximum size of a SMB2_CREATE response is 64 (smb2 header) +
* 88 (fixed part of create response) + 520 (path) + 150 (contexts) +
* 2 bytes of padding.
*/
#define MAX_SMB2_CREATE_RESPONSE_SIZE 824
struct smb2_create_rsp { struct smb2_create_rsp {
struct smb2_sync_hdr sync_hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* Must be 89 */ __le16 StructureSize; /* Must be 89 */
...@@ -996,6 +1004,11 @@ struct smb2_close_req { ...@@ -996,6 +1004,11 @@ struct smb2_close_req {
__u64 VolatileFileId; /* opaque endianness */ __u64 VolatileFileId; /* opaque endianness */
} __packed; } __packed;
/*
* Maximum size of a SMB2_CLOSE response is 64 (smb2 header) + 60 (data)
*/
#define MAX_SMB2_CLOSE_RESPONSE_SIZE 124
struct smb2_close_rsp { struct smb2_close_rsp {
struct smb2_sync_hdr sync_hdr; struct smb2_sync_hdr sync_hdr;
__le16 StructureSize; /* 60 */ __le16 StructureSize; /* 60 */
...@@ -1398,8 +1411,6 @@ struct smb2_file_link_info { /* encoding of request for level 11 */ ...@@ -1398,8 +1411,6 @@ struct smb2_file_link_info { /* encoding of request for level 11 */
char FileName[0]; /* Name to be assigned to new link */ char FileName[0]; /* Name to be assigned to new link */
} __packed; /* level 11 Set */ } __packed; /* level 11 Set */
#define SMB2_MAX_EA_BUF 65536
struct smb2_file_full_ea_info { /* encoding of response for level 15 */ struct smb2_file_full_ea_info { /* encoding of response for level 15 */
__le32 next_entry_offset; __le32 next_entry_offset;
__u8 flags; __u8 flags;
......
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