Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+66 -15
+7 -2
fs/cifs/cifs_debug.c
··· 160 160 if ((ses->serverDomain == NULL) || 161 161 (ses->serverOS == NULL) || 162 162 (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"); 165 170 } else { 166 171 seq_printf(m, 167 172 "\n%d) Name: %s Domain: %s Uses: %d OS:"
+3 -1
fs/cifs/cifsfs.c
··· 461 461 seq_puts(s, ",nocase"); 462 462 if (tcon->retry) 463 463 seq_puts(s, ",hard"); 464 + else 465 + seq_puts(s, ",soft"); 464 466 if (tcon->use_persistent) 465 467 seq_puts(s, ",persistenthandles"); 466 468 else if (tcon->use_resilient) ··· 1449 1447 exit_cifs_idmap(); 1450 1448 #endif 1451 1449 #ifdef CONFIG_CIFS_UPCALL 1452 - unregister_key_type(&cifs_spnego_key_type); 1450 + exit_cifs_spnego(); 1453 1451 #endif 1454 1452 cifs_destroy_request_bufs(); 1455 1453 cifs_destroy_mids();
+8
fs/cifs/connect.c
··· 4154 4154 cifs_dbg(FYI, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d\n", 4155 4155 server->sec_mode, server->capabilities, server->timeAdj); 4156 4156 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 + 4157 4165 if (server->ops->sess_setup) 4158 4166 rc = server->ops->sess_setup(xid, ses, nls_info); 4159 4167
+15 -4
fs/cifs/file.c
··· 224 224 if (backup_cred(cifs_sb)) 225 225 create_options |= CREATE_OPEN_BACKUP_INTENT; 226 226 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 + 227 234 oparms.tcon = tcon; 228 235 oparms.cifs_sb = cifs_sb; 229 236 oparms.desired_access = desired_access; ··· 1109 1102 struct cifs_tcon *tcon; 1110 1103 unsigned int num, max_num, max_buf; 1111 1104 LOCKING_ANDX_RANGE *buf, *cur; 1112 - int types[] = {LOCKING_ANDX_LARGE_FILES, 1113 - LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; 1105 + static const int types[] = { 1106 + LOCKING_ANDX_LARGE_FILES, 1107 + LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES 1108 + }; 1114 1109 int i; 1115 1110 1116 1111 xid = get_xid(); ··· 1443 1434 unsigned int xid) 1444 1435 { 1445 1436 int rc = 0, stored_rc; 1446 - int types[] = {LOCKING_ANDX_LARGE_FILES, 1447 - LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; 1437 + static const int types[] = { 1438 + LOCKING_ANDX_LARGE_FILES, 1439 + LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES 1440 + }; 1448 1441 unsigned int i; 1449 1442 unsigned int max_num, num, max_buf; 1450 1443 LOCKING_ANDX_RANGE *buf, *cur;
+15
fs/cifs/inode.c
··· 234 234 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); 235 235 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime); 236 236 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange); 237 + /* old POSIX extensions don't get create time */ 238 + 237 239 fattr->cf_mode = le64_to_cpu(info->Permissions); 238 240 239 241 /* ··· 2025 2023 generic_fillattr(inode, stat); 2026 2024 stat->blksize = CIFS_MAX_MSGSIZE; 2027 2025 stat->ino = CIFS_I(inode)->uniqueid; 2026 + 2027 + /* old CIFS Unix Extensions doesn't return create time */ 2028 + if (CIFS_I(inode)->createtime) { 2029 + stat->result_mask |= STATX_BTIME; 2030 + stat->btime = 2031 + cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime)); 2032 + } 2033 + 2034 + stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED); 2035 + if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_COMPRESSED) 2036 + stat->attributes |= STATX_ATTR_COMPRESSED; 2037 + if (CIFS_I(inode)->cifsAttrs & FILE_ATTRIBUTE_ENCRYPTED) 2038 + stat->attributes |= STATX_ATTR_ENCRYPTED; 2028 2039 2029 2040 /* 2030 2041 * If on a multiuser mount without unix extensions or cifsacl being
+18 -8
fs/cifs/smb2pdu.c
··· 439 439 build_encrypt_ctxt((struct smb2_encryption_neg_context *)pneg_ctxt); 440 440 req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT); 441 441 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) 443 443 + sizeof(struct smb2_encryption_neg_context)); /* calculate hash */ 444 444 } 445 445 #else ··· 570 570 /* ops set to 3.0 by default for default so update */ 571 571 ses->server->ops = &smb21_operations; 572 572 } 573 - } else if (rsp->DialectRevision != ses->server->vals->protocol_id) { 573 + } else if (le16_to_cpu(rsp->DialectRevision) != 574 + ses->server->vals->protocol_id) { 574 575 /* if requested single dialect ensure returned dialect matched */ 575 576 cifs_dbg(VFS, "Illegal 0x%x dialect returned: not requested\n", 576 - cpu_to_le16(rsp->DialectRevision)); 577 + le16_to_cpu(rsp->DialectRevision)); 577 578 return -EIO; 578 579 } 579 580 ··· 656 655 657 656 /* 658 657 * validation ioctl must be signed, so no point sending this if we 659 - * can not sign it. We could eventually change this to selectively 658 + * can not sign it (ie are not known user). Even if signing is not 659 + * required (enabled but not negotiated), in those cases we selectively 660 660 * sign just this, the first and only signed request on a connection. 661 - * This is good enough for now since a user who wants better security 662 - * would also enable signing on the mount. Having validation of 663 - * negotiate info for signed connections helps reduce attack vectors 661 + * Having validation of negotiate info helps reduce attack vectors. 664 662 */ 665 - if (tcon->ses->server->sign == false) 663 + if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) 666 664 return 0; /* validation requires signing */ 665 + 666 + if (tcon->ses->user_name == NULL) { 667 + cifs_dbg(FYI, "Can't validate negotiate: null user mount\n"); 668 + return 0; /* validation requires signing */ 669 + } 670 + 671 + if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) 672 + cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); 667 673 668 674 vneg_inbuf.Capabilities = 669 675 cpu_to_le32(tcon->ses->server->vals->req_capabilities); ··· 1183 1175 while (sess_data->func) 1184 1176 sess_data->func(sess_data); 1185 1177 1178 + if ((ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST) && (ses->sign)) 1179 + cifs_dbg(VFS, "signing requested but authenticated as guest\n"); 1186 1180 rc = sess_data->result; 1187 1181 out: 1188 1182 kfree(sess_data);