aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-03-02 12:15:21 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-02 12:15:21 -0500
commit12f1d7e4932a40100177be5681f1a26f46265217 (patch)
treee8e1795663ae7d227bf4490d2876968fa7ca0c43
parent39680f50ae54cbbb6e72ac38b8329dd3eb9105f4 (diff)
parent9589995e46d89c70c6fa4723c5f3e5ec04c3c3e3 (diff)
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Various small CIFS/SMB3 fixes for stable: Fixes address oops that can occur when accessing Macs with SMB3, and another problem found to Samba when read responses queued (e.g. with gluster under Samba)" * 'for-next' of git://git.samba.org/sfrench/cifs-2.6: CIFS: Fix duplicate line introduced by clone_file_range patch Fix cifs_uniqueid_to_ino_t() function for s390x CIFS: Fix SMB2+ interim response processing for read requests cifs: fix out-of-bounds access in lease parsing
-rw-r--r--fs/cifs/cifsfs.c1
-rw-r--r--fs/cifs/cifsfs.h12
-rw-r--r--fs/cifs/cifssmb.c21
-rw-r--r--fs/cifs/smb2pdu.c24
4 files changed, 36 insertions, 22 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c48ca13673e3..2eea40353e60 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -1013,7 +1013,6 @@ const struct file_operations cifs_file_strict_ops = {
1013 .llseek = cifs_llseek, 1013 .llseek = cifs_llseek,
1014 .unlocked_ioctl = cifs_ioctl, 1014 .unlocked_ioctl = cifs_ioctl,
1015 .clone_file_range = cifs_clone_file_range, 1015 .clone_file_range = cifs_clone_file_range,
1016 .clone_file_range = cifs_clone_file_range,
1017 .setlease = cifs_setlease, 1016 .setlease = cifs_setlease,
1018 .fallocate = cifs_fallocate, 1017 .fallocate = cifs_fallocate,
1019}; 1018};
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 68c4547528c4..83aac8ba50b0 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -31,19 +31,15 @@
31 * so that it will fit. We use hash_64 to convert the value to 31 bits, and 31 * so that it will fit. We use hash_64 to convert the value to 31 bits, and
32 * then add 1, to ensure that we don't end up with a 0 as the value. 32 * then add 1, to ensure that we don't end up with a 0 as the value.
33 */ 33 */
34#if BITS_PER_LONG == 64
35static inline ino_t 34static inline ino_t
36cifs_uniqueid_to_ino_t(u64 fileid) 35cifs_uniqueid_to_ino_t(u64 fileid)
37{ 36{
37 if ((sizeof(ino_t)) < (sizeof(u64)))
38 return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
39
38 return (ino_t)fileid; 40 return (ino_t)fileid;
41
39} 42}
40#else
41static inline ino_t
42cifs_uniqueid_to_ino_t(u64 fileid)
43{
44 return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
45}
46#endif
47 43
48extern struct file_system_type cifs_fs_type; 44extern struct file_system_type cifs_fs_type;
49extern const struct address_space_operations cifs_addr_ops; 45extern const struct address_space_operations cifs_addr_ops;
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 90b4f9f7de66..76fcb50295a3 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1396,11 +1396,10 @@ openRetry:
1396 * current bigbuf. 1396 * current bigbuf.
1397 */ 1397 */
1398static int 1398static int
1399cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1399discard_remaining_data(struct TCP_Server_Info *server)
1400{ 1400{
1401 unsigned int rfclen = get_rfc1002_length(server->smallbuf); 1401 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1402 int remaining = rfclen + 4 - server->total_read; 1402 int remaining = rfclen + 4 - server->total_read;
1403 struct cifs_readdata *rdata = mid->callback_data;
1404 1403
1405 while (remaining > 0) { 1404 while (remaining > 0) {
1406 int length; 1405 int length;
@@ -1414,10 +1413,20 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1414 remaining -= length; 1413 remaining -= length;
1415 } 1414 }
1416 1415
1417 dequeue_mid(mid, rdata->result);
1418 return 0; 1416 return 0;
1419} 1417}
1420 1418
1419static int
1420cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1421{
1422 int length;
1423 struct cifs_readdata *rdata = mid->callback_data;
1424
1425 length = discard_remaining_data(server);
1426 dequeue_mid(mid, rdata->result);
1427 return length;
1428}
1429
1421int 1430int
1422cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1431cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1423{ 1432{
@@ -1446,6 +1455,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1446 return length; 1455 return length;
1447 server->total_read += length; 1456 server->total_read += length;
1448 1457
1458 if (server->ops->is_status_pending &&
1459 server->ops->is_status_pending(buf, server, 0)) {
1460 discard_remaining_data(server);
1461 return -1;
1462 }
1463
1449 /* Was the SMB read successful? */ 1464 /* Was the SMB read successful? */
1450 rdata->result = server->ops->map_error(buf, false); 1465 rdata->result = server->ops->map_error(buf, false);
1451 if (rdata->result != 0) { 1466 if (rdata->result != 0) {
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 10f8d5cf5681..42e1f440eb1e 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1106,21 +1106,25 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
1106{ 1106{
1107 char *data_offset; 1107 char *data_offset;
1108 struct create_context *cc; 1108 struct create_context *cc;
1109 unsigned int next = 0; 1109 unsigned int next;
1110 unsigned int remaining;
1110 char *name; 1111 char *name;
1111 1112
1112 data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset); 1113 data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
1114 remaining = le32_to_cpu(rsp->CreateContextsLength);
1113 cc = (struct create_context *)data_offset; 1115 cc = (struct create_context *)data_offset;
1114 do { 1116 while (remaining >= sizeof(struct create_context)) {
1115 cc = (struct create_context *)((char *)cc + next);
1116 name = le16_to_cpu(cc->NameOffset) + (char *)cc; 1117 name = le16_to_cpu(cc->NameOffset) + (char *)cc;
1117 if (le16_to_cpu(cc->NameLength) != 4 || 1118 if (le16_to_cpu(cc->NameLength) == 4 &&
1118 strncmp(name, "RqLs", 4)) { 1119 strncmp(name, "RqLs", 4) == 0)
1119 next = le32_to_cpu(cc->Next); 1120 return server->ops->parse_lease_buf(cc, epoch);
1120 continue; 1121
1121 } 1122 next = le32_to_cpu(cc->Next);
1122 return server->ops->parse_lease_buf(cc, epoch); 1123 if (!next)
1123 } while (next != 0); 1124 break;
1125 remaining -= next;
1126 cc = (struct create_context *)((char *)cc + next);
1127 }
1124 1128
1125 return 0; 1129 return 0;
1126} 1130}