Skip to content

Commit 69c902f

Browse files
committed
Merge tag '4.14-smb3-fixes-from-recent-test-events-for-stable' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Various SMB3 fixes for stable and security improvements from the recently completed SMB3/Samba test events * tag '4.14-smb3-fixes-from-recent-test-events-for-stable' of git://git.samba.org/sfrench/cifs-2.6: SMB3: Don't ignore O_SYNC/O_DSYNC and O_DIRECT flags SMB3: handle new statx fields SMB: Validate negotiate (to protect against downgrade) even if signing off cifs: release auth_key.response for reconnect. cifs: release cifs root_cred after exit_cifs CIFS: make arrays static const, reduces object code size [SMB3] Update session and share information displayed for debugging SMB2/SMB3 cifs: show 'soft' in the mount options for hard mounts SMB3: Warn user if trying to sign connection that authenticated as guest SMB3: Fix endian warning Fix SMB3.1.1 guest authentication to Samba
2 parents b03fcfa + 1013e76 commit 69c902f

File tree

6 files changed

+66
-15
lines changed

6 files changed

+66
-15
lines changed

fs/cifs/cifs_debug.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,13 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
160160
if ((ses->serverDomain == NULL) ||
161161
(ses->serverOS == NULL) ||
162162
(ses->serverNOS == NULL)) {
163-
seq_printf(m, "\n%d) entry for %s not fully "
164-
"displayed\n\t", i, ses->serverName);
163+
seq_printf(m, "\n%d) Name: %s Uses: %d Capability: 0x%x\tSession Status: %d\t",
164+
i, ses->serverName, ses->ses_count,
165+
ses->capabilities, ses->status);
166+
if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
167+
seq_printf(m, "Guest\t");
168+
else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
169+
seq_printf(m, "Anonymous\t");
165170
} else {
166171
seq_printf(m,
167172
"\n%d) Name: %s Domain: %s Uses: %d OS:"

fs/cifs/cifsfs.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
461461
seq_puts(s, ",nocase");
462462
if (tcon->retry)
463463
seq_puts(s, ",hard");
464+
else
465+
seq_puts(s, ",soft");
464466
if (tcon->use_persistent)
465467
seq_puts(s, ",persistenthandles");
466468
else if (tcon->use_resilient)
@@ -1447,7 +1449,7 @@ exit_cifs(void)
14471449
exit_cifs_idmap();
14481450
#endif
14491451
#ifdef CONFIG_CIFS_UPCALL
1450-
unregister_key_type(&cifs_spnego_key_type);
1452+
exit_cifs_spnego();
14511453
#endif
14521454
cifs_destroy_request_bufs();
14531455
cifs_destroy_mids();

fs/cifs/connect.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4154,6 +4154,14 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
41544154
cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n",
41554155
server->sec_mode, server->capabilities, server->timeAdj);
41564156

4157+
if (ses->auth_key.response) {
4158+
cifs_dbg(VFS, "Free previous auth_key.response = %p\n",
4159+
ses->auth_key.response);
4160+
kfree(ses->auth_key.response);
4161+
ses->auth_key.response = NULL;
4162+
ses->auth_key.len = 0;
4163+
}
4164+
41574165
if (server->ops->sess_setup)
41584166
rc = server->ops->sess_setup(xid, ses, nls_info);
41594167

fs/cifs/file.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,13 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
224224
if (backup_cred(cifs_sb))
225225
create_options |= CREATE_OPEN_BACKUP_INTENT;
226226

227+
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
228+
if (f_flags & O_SYNC)
229+
create_options |= CREATE_WRITE_THROUGH;
230+
231+
if (f_flags & O_DIRECT)
232+
create_options |= CREATE_NO_BUFFER;
233+
227234
oparms.tcon = tcon;
228235
oparms.cifs_sb = cifs_sb;
229236
oparms.desired_access = desired_access;
@@ -1102,8 +1109,10 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
11021109
struct cifs_tcon *tcon;
11031110
unsigned int num, max_num, max_buf;
11041111
LOCKING_ANDX_RANGE *buf, *cur;
1105-
int types[] = {LOCKING_ANDX_LARGE_FILES,
1106-
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
1112+
static const int types[] = {
1113+
LOCKING_ANDX_LARGE_FILES,
1114+
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES
1115+
};
11071116
int i;
11081117

11091118
xid = get_xid();
@@ -1434,8 +1443,10 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
14341443
unsigned int xid)
14351444
{
14361445
int rc = 0, stored_rc;
1437-
int types[] = {LOCKING_ANDX_LARGE_FILES,
1438-
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES};
1446+
static const int types[] = {
1447+
LOCKING_ANDX_LARGE_FILES,
1448+
LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES
1449+
};
14391450
unsigned int i;
14401451
unsigned int max_num, num, max_buf;
14411452
LOCKING_ANDX_RANGE *buf, *cur;

fs/cifs/inode.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
234234
fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
235235
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
236236
fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
237+
/* old POSIX extensions don't get create time */
238+
237239
fattr->cf_mode = le64_to_cpu(info->Permissions);
238240

239241
/*
@@ -2024,6 +2026,19 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
20242026
stat->blksize = CIFS_MAX_MSGSIZE;
20252027
stat->ino = CIFS_I(inode)->uniqueid;
20262028

2029+
/* old CIFS Unix Extensions doesn't return create time */
2030+
if (CIFS_I(inode)->createtime) {
2031+
stat->result_mask |= STATX_BTIME;
2032+
stat->btime =
2033+
cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
2034+
}
2035+
2036+
stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
2037+
if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED)
2038+
stat->attributes |= STATX_ATTR_COMPRESSED;
2039+
if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED)
2040+
stat->attributes |= STATX_ATTR_ENCRYPTED;
2041+
20272042
/*
20282043
* If on a multiuser mount without unix extensions or cifsacl being
20292044
* enabled, and the admin hasn't overridden them, set the ownership

fs/cifs/smb2pdu.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ assemble_neg_contexts(struct smb2_negotiate_req *req)
439439
build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt);
440440
req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
441441
req->NegotiateContextCount = cpu_to_le16(2);
442-
inc_rfc1001_len(req, 4 + sizeof(struct smb2_preauth_neg_context) + 2
442+
inc_rfc1001_len(req, 4 + sizeof(struct smb2_preauth_neg_context)
443443
+ sizeof(struct smb2_encryption_neg_context)); /* calculate hash */
444444
}
445445
#else
@@ -570,10 +570,11 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
570570
/* ops set to 3.0 by default for default so update */
571571
ses->server->ops = &smb21_operations;
572572
}
573-
} else if (rsp->DialectRevision != ses->server->vals->protocol_id) {
573+
} else if (le16_to_cpu(rsp->DialectRevision) !=
574+
ses->server->vals->protocol_id) {
574575
/* if requested single dialect ensure returned dialect matched */
575576
cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n",
576-
cpu_to_le16(rsp->DialectRevision));
577+
le16_to_cpu(rsp->DialectRevision));
577578
return -EIO;
578579
}
579580

@@ -655,15 +656,22 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
655656

656657
/*
657658
* validation ioctl must be signed, so no point sending this if we
658-
* can not sign it. We could eventually change this to selectively
659+
* can not sign it (ie are not known user). Even if signing is not
660+
* required (enabled but not negotiated), in those cases we selectively
659661
* sign just this, the first and only signed request on a connection.
660-
* This is good enough for now since a user who wants better security
661-
* would also enable signing on the mount. Having validation of
662-
* negotiate info for signed connections helps reduce attack vectors
662+
* Having validation of negotiate info helps reduce attack vectors.
663663
*/
664-
if (tcon->ses->server->sign == false)
664+
if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
665665
return 0; /* validation requires signing */
666666

667+
if (tcon->ses->user_name == NULL) {
668+
cifs_dbg(FYI, "Can't validate negotiate: null user mount\n");
669+
return 0; /* validation requires signing */
670+
}
671+
672+
if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
673+
cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n");
674+
667675
vneg_inbuf.Capabilities =
668676
cpu_to_le32(tcon->ses->server->vals->req_capabilities);
669677
memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid,
@@ -1175,6 +1183,8 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
11751183
while (sess_data->func)
11761184
sess_data->func(sess_data);
11771185

1186+
if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign))
1187+
cifs_dbg(VFS, "signing requested but authenticated as guest\n");
11781188
rc = sess_data->result;
11791189
out:
11801190
kfree(sess_data);

0 commit comments

Comments
 (0)