--- /dev/null
+From 511c54a2f69195b28afb9dd119f03787b1625bb4 Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Sat, 8 Jul 2017 14:32:00 -0700
+Subject: CIFS: Reconnect expired SMB sessions
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit 511c54a2f69195b28afb9dd119f03787b1625bb4 upstream.
+
+According to the MS-SMB2 spec (3.2.5.1.6) once the client receives
+STATUS_NETWORK_SESSION_EXPIRED error code from a server it should
+reconnect the current SMB session. Currently the client doesn't do
+that. This can result in subsequent client requests failing by
+the server. The patch adds an additional logic to the demultiplex
+thread to identify expired sessions and reconnect them.
+
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ fs/cifs/cifsglob.h | 2 ++
+ fs/cifs/cifssmb.c | 7 +++++++
+ fs/cifs/connect.c | 7 +++++++
+ fs/cifs/smb2ops.c | 15 +++++++++++++++
+ 4 files changed, 31 insertions(+)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -347,6 +347,8 @@ struct smb_version_operations {
+ unsigned int (*calc_smb_size)(void *);
+ /* check for STATUS_PENDING and process it in a positive case */
+ bool (*is_status_pending)(char *, struct TCP_Server_Info *, int);
++ /* check for STATUS_NETWORK_SESSION_EXPIRED */
++ bool (*is_session_expired)(char *);
+ /* send oplock break response */
+ int (*oplock_response)(struct cifs_tcon *, struct cifs_fid *,
+ struct cifsInodeInfo *);
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -1458,6 +1458,13 @@ cifs_readv_receive(struct TCP_Server_Inf
+ return length;
+ server->total_read += length;
+
++ if (server->ops->is_session_expired &&
++ server->ops->is_session_expired(buf)) {
++ cifs_reconnect(server);
++ wake_up(&server->response_q);
++ return -1;
++ }
++
+ if (server->ops->is_status_pending &&
+ server->ops->is_status_pending(buf, server, 0)) {
+ discard_remaining_data(server);
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -839,6 +839,13 @@ standard_receive3(struct TCP_Server_Info
+ cifs_dump_mem("Bad SMB: ", buf,
+ min_t(unsigned int, server->total_read, 48));
+
++ if (server->ops->is_session_expired &&
++ server->ops->is_session_expired(buf)) {
++ cifs_reconnect(server);
++ wake_up(&server->response_q);
++ return -1;
++ }
++
+ if (server->ops->is_status_pending &&
+ server->ops->is_status_pending(buf, server, length))
+ return -1;
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -896,6 +896,18 @@ smb2_is_status_pending(char *buf, struct
+ return true;
+ }
+
++static bool
++smb2_is_session_expired(char *buf)
++{
++ struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
++
++ if (hdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
++ return false;
++
++ cifs_dbg(FYI, "Session expired\n");
++ return true;
++}
++
+ static int
+ smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
+ struct cifsInodeInfo *cinode)
+@@ -1424,6 +1436,7 @@ struct smb_version_operations smb20_oper
+ .close_dir = smb2_close_dir,
+ .calc_smb_size = smb2_calc_size,
+ .is_status_pending = smb2_is_status_pending,
++ .is_session_expired = smb2_is_session_expired,
+ .oplock_response = smb2_oplock_response,
+ .queryfs = smb2_queryfs,
+ .mand_lock = smb2_mand_lock,
+@@ -1505,6 +1518,7 @@ struct smb_version_operations smb21_oper
+ .close_dir = smb2_close_dir,
+ .calc_smb_size = smb2_calc_size,
+ .is_status_pending = smb2_is_status_pending,
++ .is_session_expired = smb2_is_session_expired,
+ .oplock_response = smb2_oplock_response,
+ .queryfs = smb2_queryfs,
+ .mand_lock = smb2_mand_lock,
+@@ -1587,6 +1601,7 @@ struct smb_version_operations smb30_oper
+ .close_dir = smb2_close_dir,
+ .calc_smb_size = smb2_calc_size,
+ .is_status_pending = smb2_is_status_pending,
++ .is_session_expired = smb2_is_session_expired,
+ .oplock_response = smb2_oplock_response,
+ .queryfs = smb2_queryfs,
+ .mand_lock = smb2_mand_lock,
--- /dev/null
+From 1bd8d6cd3e413d64e543ec3e69ff43e75a1cf1ea Mon Sep 17 00:00:00 2001
+From: "Darrick J. Wong" <darrick.wong@oracle.com>
+Date: Thu, 24 Aug 2017 13:22:06 -0400
+Subject: ext4: in ext4_seek_{hole,data}, return -ENXIO for negative offsets
+
+From: Darrick J. Wong <darrick.wong@oracle.com>
+
+commit 1bd8d6cd3e413d64e543ec3e69ff43e75a1cf1ea upstream.
+
+In the ext4 implementations of SEEK_HOLE and SEEK_DATA, make sure we
+return -ENXIO for negative offsets instead of banging around inside
+the extent code and returning -EFSCORRUPTED.
+
+Reported-by: Mateusz S <muttdini@gmail.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/file.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/file.c
++++ b/fs/ext4/file.c
+@@ -399,7 +399,7 @@ static loff_t ext4_seek_data(struct file
+ mutex_lock(&inode->i_mutex);
+
+ isize = i_size_read(inode);
+- if (offset >= isize) {
++ if (offset < 0 || offset >= isize) {
+ mutex_unlock(&inode->i_mutex);
+ return -ENXIO;
+ }
+@@ -472,7 +472,7 @@ static loff_t ext4_seek_hole(struct file
+ mutex_lock(&inode->i_mutex);
+
+ isize = i_size_read(inode);
+- if (offset >= isize) {
++ if (offset < 0 || offset >= isize) {
+ mutex_unlock(&inode->i_mutex);
+ return -ENXIO;
+ }