Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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;
+23 −8
Original line number Diff line number Diff line
@@ -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;
	__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;
	__u16	SubstituteNameOffset;
	__u16	SubstituteNameLength;
	__u16	PrintNameOffset;
	__u16	PrintNameLength;
	__u32	Flags;
	__le64	InodeType; /* LNK, FIFO, CHR etc. */
	char	PathBuffer[0];
} __attribute__((packed));

+34 −6
Original line number Diff line number Diff line
@@ -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
+3 −1
Original line number Diff line number Diff line
@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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) {
Loading