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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'v6.9-rc3-SMB3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

- fix for oops in cifs_get_fattr of deleted files

- fix for the remote open counter going negative in some directory
lease cases

- fix for mkfifo to instantiate dentry to avoid possible crash

- important fix to allow handling key rotation for mount and remount
(ie cases that are becoming more common when password that was used
for the mount will expire soon but will be replaced by new password)

* tag 'v6.9-rc3-SMB3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
smb3: fix broken reconnect when password changing on the server by allowing password rotation
smb: client: instantiate when creating SFU files
smb3: fix Open files on server counter going negative
smb: client: fix NULL ptr deref in cifs_mark_open_handles_for_deleted_file()

+103 -42
+2 -2
fs/smb/client/cached_dir.c
··· 433 433 if (cfid->is_open) { 434 434 rc = SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, 435 435 cfid->fid.volatile_fid); 436 - if (rc != -EBUSY && rc != -EAGAIN) 437 - atomic_dec(&cfid->tcon->num_remote_opens); 436 + if (rc) /* should we retry on -EBUSY or -EAGAIN? */ 437 + cifs_dbg(VFS, "close cached dir rc %d\n", rc); 438 438 } 439 439 440 440 free_cached_dir(cfid);
+1
fs/smb/client/cifsglob.h
··· 1077 1077 and after mount option parsing we fill it */ 1078 1078 char *domainName; 1079 1079 char *password; 1080 + char *password2; /* When key rotation used, new password may be set before it expires */ 1080 1081 char workstation_name[CIFS_MAX_WORKSTATION_LEN]; 1081 1082 struct session_key auth_key; 1082 1083 struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
+8
fs/smb/client/connect.c
··· 2183 2183 } 2184 2184 2185 2185 ++delim; 2186 + /* BB consider adding support for password2 (Key Rotation) for multiuser in future */ 2186 2187 ctx->password = kstrndup(delim, len, GFP_KERNEL); 2187 2188 if (!ctx->password) { 2188 2189 cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n", ··· 2207 2206 kfree(ctx->username); 2208 2207 ctx->username = NULL; 2209 2208 kfree_sensitive(ctx->password); 2209 + /* no need to free ctx->password2 since not allocated in this path */ 2210 2210 ctx->password = NULL; 2211 2211 goto out_key_put; 2212 2212 } ··· 2317 2315 if (ctx->password) { 2318 2316 ses->password = kstrdup(ctx->password, GFP_KERNEL); 2319 2317 if (!ses->password) 2318 + goto get_ses_fail; 2319 + } 2320 + /* ctx->password freed at unmount */ 2321 + if (ctx->password2) { 2322 + ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); 2323 + if (!ses->password2) 2320 2324 goto get_ses_fail; 2321 2325 } 2322 2326 if (ctx->domainname) {
+21
fs/smb/client/fs_context.c
··· 162 162 fsparam_string("username", Opt_user), 163 163 fsparam_string("pass", Opt_pass), 164 164 fsparam_string("password", Opt_pass), 165 + fsparam_string("password2", Opt_pass2), 165 166 fsparam_string("ip", Opt_ip), 166 167 fsparam_string("addr", Opt_ip), 167 168 fsparam_string("domain", Opt_domain), ··· 346 345 new_ctx->nodename = NULL; 347 346 new_ctx->username = NULL; 348 347 new_ctx->password = NULL; 348 + new_ctx->password2 = NULL; 349 349 new_ctx->server_hostname = NULL; 350 350 new_ctx->domainname = NULL; 351 351 new_ctx->UNC = NULL; ··· 359 357 DUP_CTX_STR(prepath); 360 358 DUP_CTX_STR(username); 361 359 DUP_CTX_STR(password); 360 + DUP_CTX_STR(password2); 362 361 DUP_CTX_STR(server_hostname); 363 362 DUP_CTX_STR(UNC); 364 363 DUP_CTX_STR(source); ··· 908 905 else { 909 906 kfree_sensitive(ses->password); 910 907 ses->password = kstrdup(ctx->password, GFP_KERNEL); 908 + kfree_sensitive(ses->password2); 909 + ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); 911 910 } 912 911 STEAL_STRING(cifs_sb, ctx, domainname); 913 912 STEAL_STRING(cifs_sb, ctx, nodename); ··· 1310 1305 goto cifs_parse_mount_err; 1311 1306 } 1312 1307 break; 1308 + case Opt_pass2: 1309 + kfree_sensitive(ctx->password2); 1310 + ctx->password2 = NULL; 1311 + if (strlen(param->string) == 0) 1312 + break; 1313 + 1314 + ctx->password2 = kstrdup(param->string, GFP_KERNEL); 1315 + if (ctx->password2 == NULL) { 1316 + cifs_errorf(fc, "OOM when copying password2 string\n"); 1317 + goto cifs_parse_mount_err; 1318 + } 1319 + break; 1313 1320 case Opt_ip: 1314 1321 if (strlen(param->string) == 0) { 1315 1322 ctx->got_ip = false; ··· 1625 1608 cifs_parse_mount_err: 1626 1609 kfree_sensitive(ctx->password); 1627 1610 ctx->password = NULL; 1611 + kfree_sensitive(ctx->password2); 1612 + ctx->password2 = NULL; 1628 1613 return -EINVAL; 1629 1614 } 1630 1615 ··· 1732 1713 ctx->username = NULL; 1733 1714 kfree_sensitive(ctx->password); 1734 1715 ctx->password = NULL; 1716 + kfree_sensitive(ctx->password2); 1717 + ctx->password2 = NULL; 1735 1718 kfree(ctx->server_hostname); 1736 1719 ctx->server_hostname = NULL; 1737 1720 kfree(ctx->UNC);
+2
fs/smb/client/fs_context.h
··· 145 145 Opt_source, 146 146 Opt_user, 147 147 Opt_pass, 148 + Opt_pass2, 148 149 Opt_ip, 149 150 Opt_domain, 150 151 Opt_srcaddr, ··· 178 177 179 178 char *username; 180 179 char *password; 180 + char *password2; 181 181 char *domainname; 182 182 char *source; 183 183 char *server_hostname;
+2 -1
fs/smb/client/inode.c
··· 1105 1105 } else { 1106 1106 cifs_open_info_to_fattr(fattr, data, sb); 1107 1107 } 1108 - if (!rc && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING) 1108 + if (!rc && *inode && 1109 + (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)) 1109 1110 cifs_mark_open_handles_for_deleted_file(*inode, full_path); 1110 1111 break; 1111 1112 case -EREMOTE:
+1
fs/smb/client/misc.c
··· 98 98 kfree(buf_to_free->serverDomain); 99 99 kfree(buf_to_free->serverNOS); 100 100 kfree_sensitive(buf_to_free->password); 101 + kfree_sensitive(buf_to_free->password2); 101 102 kfree(buf_to_free->user_name); 102 103 kfree(buf_to_free->domainName); 103 104 kfree_sensitive(buf_to_free->auth_key.response);
+55 -39
fs/smb/client/smb2ops.c
··· 4964 4964 return 0; 4965 4965 } 4966 4966 4967 - int cifs_sfu_make_node(unsigned int xid, struct inode *inode, 4968 - struct dentry *dentry, struct cifs_tcon *tcon, 4969 - const char *full_path, umode_t mode, dev_t dev) 4967 + static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode, 4968 + struct dentry *dentry, struct cifs_tcon *tcon, 4969 + const char *full_path, umode_t mode, dev_t dev) 4970 4970 { 4971 - struct cifs_open_info_data buf = {}; 4972 4971 struct TCP_Server_Info *server = tcon->ses->server; 4973 4972 struct cifs_open_parms oparms; 4974 4973 struct cifs_io_parms io_parms = {}; 4975 4974 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 4976 4975 struct cifs_fid fid; 4977 4976 unsigned int bytes_written; 4978 - struct win_dev *pdev; 4977 + struct win_dev pdev = {}; 4979 4978 struct kvec iov[2]; 4980 4979 __u32 oplock = server->oplocks ? REQ_OPLOCK : 0; 4981 4980 int rc; 4982 4981 4983 - if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode)) 4982 + switch (mode & S_IFMT) { 4983 + case S_IFCHR: 4984 + strscpy(pdev.type, "IntxCHR"); 4985 + pdev.major = cpu_to_le64(MAJOR(dev)); 4986 + pdev.minor = cpu_to_le64(MINOR(dev)); 4987 + break; 4988 + case S_IFBLK: 4989 + strscpy(pdev.type, "IntxBLK"); 4990 + pdev.major = cpu_to_le64(MAJOR(dev)); 4991 + pdev.minor = cpu_to_le64(MINOR(dev)); 4992 + break; 4993 + case S_IFIFO: 4994 + strscpy(pdev.type, "LnxFIFO"); 4995 + break; 4996 + default: 4984 4997 return -EPERM; 4998 + } 4985 4999 4986 - oparms = (struct cifs_open_parms) { 4987 - .tcon = tcon, 4988 - .cifs_sb = cifs_sb, 4989 - .desired_access = GENERIC_WRITE, 4990 - .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | 4991 - CREATE_OPTION_SPECIAL), 4992 - .disposition = FILE_CREATE, 4993 - .path = full_path, 4994 - .fid = &fid, 4995 - }; 5000 + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, GENERIC_WRITE, 5001 + FILE_CREATE, CREATE_NOT_DIR | 5002 + CREATE_OPTION_SPECIAL, ACL_NO_MODE); 5003 + oparms.fid = &fid; 4996 5004 4997 - rc = server->ops->open(xid, &oparms, &oplock, &buf); 5005 + rc = server->ops->open(xid, &oparms, &oplock, NULL); 4998 5006 if (rc) 4999 5007 return rc; 5000 5008 5001 - /* 5002 - * BB Do not bother to decode buf since no local inode yet to put 5003 - * timestamps in, but we can reuse it safely. 5004 - */ 5005 - pdev = (struct win_dev *)&buf.fi; 5006 5009 io_parms.pid = current->tgid; 5007 5010 io_parms.tcon = tcon; 5008 - io_parms.length = sizeof(*pdev); 5009 - iov[1].iov_base = pdev; 5010 - iov[1].iov_len = sizeof(*pdev); 5011 - if (S_ISCHR(mode)) { 5012 - memcpy(pdev->type, "IntxCHR", 8); 5013 - pdev->major = cpu_to_le64(MAJOR(dev)); 5014 - pdev->minor = cpu_to_le64(MINOR(dev)); 5015 - } else if (S_ISBLK(mode)) { 5016 - memcpy(pdev->type, "IntxBLK", 8); 5017 - pdev->major = cpu_to_le64(MAJOR(dev)); 5018 - pdev->minor = cpu_to_le64(MINOR(dev)); 5019 - } else if (S_ISFIFO(mode)) { 5020 - memcpy(pdev->type, "LnxFIFO", 8); 5021 - } 5011 + io_parms.length = sizeof(pdev); 5012 + iov[1].iov_base = &pdev; 5013 + iov[1].iov_len = sizeof(pdev); 5022 5014 5023 5015 rc = server->ops->sync_write(xid, &fid, &io_parms, 5024 5016 &bytes_written, iov, 1); 5025 5017 server->ops->close(xid, tcon, &fid); 5026 - d_drop(dentry); 5027 - /* FIXME: add code here to set EAs */ 5028 - cifs_free_open_info(&buf); 5018 + return rc; 5019 + } 5020 + 5021 + int cifs_sfu_make_node(unsigned int xid, struct inode *inode, 5022 + struct dentry *dentry, struct cifs_tcon *tcon, 5023 + const char *full_path, umode_t mode, dev_t dev) 5024 + { 5025 + struct inode *new = NULL; 5026 + int rc; 5027 + 5028 + rc = __cifs_sfu_make_node(xid, inode, dentry, tcon, 5029 + full_path, mode, dev); 5030 + if (rc) 5031 + return rc; 5032 + 5033 + if (tcon->posix_extensions) { 5034 + rc = smb311_posix_get_inode_info(&new, full_path, NULL, 5035 + inode->i_sb, xid); 5036 + } else if (tcon->unix_ext) { 5037 + rc = cifs_get_inode_info_unix(&new, full_path, 5038 + inode->i_sb, xid); 5039 + } else { 5040 + rc = cifs_get_inode_info(&new, full_path, NULL, 5041 + inode->i_sb, xid, NULL); 5042 + } 5043 + if (!rc) 5044 + d_instantiate(dentry, new); 5029 5045 return rc; 5030 5046 } 5031 5047
+11
fs/smb/client/smb2pdu.c
··· 367 367 } 368 368 369 369 rc = cifs_setup_session(0, ses, server, nls_codepage); 370 + if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) { 371 + /* 372 + * Try alternate password for next reconnect (key rotation 373 + * could be enabled on the server e.g.) if an alternate 374 + * password is available and the current password is expired, 375 + * but do not swap on non pwd related errors like host down 376 + */ 377 + if (ses->password2) 378 + swap(ses->password2, ses->password); 379 + } 380 + 370 381 if ((rc == -EACCES) && !tcon->retry) { 371 382 mutex_unlock(&ses->session_mutex); 372 383 rc = -EHOSTDOWN;