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
This commit is contained in:
Linus Torvalds 2016-03-02 09:15:21 -08:00
Родитель 39680f50ae 9589995e46
Коммит 12f1d7e493
4 изменённых файлов: 36 добавлений и 22 удалений

Просмотреть файл

@ -1013,7 +1013,6 @@ const struct file_operations cifs_file_strict_ops = {
.llseek = cifs_llseek, .llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl, .unlocked_ioctl = cifs_ioctl,
.clone_file_range = cifs_clone_file_range, .clone_file_range = cifs_clone_file_range,
.clone_file_range = cifs_clone_file_range,
.setlease = cifs_setlease, .setlease = cifs_setlease,
.fallocate = cifs_fallocate, .fallocate = cifs_fallocate,
}; };

Просмотреть файл

@ -31,19 +31,15 @@
* so that it will fit. We use hash_64 to convert the value to 31 bits, and * so that it will fit. We use hash_64 to convert the value to 31 bits, and
* then add 1, to ensure that we don't end up with a 0 as the value. * then add 1, to ensure that we don't end up with a 0 as the value.
*/ */
#if BITS_PER_LONG == 64
static inline ino_t static inline ino_t
cifs_uniqueid_to_ino_t(u64 fileid) cifs_uniqueid_to_ino_t(u64 fileid)
{ {
if ((sizeof(ino_t)) < (sizeof(u64)))
return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
return (ino_t)fileid; return (ino_t)fileid;
} }
#else
static inline ino_t
cifs_uniqueid_to_ino_t(u64 fileid)
{
return (ino_t)hash_64(fileid, (sizeof(ino_t) * 8) - 1) + 1;
}
#endif
extern struct file_system_type cifs_fs_type; extern struct file_system_type cifs_fs_type;
extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops;

Просмотреть файл

@ -1396,11 +1396,10 @@ openRetry:
* current bigbuf. * current bigbuf.
*/ */
static int static int
cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) discard_remaining_data(struct TCP_Server_Info *server)
{ {
unsigned int rfclen = get_rfc1002_length(server->smallbuf); unsigned int rfclen = get_rfc1002_length(server->smallbuf);
int remaining = rfclen + 4 - server->total_read; int remaining = rfclen + 4 - server->total_read;
struct cifs_readdata *rdata = mid->callback_data;
while (remaining > 0) { while (remaining > 0) {
int length; int length;
@ -1414,10 +1413,20 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
remaining -= length; remaining -= length;
} }
dequeue_mid(mid, rdata->result);
return 0; return 0;
} }
static int
cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{
int length;
struct cifs_readdata *rdata = mid->callback_data;
length = discard_remaining_data(server);
dequeue_mid(mid, rdata->result);
return length;
}
int int
cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
{ {
@ -1446,6 +1455,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return length; return length;
server->total_read += length; server->total_read += length;
if (server->ops->is_status_pending &&
server->ops->is_status_pending(buf, server, 0)) {
discard_remaining_data(server);
return -1;
}
/* Was the SMB read successful? */ /* Was the SMB read successful? */
rdata->result = server->ops->map_error(buf, false); rdata->result = server->ops->map_error(buf, false);
if (rdata->result != 0) { if (rdata->result != 0) {

Просмотреть файл

@ -1106,21 +1106,25 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
{ {
char *data_offset; char *data_offset;
struct create_context *cc; struct create_context *cc;
unsigned int next = 0; unsigned int next;
unsigned int remaining;
char *name; char *name;
data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset); data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
remaining = le32_to_cpu(rsp->CreateContextsLength);
cc = (struct create_context *)data_offset; cc = (struct create_context *)data_offset;
do { while (remaining >= sizeof(struct create_context)) {
cc = (struct create_context *)((char *)cc + next);
name = le16_to_cpu(cc->NameOffset) + (char *)cc; name = le16_to_cpu(cc->NameOffset) + (char *)cc;
if (le16_to_cpu(cc->NameLength) != 4 || if (le16_to_cpu(cc->NameLength) == 4 &&
strncmp(name, "RqLs", 4)) { strncmp(name, "RqLs", 4) == 0)
next = le32_to_cpu(cc->Next); return server->ops->parse_lease_buf(cc, epoch);
continue;
} next = le32_to_cpu(cc->Next);
return server->ops->parse_lease_buf(cc, epoch); if (!next)
} while (next != 0); break;
remaining -= next;
cc = (struct create_context *)((char *)cc + next);
}
return 0; return 0;
} }