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 '6.18-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client updates from Steve French:

- Fix oops in crypt message

- Remove duplicate arc4 code

- Fix potential io_uring reconnect

- Two important directory leases fixes and three perf improvements

- Three minor cleanups

- Four debug improvements (e.g. for showing more information on leases,
and one for adding more helpful information on reconnect)

* tag '6.18-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: client: force multichannel=off when max_channels=1
smb client: fix bug with newly created file in cached dir
smb: client: short-circuit negative lookups when parent dir is fully cached
smb: client: short-circuit in open_cached_dir_by_dentry() if !dentry
smb: client: remove pointless cfid->has_lease check
smb: client: transport: minor indentation style fix
smb: client: transport: avoid reconnects triggered by pending task work
smb: client: remove unused fid_lock
smb: client: update cfid->last_access_time in open_cached_dir_by_dentry()
smb: client: ensure open_cached_dir_by_dentry() only returns valid cfid
smb: client: account smb directory cache usage and per-tcon totals
smb: client: add drop_dir_cache module parameter to invalidate cached dirents
smb: client: show lease state as R/H/W (or NONE) in open_files
smb: client: fix crypto buffers in non-linear memory
smb: Use arc4 library instead of duplicate arc4 code
smb: client: add tcon information to smb2_reconnect() debug messages

+236 -177
+1
fs/smb/client/Kconfig
··· 15 15 select CRYPTO_GCM 16 16 select CRYPTO_ECB 17 17 select CRYPTO_AES 18 + select CRYPTO_LIB_ARC4 18 19 select KEYS 19 20 select DNS_RESOLVER 20 21 select ASN1
+31 -19
fs/smb/client/cached_dir.c
··· 36 36 * fully cached or it may be in the process of 37 37 * being deleted due to a lease break. 38 38 */ 39 - if (!cfid->time || !cfid->has_lease) { 39 + if (!is_valid_cached_dir(cfid)) 40 40 return NULL; 41 - } 42 41 kref_get(&cfid->refcount); 43 42 return cfid; 44 43 } ··· 193 194 * Otherwise, it is either a new entry or laundromat worker removed it 194 195 * from @cfids->entries. Caller will put last reference if the latter. 195 196 */ 196 - if (cfid->has_lease && cfid->time) { 197 + if (is_valid_cached_dir(cfid)) { 197 198 cfid->last_access_time = jiffies; 198 199 spin_unlock(&cfids->cfid_list_lock); 199 200 *ret_cfid = cfid; ··· 232 233 list_for_each_entry(parent_cfid, &cfids->entries, entry) { 233 234 if (parent_cfid->dentry == dentry->d_parent) { 234 235 cifs_dbg(FYI, "found a parent cached file handle\n"); 235 - if (parent_cfid->has_lease && parent_cfid->time) { 236 + if (is_valid_cached_dir(parent_cfid)) { 236 237 lease_flags 237 238 |= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE; 238 239 memcpy(pfid->parent_lease_key, ··· 416 417 if (cfids == NULL) 417 418 return -EOPNOTSUPP; 418 419 420 + if (!dentry) 421 + return -ENOENT; 422 + 419 423 spin_lock(&cfids->cfid_list_lock); 420 424 list_for_each_entry(cfid, &cfids->entries, entry) { 421 - if (dentry && cfid->dentry == dentry) { 425 + if (cfid->dentry == dentry) { 426 + if (!is_valid_cached_dir(cfid)) 427 + break; 422 428 cifs_dbg(FYI, "found a cached file handle by dentry\n"); 423 429 kref_get(&cfid->refcount); 424 430 *ret_cfid = cfid; 431 + cfid->last_access_time = jiffies; 425 432 spin_unlock(&cfids->cfid_list_lock); 426 433 return 0; 427 434 } ··· 527 522 spin_unlock(&cifs_sb->tlink_tree_lock); 528 523 goto done; 529 524 } 530 - spin_lock(&cfid->fid_lock); 525 + 531 526 tmp_list->dentry = cfid->dentry; 532 527 cfid->dentry = NULL; 533 - spin_unlock(&cfid->fid_lock); 534 528 535 529 list_add_tail(&tmp_list->entry, &entry); 536 530 } ··· 612 608 { 613 609 struct cached_fid *cfid = container_of(work, struct cached_fid, 614 610 put_work); 615 - struct dentry *dentry; 616 - 617 - spin_lock(&cfid->fid_lock); 618 - dentry = cfid->dentry; 611 + dput(cfid->dentry); 619 612 cfid->dentry = NULL; 620 - spin_unlock(&cfid->fid_lock); 621 613 622 - dput(dentry); 623 614 queue_work(serverclose_wq, &cfid->close_work); 624 615 } 625 616 ··· 672 673 INIT_LIST_HEAD(&cfid->entry); 673 674 INIT_LIST_HEAD(&cfid->dirents.entries); 674 675 mutex_init(&cfid->dirents.de_mutex); 675 - spin_lock_init(&cfid->fid_lock); 676 676 kref_init(&cfid->refcount); 677 677 return cfid; 678 678 } ··· 694 696 kfree(dirent->name); 695 697 kfree(dirent); 696 698 } 699 + 700 + /* adjust tcon-level counters and reset per-dir accounting */ 701 + if (cfid->cfids) { 702 + if (cfid->dirents.entries_count) 703 + atomic_long_sub((long)cfid->dirents.entries_count, 704 + &cfid->cfids->total_dirents_entries); 705 + if (cfid->dirents.bytes_used) { 706 + atomic64_sub((long long)cfid->dirents.bytes_used, 707 + &cfid->cfids->total_dirents_bytes); 708 + atomic64_sub((long long)cfid->dirents.bytes_used, 709 + &cifs_dircache_bytes_used); 710 + } 711 + } 712 + cfid->dirents.entries_count = 0; 713 + cfid->dirents.bytes_used = 0; 697 714 698 715 kfree(cfid->path); 699 716 cfid->path = NULL; ··· 738 725 { 739 726 struct cached_fids *cfids; 740 727 struct cached_fid *cfid, *q; 741 - struct dentry *dentry; 742 728 LIST_HEAD(entry); 743 729 744 730 cfids = container_of(work, struct cached_fids, laundromat_work.work); ··· 764 752 list_for_each_entry_safe(cfid, q, &entry, entry) { 765 753 list_del(&cfid->entry); 766 754 767 - spin_lock(&cfid->fid_lock); 768 - dentry = cfid->dentry; 755 + dput(cfid->dentry); 769 756 cfid->dentry = NULL; 770 - spin_unlock(&cfid->fid_lock); 771 757 772 - dput(dentry); 773 758 if (cfid->is_open) { 774 759 spin_lock(&cifs_tcp_ses_lock); 775 760 ++cfid->tcon->tc_count; ··· 800 791 INIT_DELAYED_WORK(&cfids->laundromat_work, cfids_laundromat_worker); 801 792 queue_delayed_work(cfid_put_wq, &cfids->laundromat_work, 802 793 dir_cache_timeout * HZ); 794 + 795 + atomic_long_set(&cfids->total_dirents_entries, 0); 796 + atomic64_set(&cfids->total_dirents_bytes, 0); 803 797 804 798 return cfids; 805 799 }
+15 -1
fs/smb/client/cached_dir.h
··· 27 27 struct mutex de_mutex; 28 28 loff_t pos; /* Expected ctx->pos */ 29 29 struct list_head entries; 30 + /* accounting for cached entries in this directory */ 31 + unsigned long entries_count; 32 + unsigned long bytes_used; 30 33 }; 31 34 32 35 struct cached_fid { ··· 44 41 unsigned long last_access_time; /* jiffies of when last accessed */ 45 42 struct kref refcount; 46 43 struct cifs_fid fid; 47 - spinlock_t fid_lock; 48 44 struct cifs_tcon *tcon; 49 45 struct dentry *dentry; 50 46 struct work_struct put_work; ··· 64 62 struct list_head dying; 65 63 struct work_struct invalidation_work; 66 64 struct delayed_work laundromat_work; 65 + /* aggregate accounting for all cached dirents under this tcon */ 66 + atomic_long_t total_dirents_entries; 67 + atomic64_t total_dirents_bytes; 67 68 }; 69 + 70 + /* Module-wide directory cache accounting (defined in cifsfs.c) */ 71 + extern atomic64_t cifs_dircache_bytes_used; /* bytes across all mounts */ 72 + 73 + static inline bool 74 + is_valid_cached_dir(struct cached_fid *cfid) 75 + { 76 + return cfid->time && cfid->has_lease; 77 + } 68 78 69 79 extern struct cached_fids *init_cached_dirs(void); 70 80 extern void free_cached_dirs(struct cached_fids *cfids);
+35 -6
fs/smb/client/cifs_debug.c
··· 240 240 struct cifs_ses *ses; 241 241 struct cifs_tcon *tcon; 242 242 struct cifsFileInfo *cfile; 243 + struct inode *inode; 244 + struct cifsInodeInfo *cinode; 245 + char lease[4]; 246 + int n; 243 247 244 248 seq_puts(m, "# Version:1\n"); 245 249 seq_puts(m, "# Format:\n"); 246 250 seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>"); 247 251 #ifdef CONFIG_CIFS_DEBUG2 248 - seq_printf(m, " <filename> <mid>\n"); 252 + seq_puts(m, " <filename> <lease> <mid>\n"); 249 253 #else 250 - seq_printf(m, " <filename>\n"); 254 + seq_puts(m, " <filename> <lease>\n"); 251 255 #endif /* CIFS_DEBUG2 */ 252 256 spin_lock(&cifs_tcp_ses_lock); 253 257 list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { ··· 271 267 cfile->pid, 272 268 from_kuid(&init_user_ns, cfile->uid), 273 269 cfile->dentry); 270 + 271 + /* Append lease/oplock caching state as RHW letters */ 272 + inode = d_inode(cfile->dentry); 273 + n = 0; 274 + if (inode) { 275 + cinode = CIFS_I(inode); 276 + if (CIFS_CACHE_READ(cinode)) 277 + lease[n++] = 'R'; 278 + if (CIFS_CACHE_HANDLE(cinode)) 279 + lease[n++] = 'H'; 280 + if (CIFS_CACHE_WRITE(cinode)) 281 + lease[n++] = 'W'; 282 + } 283 + lease[n] = '\0'; 284 + seq_puts(m, " "); 285 + if (n) 286 + seq_printf(m, "%s", lease); 287 + else 288 + seq_puts(m, "NONE"); 289 + 274 290 #ifdef CONFIG_CIFS_DEBUG2 275 - seq_printf(m, " %llu\n", cfile->fid.mid); 276 - #else 291 + seq_printf(m, " %llu", cfile->fid.mid); 292 + #endif /* CONFIG_CIFS_DEBUG2 */ 277 293 seq_printf(m, "\n"); 278 - #endif /* CIFS_DEBUG2 */ 279 294 } 280 295 spin_unlock(&tcon->open_file_lock); 281 296 } ··· 331 308 if (!cfids) 332 309 continue; 333 310 spin_lock(&cfids->cfid_list_lock); /* check lock ordering */ 334 - seq_printf(m, "Num entries: %d\n", cfids->num_entries); 311 + seq_printf(m, "Num entries: %d, cached_dirents: %lu entries, %llu bytes\n", 312 + cfids->num_entries, 313 + (unsigned long)atomic_long_read(&cfids->total_dirents_entries), 314 + (unsigned long long)atomic64_read(&cfids->total_dirents_bytes)); 335 315 list_for_each_entry(cfid, &cfids->entries, entry) { 336 316 seq_printf(m, "0x%x 0x%llx 0x%llx %s", 337 317 tcon->tid, ··· 345 319 seq_printf(m, "\tvalid file info"); 346 320 if (cfid->dirents.is_valid) 347 321 seq_printf(m, ", valid dirents"); 322 + if (!list_empty(&cfid->dirents.entries)) 323 + seq_printf(m, ", dirents: %lu entries, %lu bytes", 324 + cfid->dirents.entries_count, cfid->dirents.bytes_used); 348 325 seq_printf(m, "\n"); 349 326 } 350 327 spin_unlock(&cfids->cfid_list_lock);
+4 -4
fs/smb/client/cifsencrypt.c
··· 22 22 #include <linux/highmem.h> 23 23 #include <linux/fips.h> 24 24 #include <linux/iov_iter.h> 25 - #include "../common/arc4.h" 26 25 #include <crypto/aead.h> 26 + #include <crypto/arc4.h> 27 27 28 28 static size_t cifs_shash_step(void *iter_base, size_t progress, size_t len, 29 29 void *priv, void *priv2) ··· 725 725 return -ENOMEM; 726 726 } 727 727 728 - cifs_arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE); 729 - cifs_arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key, 730 - CIFS_CPHTXT_SIZE); 728 + arc4_setkey(ctx_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE); 729 + arc4_crypt(ctx_arc4, ses->ntlmssp->ciphertext, sec_key, 730 + CIFS_CPHTXT_SIZE); 731 731 732 732 /* make secondary_key/nonce as session key */ 733 733 memcpy(ses->auth_key.response, sec_key, CIFS_SESS_KEY_SIZE);
+40
fs/smb/client/cifsfs.c
··· 121 121 module_param(dir_cache_timeout, uint, 0644); 122 122 MODULE_PARM_DESC(dir_cache_timeout, "Number of seconds to cache directory contents for which we have a lease. Default: 30 " 123 123 "Range: 1 to 65000 seconds, 0 to disable caching dir contents"); 124 + /* Module-wide total cached dirents (in bytes) across all tcons */ 125 + atomic64_t cifs_dircache_bytes_used = ATOMIC64_INIT(0); 126 + 127 + /* 128 + * Write-only module parameter to drop all cached directory entries across 129 + * all CIFS mounts. Echo a non-zero value to trigger. 130 + */ 131 + static void cifs_drop_all_dir_caches(void) 132 + { 133 + struct TCP_Server_Info *server; 134 + struct cifs_ses *ses; 135 + struct cifs_tcon *tcon; 136 + 137 + spin_lock(&cifs_tcp_ses_lock); 138 + list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { 139 + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 140 + if (cifs_ses_exiting(ses)) 141 + continue; 142 + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) 143 + invalidate_all_cached_dirs(tcon); 144 + } 145 + } 146 + spin_unlock(&cifs_tcp_ses_lock); 147 + } 148 + 149 + static int cifs_param_set_drop_dir_cache(const char *val, const struct kernel_param *kp) 150 + { 151 + bool bv; 152 + int rc = kstrtobool(val, &bv); 153 + 154 + if (rc) 155 + return rc; 156 + if (bv) 157 + cifs_drop_all_dir_caches(); 158 + return 0; 159 + } 160 + 161 + module_param_call(drop_dir_cache, cifs_param_set_drop_dir_cache, NULL, NULL, 0200); 162 + MODULE_PARM_DESC(drop_dir_cache, "Write 1 to drop all cached directory entries across all CIFS mounts"); 163 + 124 164 #ifdef CONFIG_CIFS_STATS2 125 165 unsigned int slow_rsp_threshold = 1; 126 166 module_param(slow_rsp_threshold, uint, 0644);
+44 -2
fs/smb/client/dir.c
··· 322 322 list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) { 323 323 if (parent_cfid->dentry == direntry->d_parent) { 324 324 cifs_dbg(FYI, "found a parent cached file handle\n"); 325 - if (parent_cfid->has_lease && parent_cfid->time) { 325 + if (is_valid_cached_dir(parent_cfid)) { 326 326 lease_flags 327 327 |= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE; 328 328 memcpy(fid->parent_lease_key, 329 329 parent_cfid->fid.lease_key, 330 330 SMB2_LEASE_KEY_SIZE); 331 331 parent_cfid->dirents.is_valid = false; 332 + parent_cfid->dirents.is_failed = true; 332 333 } 333 334 break; 334 335 } ··· 678 677 const char *full_path; 679 678 void *page; 680 679 int retry_count = 0; 680 + struct cached_fid *cfid = NULL; 681 681 682 682 xid = get_xid(); 683 683 ··· 718 716 cifs_dbg(FYI, "non-NULL inode in lookup\n"); 719 717 } else { 720 718 cifs_dbg(FYI, "NULL inode in lookup\n"); 719 + 720 + /* 721 + * We can only rely on negative dentries having the same 722 + * spelling as the cached dirent if case insensitivity is 723 + * forced on mount. 724 + * 725 + * XXX: if servers correctly announce Case Sensitivity Search 726 + * on GetInfo of FileFSAttributeInformation, then we can take 727 + * correct action even if case insensitive is not forced on 728 + * mount. 729 + */ 730 + if (pTcon->nocase && !open_cached_dir_by_dentry(pTcon, direntry->d_parent, &cfid)) { 731 + /* 732 + * dentry is negative and parent is fully cached: 733 + * we can assume file does not exist 734 + */ 735 + if (cfid->dirents.is_valid) { 736 + close_cached_dir(cfid); 737 + goto out; 738 + } 739 + close_cached_dir(cfid); 740 + } 721 741 } 722 742 cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", 723 743 full_path, d_inode(direntry)); ··· 773 749 } 774 750 newInode = ERR_PTR(rc); 775 751 } 752 + 753 + out: 776 754 free_dentry_path(page); 777 755 cifs_put_tlink(tlink); 778 756 free_xid(xid); ··· 785 759 cifs_d_revalidate(struct inode *dir, const struct qstr *name, 786 760 struct dentry *direntry, unsigned int flags) 787 761 { 788 - struct inode *inode; 762 + struct inode *inode = NULL; 763 + struct cached_fid *cfid; 789 764 int rc; 790 765 791 766 if (flags & LOOKUP_RCU) ··· 832 805 } 833 806 834 807 return 1; 808 + } 809 + } else { 810 + struct cifs_sb_info *cifs_sb = CIFS_SB(dir->i_sb); 811 + struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 812 + 813 + if (!open_cached_dir_by_dentry(tcon, direntry->d_parent, &cfid)) { 814 + /* 815 + * dentry is negative and parent is fully cached: 816 + * we can assume file does not exist 817 + */ 818 + if (cfid->dirents.is_valid) { 819 + close_cached_dir(cfid); 820 + return 1; 821 + } 822 + close_cached_dir(cfid); 835 823 } 836 824 } 837 825
+7
fs/smb/client/fs_context.c
··· 1818 1818 goto cifs_parse_mount_err; 1819 1819 } 1820 1820 1821 + /* 1822 + * Multichannel is not meaningful if max_channels is 1. 1823 + * Force multichannel to false to ensure consistent configuration. 1824 + */ 1825 + if (ctx->multichannel && ctx->max_channels == 1) 1826 + ctx->multichannel = false; 1827 + 1821 1828 return 0; 1822 1829 1823 1830 cifs_parse_mount_err:
+1 -1
fs/smb/client/inode.c
··· 2704 2704 return true; 2705 2705 2706 2706 if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) { 2707 - if (cfid->time && cifs_i->time > cfid->time) { 2707 + if (cifs_i->time > cfid->time) { 2708 2708 close_cached_dir(cfid); 2709 2709 return false; 2710 2710 }
+27 -13
fs/smb/client/readdir.c
··· 874 874 cde->is_valid = 1; 875 875 } 876 876 877 - static void add_cached_dirent(struct cached_dirents *cde, 878 - struct dir_context *ctx, 879 - const char *name, int namelen, 880 - struct cifs_fattr *fattr, 881 - struct file *file) 877 + static bool add_cached_dirent(struct cached_dirents *cde, 878 + struct dir_context *ctx, const char *name, 879 + int namelen, struct cifs_fattr *fattr, 880 + struct file *file) 882 881 { 883 882 struct cached_dirent *de; 884 883 885 884 if (cde->file != file) 886 - return; 885 + return false; 887 886 if (cde->is_valid || cde->is_failed) 888 - return; 887 + return false; 889 888 if (ctx->pos != cde->pos) { 890 889 cde->is_failed = 1; 891 - return; 890 + return false; 892 891 } 893 892 de = kzalloc(sizeof(*de), GFP_ATOMIC); 894 893 if (de == NULL) { 895 894 cde->is_failed = 1; 896 - return; 895 + return false; 897 896 } 898 897 de->namelen = namelen; 899 898 de->name = kstrndup(name, namelen, GFP_ATOMIC); 900 899 if (de->name == NULL) { 901 900 kfree(de); 902 901 cde->is_failed = 1; 903 - return; 902 + return false; 904 903 } 905 904 de->pos = ctx->pos; 906 905 907 906 memcpy(&de->fattr, fattr, sizeof(struct cifs_fattr)); 908 907 909 908 list_add_tail(&de->entry, &cde->entries); 909 + /* update accounting */ 910 + cde->entries_count++; 911 + cde->bytes_used += sizeof(*de) + (size_t)namelen + 1; 912 + return true; 910 913 } 911 914 912 915 static bool cifs_dir_emit(struct dir_context *ctx, ··· 918 915 struct cached_fid *cfid, 919 916 struct file *file) 920 917 { 921 - bool rc; 918 + size_t delta_bytes = 0; 919 + bool rc, added = false; 922 920 ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); 923 921 924 922 rc = dir_emit(ctx, name, namelen, ino, fattr->cf_dtype); ··· 927 923 return rc; 928 924 929 925 if (cfid) { 926 + /* Cost of this entry */ 927 + delta_bytes = sizeof(struct cached_dirent) + (size_t)namelen + 1; 928 + 930 929 mutex_lock(&cfid->dirents.de_mutex); 931 - add_cached_dirent(&cfid->dirents, ctx, name, namelen, 932 - fattr, file); 930 + added = add_cached_dirent(&cfid->dirents, ctx, name, namelen, 931 + fattr, file); 933 932 mutex_unlock(&cfid->dirents.de_mutex); 933 + 934 + if (added) { 935 + /* per-tcon then global for consistency with free path */ 936 + atomic64_add((long long)delta_bytes, &cfid->cfids->total_dirents_bytes); 937 + atomic_long_inc(&cfid->cfids->total_dirents_entries); 938 + atomic64_add((long long)delta_bytes, &cifs_dircache_bytes_used); 939 + } 934 940 } 935 941 936 942 return rc;
+7 -15
fs/smb/client/smb2ops.c
··· 954 954 955 955 rc = open_cached_dir(xid, tcon, full_path, cifs_sb, true, &cfid); 956 956 if (!rc) { 957 - if (cfid->has_lease) { 958 - close_cached_dir(cfid); 959 - return 0; 960 - } 961 957 close_cached_dir(cfid); 958 + return 0; 962 959 } 963 960 964 961 utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb); ··· 4216 4219 static void *smb2_aead_req_alloc(struct crypto_aead *tfm, const struct smb_rqst *rqst, 4217 4220 int num_rqst, const u8 *sig, u8 **iv, 4218 4221 struct aead_request **req, struct sg_table *sgt, 4219 - unsigned int *num_sgs, size_t *sensitive_size) 4222 + unsigned int *num_sgs) 4220 4223 { 4221 4224 unsigned int req_size = sizeof(**req) + crypto_aead_reqsize(tfm); 4222 4225 unsigned int iv_size = crypto_aead_ivsize(tfm); ··· 4233 4236 len += req_size; 4234 4237 len = ALIGN(len, __alignof__(struct scatterlist)); 4235 4238 len += array_size(*num_sgs, sizeof(struct scatterlist)); 4236 - *sensitive_size = len; 4237 4239 4238 - p = kvzalloc(len, GFP_NOFS); 4240 + p = kzalloc(len, GFP_NOFS); 4239 4241 if (!p) 4240 4242 return ERR_PTR(-ENOMEM); 4241 4243 ··· 4248 4252 4249 4253 static void *smb2_get_aead_req(struct crypto_aead *tfm, struct smb_rqst *rqst, 4250 4254 int num_rqst, const u8 *sig, u8 **iv, 4251 - struct aead_request **req, struct scatterlist **sgl, 4252 - size_t *sensitive_size) 4255 + struct aead_request **req, struct scatterlist **sgl) 4253 4256 { 4254 4257 struct sg_table sgtable = {}; 4255 4258 unsigned int skip, num_sgs, i, j; 4256 4259 ssize_t rc; 4257 4260 void *p; 4258 4261 4259 - p = smb2_aead_req_alloc(tfm, rqst, num_rqst, sig, iv, req, &sgtable, 4260 - &num_sgs, sensitive_size); 4262 + p = smb2_aead_req_alloc(tfm, rqst, num_rqst, sig, iv, req, &sgtable, &num_sgs); 4261 4263 if (IS_ERR(p)) 4262 4264 return ERR_CAST(p); 4263 4265 ··· 4344 4350 DECLARE_CRYPTO_WAIT(wait); 4345 4351 unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize); 4346 4352 void *creq; 4347 - size_t sensitive_size; 4348 4353 4349 4354 rc = smb2_get_enc_key(server, le64_to_cpu(tr_hdr->SessionId), enc, key); 4350 4355 if (rc) { ··· 4369 4376 return rc; 4370 4377 } 4371 4378 4372 - creq = smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg, 4373 - &sensitive_size); 4379 + creq = smb2_get_aead_req(tfm, rqst, num_rqst, sign, &iv, &req, &sg); 4374 4380 if (IS_ERR(creq)) 4375 4381 return PTR_ERR(creq); 4376 4382 ··· 4399 4407 if (!rc && enc) 4400 4408 memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE); 4401 4409 4402 - kvfree_sensitive(creq, sensitive_size); 4410 + kfree_sensitive(creq); 4403 4411 return rc; 4404 4412 } 4405 4413
+9 -9
fs/smb/client/smb2pdu.c
··· 240 240 */ 241 241 if (smb2_command != SMB2_TREE_DISCONNECT) { 242 242 spin_unlock(&tcon->tc_lock); 243 - cifs_dbg(FYI, "can not send cmd %d while umounting\n", 244 - smb2_command); 243 + cifs_tcon_dbg(FYI, "can not send cmd %d while umounting\n", 244 + smb2_command); 245 245 return -ENODEV; 246 246 } 247 247 } ··· 296 296 return 0; 297 297 } 298 298 spin_unlock(&ses->chan_lock); 299 - cifs_dbg(FYI, "sess reconnect mask: 0x%lx, tcon reconnect: %d", 300 - tcon->ses->chans_need_reconnect, 301 - tcon->need_reconnect); 299 + cifs_tcon_dbg(FYI, "sess reconnect mask: 0x%lx, tcon reconnect: %d\n", 300 + tcon->ses->chans_need_reconnect, 301 + tcon->need_reconnect); 302 302 303 303 mutex_lock(&ses->session_mutex); 304 304 /* ··· 392 392 393 393 rc = cifs_tree_connect(0, tcon); 394 394 395 - cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc); 395 + cifs_tcon_dbg(FYI, "reconnect tcon rc = %d\n", rc); 396 396 if (rc) { 397 397 /* If sess reconnected but tcon didn't, something strange ... */ 398 398 mutex_unlock(&ses->session_mutex); 399 - cifs_dbg(VFS, "reconnect tcon failed rc = %d\n", rc); 399 + cifs_tcon_dbg(VFS, "reconnect tcon failed rc = %d\n", rc); 400 400 goto out; 401 401 } 402 402 ··· 442 442 from_reconnect); 443 443 goto skip_add_channels; 444 444 } else if (rc) 445 - cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n", 446 - __func__, rc); 445 + cifs_tcon_dbg(FYI, "%s: failed to query server interfaces: %d\n", 446 + __func__, rc); 447 447 448 448 if (ses->chan_max > ses->chan_count && 449 449 ses->iface_count &&
+10 -3
fs/smb/client/transport.c
··· 22 22 #include <linux/mempool.h> 23 23 #include <linux/sched/signal.h> 24 24 #include <linux/task_io_accounting_ops.h> 25 + #include <linux/task_work.h> 25 26 #include "cifspdu.h" 26 27 #include "cifsglob.h" 27 28 #include "cifsproto.h" ··· 174 173 * send a packet. In most cases if we fail to send 175 174 * after the retries we will kill the socket and 176 175 * reconnect which may clear the network problem. 176 + * 177 + * Even if regular signals are masked, EINTR might be 178 + * propagated from sk_stream_wait_memory() to here when 179 + * TIF_NOTIFY_SIGNAL is used for task work. For example, 180 + * certain io_uring completions will use that. Treat 181 + * having EINTR with pending task work the same as EAGAIN 182 + * to avoid unnecessary reconnects. 177 183 */ 178 184 rc = sock_sendmsg(ssocket, smb_msg); 179 - if (rc == -EAGAIN) { 185 + if (rc == -EAGAIN || unlikely(rc == -EINTR && task_work_pending(current))) { 180 186 retries++; 181 187 if (retries >= 14 || 182 188 (!server->noblocksnd && (retries > 2))) { ··· 331 323 break; 332 324 total_len += sent; 333 325 } 334 - 335 - } 326 + } 336 327 337 328 unmask: 338 329 sigprocmask(SIG_SETMASK, &oldmask, NULL);
-1
fs/smb/common/Makefile
··· 3 3 # Makefile for Linux filesystem routines that are shared by client and server. 4 4 # 5 5 6 - obj-$(CONFIG_SMBFS) += cifs_arc4.o 7 6 obj-$(CONFIG_SMBFS) += cifs_md4.o
-23
fs/smb/common/arc4.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ */ 2 - /* 3 - * Common values for ARC4 Cipher Algorithm 4 - */ 5 - 6 - #ifndef _CRYPTO_ARC4_H 7 - #define _CRYPTO_ARC4_H 8 - 9 - #include <linux/types.h> 10 - 11 - #define ARC4_MIN_KEY_SIZE 1 12 - #define ARC4_MAX_KEY_SIZE 256 13 - #define ARC4_BLOCK_SIZE 1 14 - 15 - struct arc4_ctx { 16 - u32 S[256]; 17 - u32 x, y; 18 - }; 19 - 20 - int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len); 21 - void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len); 22 - 23 - #endif /* _CRYPTO_ARC4_H */
-75
fs/smb/common/cifs_arc4.c
··· 1 - // SPDX-License-Identifier: GPL-2.0-or-later 2 - /* 3 - * Cryptographic API 4 - * 5 - * ARC4 Cipher Algorithm 6 - * 7 - * Jon Oberheide <jon@oberheide.org> 8 - */ 9 - 10 - #include <linux/module.h> 11 - #include "arc4.h" 12 - 13 - MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); 14 - MODULE_LICENSE("GPL"); 15 - 16 - int cifs_arc4_setkey(struct arc4_ctx *ctx, const u8 *in_key, unsigned int key_len) 17 - { 18 - int i, j = 0, k = 0; 19 - 20 - ctx->x = 1; 21 - ctx->y = 0; 22 - 23 - for (i = 0; i < 256; i++) 24 - ctx->S[i] = i; 25 - 26 - for (i = 0; i < 256; i++) { 27 - u32 a = ctx->S[i]; 28 - 29 - j = (j + in_key[k] + a) & 0xff; 30 - ctx->S[i] = ctx->S[j]; 31 - ctx->S[j] = a; 32 - if (++k >= key_len) 33 - k = 0; 34 - } 35 - 36 - return 0; 37 - } 38 - EXPORT_SYMBOL_GPL(cifs_arc4_setkey); 39 - 40 - void cifs_arc4_crypt(struct arc4_ctx *ctx, u8 *out, const u8 *in, unsigned int len) 41 - { 42 - u32 *const S = ctx->S; 43 - u32 x, y, a, b; 44 - u32 ty, ta, tb; 45 - 46 - if (len == 0) 47 - return; 48 - 49 - x = ctx->x; 50 - y = ctx->y; 51 - 52 - a = S[x]; 53 - y = (y + a) & 0xff; 54 - b = S[y]; 55 - 56 - do { 57 - S[y] = a; 58 - a = (a + b) & 0xff; 59 - S[x] = b; 60 - x = (x + 1) & 0xff; 61 - ta = S[x]; 62 - ty = (y + ta) & 0xff; 63 - tb = S[ty]; 64 - *out++ = *in++ ^ S[a]; 65 - if (--len == 0) 66 - break; 67 - y = ty; 68 - a = ta; 69 - b = tb; 70 - } while (true); 71 - 72 - ctx->x = x; 73 - ctx->y = y; 74 - } 75 - EXPORT_SYMBOL_GPL(cifs_arc4_crypt);
+1
fs/smb/server/Kconfig
··· 10 10 select CRYPTO_MD5 11 11 select CRYPTO_HMAC 12 12 select CRYPTO_ECB 13 + select CRYPTO_LIB_ARC4 13 14 select CRYPTO_LIB_DES 14 15 select CRYPTO_LIB_SHA256 15 16 select CRYPTO_SHA256
+4 -5
fs/smb/server/auth.c
··· 20 20 #include "glob.h" 21 21 22 22 #include <linux/fips.h> 23 + #include <crypto/arc4.h> 23 24 #include <crypto/des.h> 24 25 25 26 #include "server.h" ··· 30 29 #include "mgmt/user_config.h" 31 30 #include "crypto_ctx.h" 32 31 #include "transport_ipc.h" 33 - #include "../common/arc4.h" 34 32 35 33 /* 36 34 * Fixed format data defining GSS header and fixed string ··· 365 365 if (!ctx_arc4) 366 366 return -ENOMEM; 367 367 368 - cifs_arc4_setkey(ctx_arc4, sess->sess_key, 369 - SMB2_NTLMV2_SESSKEY_SIZE); 370 - cifs_arc4_crypt(ctx_arc4, sess->sess_key, 371 - (char *)authblob + sess_key_off, sess_key_len); 368 + arc4_setkey(ctx_arc4, sess->sess_key, SMB2_NTLMV2_SESSKEY_SIZE); 369 + arc4_crypt(ctx_arc4, sess->sess_key, 370 + (char *)authblob + sess_key_off, sess_key_len); 372 371 kfree_sensitive(ctx_arc4); 373 372 } 374 373