Skip to content

Commit 04919af

Browse files
committed
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
2 parents 83f11a9 + 0c26606 commit 04919af

File tree

8 files changed

+93
-21
lines changed

8 files changed

+93
-21
lines changed

fs/cifs/cifsfs.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,16 @@ cifs_read_super(struct super_block *sb)
120120
{
121121
struct inode *inode;
122122
struct cifs_sb_info *cifs_sb;
123+
struct cifs_tcon *tcon;
123124
int rc = 0;
124125

125126
cifs_sb = CIFS_SB(sb);
127+
tcon = cifs_sb_master_tcon(cifs_sb);
126128

127129
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
128130
sb->s_flags |= MS_POSIXACL;
129131

130-
if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES)
132+
if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files)
131133
sb->s_maxbytes = MAX_LFS_FILESIZE;
132134
else
133135
sb->s_maxbytes = MAX_NON_LFS;
@@ -147,7 +149,7 @@ cifs_read_super(struct super_block *sb)
147149
goto out_no_root;
148150
}
149151

150-
if (cifs_sb_master_tcon(cifs_sb)->nocase)
152+
if (tcon->nocase)
151153
sb->s_d_op = &cifs_ci_dentry_ops;
152154
else
153155
sb->s_d_op = &cifs_dentry_ops;

fs/cifs/cifspdu.h

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,15 +1491,30 @@ struct file_notify_information {
14911491
__u8 FileName[0];
14921492
} __attribute__((packed));
14931493

1494-
struct reparse_data {
1495-
__u32 ReparseTag;
1496-
__u16 ReparseDataLength;
1494+
/* For IO_REPARSE_TAG_SYMLINK */
1495+
struct reparse_symlink_data {
1496+
__le32 ReparseTag;
1497+
__le16 ReparseDataLength;
14971498
__u16 Reserved;
1498-
__u16 SubstituteNameOffset;
1499-
__u16 SubstituteNameLength;
1500-
__u16 PrintNameOffset;
1501-
__u16 PrintNameLength;
1502-
__u32 Flags;
1499+
__le16 SubstituteNameOffset;
1500+
__le16 SubstituteNameLength;
1501+
__le16 PrintNameOffset;
1502+
__le16 PrintNameLength;
1503+
__le32 Flags;
1504+
char PathBuffer[0];
1505+
} __attribute__((packed));
1506+
1507+
/* For IO_REPARSE_TAG_NFS */
1508+
#define NFS_SPECFILE_LNK 0x00000000014B4E4C
1509+
#define NFS_SPECFILE_CHR 0x0000000000524843
1510+
#define NFS_SPECFILE_BLK 0x00000000004B4C42
1511+
#define NFS_SPECFILE_FIFO 0x000000004F464946
1512+
#define NFS_SPECFILE_SOCK 0x000000004B434F53
1513+
struct reparse_posix_data {
1514+
__le32 ReparseTag;
1515+
__le16 ReparseDataLength;
1516+
__u16 Reserved;
1517+
__le64 InodeType; /* LNK, FIFO, CHR etc. */
15031518
char PathBuffer[0];
15041519
} __attribute__((packed));
15051520

fs/cifs/cifssmb.c

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3088,7 +3088,8 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
30883088
bool is_unicode;
30893089
unsigned int sub_len;
30903090
char *sub_start;
3091-
struct reparse_data *reparse_buf;
3091+
struct reparse_symlink_data *reparse_buf;
3092+
struct reparse_posix_data *posix_buf;
30923093
__u32 data_offset, data_count;
30933094
char *end_of_smb;
30943095

@@ -3137,20 +3138,47 @@ CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
31373138
goto qreparse_out;
31383139
}
31393140
end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
3140-
reparse_buf = (struct reparse_data *)
3141+
reparse_buf = (struct reparse_symlink_data *)
31413142
((char *)&pSMBr->hdr.Protocol + data_offset);
31423143
if ((char *)reparse_buf >= end_of_smb) {
31433144
rc = -EIO;
31443145
goto qreparse_out;
31453146
}
3146-
if ((reparse_buf->PathBuffer + reparse_buf->PrintNameOffset +
3147-
reparse_buf->PrintNameLength) > end_of_smb) {
3147+
if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
3148+
cifs_dbg(FYI, "NFS style reparse tag\n");
3149+
posix_buf = (struct reparse_posix_data *)reparse_buf;
3150+
3151+
if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
3152+
cifs_dbg(FYI, "unsupported file type 0x%llx\n",
3153+
le64_to_cpu(posix_buf->InodeType));
3154+
rc = -EOPNOTSUPP;
3155+
goto qreparse_out;
3156+
}
3157+
is_unicode = true;
3158+
sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
3159+
if (posix_buf->PathBuffer + sub_len > end_of_smb) {
3160+
cifs_dbg(FYI, "reparse buf beyond SMB\n");
3161+
rc = -EIO;
3162+
goto qreparse_out;
3163+
}
3164+
*symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
3165+
sub_len, is_unicode, nls_codepage);
3166+
goto qreparse_out;
3167+
} else if (reparse_buf->ReparseTag !=
3168+
cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
3169+
rc = -EOPNOTSUPP;
3170+
goto qreparse_out;
3171+
}
3172+
3173+
/* Reparse tag is NTFS symlink */
3174+
sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
3175+
reparse_buf->PathBuffer;
3176+
sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
3177+
if (sub_start + sub_len > end_of_smb) {
31483178
cifs_dbg(FYI, "reparse buf beyond SMB\n");
31493179
rc = -EIO;
31503180
goto qreparse_out;
31513181
}
3152-
sub_start = reparse_buf->SubstituteNameOffset + reparse_buf->PathBuffer;
3153-
sub_len = reparse_buf->SubstituteNameLength;
31543182
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
31553183
is_unicode = true;
31563184
else

fs/cifs/netmisc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,9 @@ static const struct {
780780
ERRDOS, ERRnoaccess, 0xc0000290}, {
781781
ERRDOS, ERRbadfunc, 0xc000029c}, {
782782
ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
783-
ERRDOS, ERRinvlevel, 0x007c0001}, };
783+
ERRDOS, ERRinvlevel, 0x007c0001}, {
784+
0, 0, 0 }
785+
};
784786

785787
/*****************************************************************************
786788
Print an error message from the status code

fs/cifs/sess.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,9 +500,9 @@ select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
500500
return NTLMv2;
501501
if (global_secflags & CIFSSEC_MAY_NTLM)
502502
return NTLM;
503-
/* Fallthrough */
504503
default:
505-
return Unspecified;
504+
/* Fallthrough to attempt LANMAN authentication next */
505+
break;
506506
}
507507
case CIFS_NEGFLAVOR_LANMAN:
508508
switch (requested) {

fs/cifs/smb2pdu.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
687687
else
688688
return -EIO;
689689

690+
/* no need to send SMB logoff if uid already closed due to reconnect */
691+
if (ses->need_reconnect)
692+
goto smb2_session_already_dead;
693+
690694
rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req);
691695
if (rc)
692696
return rc;
@@ -701,6 +705,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
701705
* No tcon so can't do
702706
* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
703707
*/
708+
709+
smb2_session_already_dead:
704710
return rc;
705711
}
706712

fs/cifs/smbfsctl.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,23 @@
9797
#define FSCTL_QUERY_NETWORK_INTERFACE_INFO 0x001401FC /* BB add struct */
9898
#define FSCTL_SRV_READ_HASH 0x001441BB /* BB add struct */
9999

100+
/* See FSCC 2.1.2.5 */
100101
#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003
101102
#define IO_REPARSE_TAG_HSM 0xC0000004
102103
#define IO_REPARSE_TAG_SIS 0x80000007
104+
#define IO_REPARSE_TAG_HSM2 0x80000006
105+
#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005
106+
/* Used by the DFS filter. See MS-DFSC */
107+
#define IO_REPARSE_TAG_DFS 0x8000000A
108+
/* Used by the DFS filter See MS-DFSC */
109+
#define IO_REPARSE_TAG_DFSR 0x80000012
110+
#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B
111+
/* See section MS-FSCC 2.1.2.4 */
112+
#define IO_REPARSE_TAG_SYMLINK 0xA000000C
113+
#define IO_REPARSE_TAG_DEDUP 0x80000013
114+
#define IO_REPARSE_APPXSTREAM 0xC0000014
115+
/* NFS symlinks, Win 8/SMB3 and later */
116+
#define IO_REPARSE_TAG_NFS 0x80000014
103117

104118
/* fsctl flags */
105119
/* If Flags is set to this value, the request is an FSCTL not ioctl request */

fs/cifs/transport.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,13 @@ static int
410410
wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
411411
const int optype)
412412
{
413-
return wait_for_free_credits(server, timeout,
414-
server->ops->get_credits_field(server, optype));
413+
int *val;
414+
415+
val = server->ops->get_credits_field(server, optype);
416+
/* Since an echo is already inflight, no need to wait to send another */
417+
if (*val <= 0 && optype == CIFS_ECHO_OP)
418+
return -EAGAIN;
419+
return wait_for_free_credits(server, timeout, val);
415420
}
416421

417422
static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,

0 commit comments

Comments
 (0)