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
This commit is contained in:
Коммит
04919afb85
|
@ -120,14 +120,16 @@ cifs_read_super(struct super_block *sb)
|
|||
{
|
||||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb;
|
||||
struct cifs_tcon *tcon;
|
||||
int rc = 0;
|
||||
|
||||
cifs_sb = CIFS_SB(sb);
|
||||
tcon = cifs_sb_master_tcon(cifs_sb);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_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;
|
||||
else
|
||||
sb->s_maxbytes = MAX_NON_LFS;
|
||||
|
@ -147,7 +149,7 @@ cifs_read_super(struct super_block *sb)
|
|||
goto out_no_root;
|
||||
}
|
||||
|
||||
if (cifs_sb_master_tcon(cifs_sb)->nocase)
|
||||
if (tcon->nocase)
|
||||
sb->s_d_op = &cifs_ci_dentry_ops;
|
||||
else
|
||||
sb->s_d_op = &cifs_dentry_ops;
|
||||
|
|
|
@ -1491,15 +1491,30 @@ struct file_notify_information {
|
|||
__u8 FileName[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct reparse_data {
|
||||
__u32 ReparseTag;
|
||||
__u16 ReparseDataLength;
|
||||
/* For IO_REPARSE_TAG_SYMLINK */
|
||||
struct reparse_symlink_data {
|
||||
__le32 ReparseTag;
|
||||
__le16 ReparseDataLength;
|
||||
__u16 Reserved;
|
||||
__u16 SubstituteNameOffset;
|
||||
__u16 SubstituteNameLength;
|
||||
__u16 PrintNameOffset;
|
||||
__u16 PrintNameLength;
|
||||
__u32 Flags;
|
||||
__le16 SubstituteNameOffset;
|
||||
__le16 SubstituteNameLength;
|
||||
__le16 PrintNameOffset;
|
||||
__le16 PrintNameLength;
|
||||
__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];
|
||||
} __attribute__((packed));
|
||||
|
||||
|
|
|
@ -3088,7 +3088,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
bool is_unicode;
|
||||
unsigned int sub_len;
|
||||
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;
|
||||
char *end_of_smb;
|
||||
|
||||
|
@ -3137,20 +3138,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
|||
goto qreparse_out;
|
||||
}
|
||||
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);
|
||||
if ((char *)reparse_buf >= end_of_smb) {
|
||||
rc = -EIO;
|
||||
goto qreparse_out;
|
||||
}
|
||||
if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
|
||||
reparse_buf->PrintNameLength) > end_of_smb) {
|
||||
if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
|
||||
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");
|
||||
rc = -EIO;
|
||||
goto qreparse_out;
|
||||
}
|
||||
sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer;
|
||||
sub_len = reparse_buf->SubstituteNameLength;
|
||||
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
|
||||
is_unicode = true;
|
||||
else
|
||||
|
|
|
@ -780,7 +780,9 @@ static const struct {
|
|||
ERRDOS, ERRnoaccess, 0xc0000290}, {
|
||||
ERRDOS, ERRbadfunc, 0xc000029c}, {
|
||||
ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
|
||||
ERRDOS, ERRinvlevel, 0x007c0001}, };
|
||||
ERRDOS, ERRinvlevel, 0x007c0001}, {
|
||||
0, 0, 0 }
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
Print an error message from the status code
|
||||
|
|
|
@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
|
|||
return NTLMv2;
|
||||
if (global_secflags & CIFSSEC_MAY_NTLM)
|
||||
return NTLM;
|
||||
/* Fallthrough */
|
||||
default:
|
||||
return Unspecified;
|
||||
/* Fallthrough to attempt LANMAN authentication next */
|
||||
break;
|
||||
}
|
||||
case CIFS_NEGFLAVOR_LANMAN:
|
||||
switch (requested) {
|
||||
|
|
|
@ -687,6 +687,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
|
|||
else
|
||||
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);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -701,6 +705,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
|
|||
* No tcon so can't do
|
||||
* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
|
||||
*/
|
||||
|
||||
smb2_session_already_dead:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,9 +97,23 @@
|
|||
#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* 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_HSM 0xC0000004
|
||||
#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 */
|
||||
/* If Flags is set to this value, the request is an FSCTL not ioctl request */
|
||||
|
|
|
@ -410,8 +410,13 @@ static int
|
|||
wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
|
||||
const int optype)
|
||||
{
|
||||
return wait_for_free_credits(server, timeout,
|
||||
server->ops->get_credits_field(server, optype));
|
||||
int *val;
|
||||
|
||||
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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче