Commit 04919afb authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS fixes from Steve French:
 "Five small cifs fixes (includes fixes for: unmount hang, 2 security
  related, symlink, large file writes)"

* 'for-linus' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: ntstatus_to_dos_map[] is not terminated
  cifs: Allow LANMAN auth method for servers supporting unencapsulated authentication methods
  cifs: Fix inability to write files >2GB to SMB2/3 shares
  cifs: Avoid umount hangs with smb2 when server is unresponsive
  do not treat non-symlink reparse points as valid symlinks
parents 83f11a9c 0c26606c
...@@ -120,14 +120,16 @@ cifs_read_super(struct super_block *sb) ...@@ -120,14 +120,16 @@ cifs_read_super(struct super_block *sb)
{ {
struct inode *inode; struct inode *inode;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifs_tcon *tcon;
int rc = 0; int rc = 0;
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
tcon = cifs_sb_master_tcon(cifs_sb);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
sb->s_flags |= MS_POSIXACL; sb->s_flags |= MS_POSIXACL;
if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files)
sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_maxbytes = MAX_LFS_FILESIZE;
else else
sb->s_maxbytes = MAX_NON_LFS; sb->s_maxbytes = MAX_NON_LFS;
...@@ -147,7 +149,7 @@ cifs_read_super(struct super_block *sb) ...@@ -147,7 +149,7 @@ cifs_read_super(struct super_block *sb)
goto out_no_root; goto out_no_root;
} }
if (cifs_sb_master_tcon(cifs_sb)->nocase) if (tcon->nocase)
sb->s_d_op = &cifs_ci_dentry_ops; sb->s_d_op = &cifs_ci_dentry_ops;
else else
sb->s_d_op = &cifs_dentry_ops; sb->s_d_op = &cifs_dentry_ops;
......
...@@ -1491,15 +1491,30 @@ struct file_notify_information { ...@@ -1491,15 +1491,30 @@ struct file_notify_information {
__u8 FileName[0]; __u8 FileName[0];
} __attribute__((packed)); } __attribute__((packed));
struct reparse_data { /* For IO_REPARSE_TAG_SYMLINK */
__u32 ReparseTag; struct reparse_symlink_data {
__u16 ReparseDataLength; __le32 ReparseTag;
__le16 ReparseDataLength;
__u16 Reserved; __u16 Reserved;
__u16 SubstituteNameOffset; __le16 SubstituteNameOffset;
__u16 SubstituteNameLength; __le16 SubstituteNameLength;
__u16 PrintNameOffset; __le16 PrintNameOffset;
__u16 PrintNameLength; __le16 PrintNameLength;
__u32 Flags; __le32 Flags;
char PathBuffer[0];
} __attribute__((packed));
/* For IO_REPARSE_TAG_NFS */
#define NFS_SPECFILE_LNK 0x00000000014B4E4C
#define NFS_SPECFILE_CHR 0x0000000000524843
#define NFS_SPECFILE_BLK 0x00000000004B4C42
#define NFS_SPECFILE_FIFO 0x000000004F464946
#define NFS_SPECFILE_SOCK 0x000000004B434F53
struct reparse_posix_data {
__le32 ReparseTag;
__le16 ReparseDataLength;
__u16 Reserved;
__le64 InodeType; /* LNK, FIFO, CHR etc. */
char PathBuffer[0]; char PathBuffer[0];
} __attribute__((packed)); } __attribute__((packed));
......
...@@ -3088,7 +3088,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3088,7 +3088,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
bool is_unicode; bool is_unicode;
unsigned int sub_len; unsigned int sub_len;
char *sub_start; char *sub_start;
struct reparse_data *reparse_buf; struct reparse_symlink_data *reparse_buf;
struct reparse_posix_data *posix_buf;
__u32 data_offset, data_count; __u32 data_offset, data_count;
char *end_of_smb; char *end_of_smb;
...@@ -3137,20 +3138,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3137,20 +3138,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
goto qreparse_out; goto qreparse_out;
} }
end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
reparse_buf = (struct reparse_data *) reparse_buf = (struct reparse_symlink_data *)
((char *)&pSMBr->hdr.Protocol + data_offset); ((char *)&pSMBr->hdr.Protocol + data_offset);
if ((char *)reparse_buf >= end_of_smb) { if ((char *)reparse_buf >= end_of_smb) {
rc = -EIO; rc = -EIO;
goto qreparse_out; goto qreparse_out;
} }
if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset + if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
reparse_buf->PrintNameLength) > end_of_smb) { cifs_dbg(FYI, "NFS style reparse tag\n");
posix_buf = (struct reparse_posix_data *)reparse_buf;
if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
cifs_dbg(FYI, "unsupported file type 0x%llx\n",
le64_to_cpu(posix_buf->InodeType));
rc = -EOPNOTSUPP;
goto qreparse_out;
}
is_unicode = true;
sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
if (posix_buf->PathBuffer + sub_len > end_of_smb) {
cifs_dbg(FYI, "reparse buf beyond SMB\n");
rc = -EIO;
goto qreparse_out;
}
*symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
sub_len, is_unicode, nls_codepage);
goto qreparse_out;
} else if (reparse_buf->ReparseTag !=
cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
rc = -EOPNOTSUPP;
goto qreparse_out;
}
/* Reparse tag is NTFS symlink */
sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
reparse_buf->PathBuffer;
sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
if (sub_start + sub_len > end_of_smb) {
cifs_dbg(FYI, "reparse buf beyond SMB\n"); cifs_dbg(FYI, "reparse buf beyond SMB\n");
rc = -EIO; rc = -EIO;
goto qreparse_out; goto qreparse_out;
} }
sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer;
sub_len = reparse_buf->SubstituteNameLength;
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
is_unicode = true; is_unicode = true;
else else
......
...@@ -780,7 +780,9 @@ static const struct { ...@@ -780,7 +780,9 @@ static const struct {
ERRDOS, ERRnoaccess, 0xc0000290}, { ERRDOS, ERRnoaccess, 0xc0000290}, {
ERRDOS, ERRbadfunc, 0xc000029c}, { ERRDOS, ERRbadfunc, 0xc000029c}, {
ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, { ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
ERRDOS, ERRinvlevel, 0x007c0001}, }; ERRDOS, ERRinvlevel, 0x007c0001}, {
0, 0, 0 }
};
/***************************************************************************** /*****************************************************************************
Print an error message from the status code Print an error message from the status code
......
...@@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) ...@@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
return NTLMv2; return NTLMv2;
if (global_secflags & CIFSSEC_MAY_NTLM) if (global_secflags & CIFSSEC_MAY_NTLM)
return NTLM; return NTLM;
/* Fallthrough */
default: default:
return Unspecified; /* Fallthrough to attempt LANMAN authentication next */
break;
} }
case CIFS_NEGFLAVOR_LANMAN: case CIFS_NEGFLAVOR_LANMAN:
switch (requested) { switch (requested) {
......
...@@ -687,6 +687,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) ...@@ -687,6 +687,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
else else
return -EIO; return -EIO;
/* no need to send SMB logoff if uid already closed due to reconnect */
if (ses->need_reconnect)
goto smb2_session_already_dead;
rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req); rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req);
if (rc) if (rc)
return rc; return rc;
...@@ -701,6 +705,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) ...@@ -701,6 +705,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
* No tcon so can't do * No tcon so can't do
* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
*/ */
smb2_session_already_dead:
return rc; return rc;
} }
......
...@@ -97,9 +97,23 @@ ...@@ -97,9 +97,23 @@
#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */ #define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
#define FSCTL_SRV_READ_HASH 0x001441BB /* BB add struct */ #define FSCTL_SRV_READ_HASH 0x001441BB /* BB add struct */
/* See FSCC 2.1.2.5 */
#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 #define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
#define IO_REPARSE_TAG_HSM 0xC0000004 #define IO_REPARSE_TAG_HSM 0xC0000004
#define IO_REPARSE_TAG_SIS 0x80000007 #define IO_REPARSE_TAG_SIS 0x80000007
#define IO_REPARSE_TAG_HSM2 0x80000006
#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
/* Used by the DFS filter. See MS-DFSC */
#define IO_REPARSE_TAG_DFS 0x8000000A
/* Used by the DFS filter See MS-DFSC */
#define IO_REPARSE_TAG_DFSR 0x80000012
#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
/* See section MS-FSCC 2.1.2.4 */
#define IO_REPARSE_TAG_SYMLINK 0xA000000C
#define IO_REPARSE_TAG_DEDUP 0x80000013
#define IO_REPARSE_APPXSTREAM 0xC0000014
/* NFS symlinks, Win 8/SMB3 and later */
#define IO_REPARSE_TAG_NFS 0x80000014
/* fsctl flags */ /* fsctl flags */
/* If Flags is set to this value, the request is an FSCTL not ioctl request */ /* If Flags is set to this value, the request is an FSCTL not ioctl request */
......
...@@ -410,8 +410,13 @@ static int ...@@ -410,8 +410,13 @@ static int
wait_for_free_request(struct TCP_Server_Info *server, const int timeout, wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
const int optype) const int optype)
{ {
return wait_for_free_credits(server, timeout, int *val;
server->ops->get_credits_field(server, optype));
val = server->ops->get_credits_field(server, optype);
/* Since an echo is already inflight, no need to wait to send another */
if (*val <= 0 && optype == CIFS_ECHO_OP)
return -EAGAIN;
return wait_for_free_credits(server, timeout, val);
} }
static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
......
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