projects/linux·commit ce14fe4c

Merge tag 'cifs-fixes-7.3-rc1' of https://git.manguebit.org/linux

ce14fe4c · Linus Torvalds <[email protected]> · 2026-08-24 18:11:49 -07:00

Pull smb client updates from Paulo Alcantara:

 - clear sensitive data after use (stack and heap cryptographic
   keys/hashes)

 - file size and cache synchronization fixes (fscache cookie
   serialization and truncation handling)

 - protocol validation and buffer safety fixes (prevent OOB access and
   loff_t underflow)

 - metadata and POSIX attribute fixes (proper hard-link counts and
   setuid/setgid stripping)

 - DFS cache and unmount fixes (prevent target-hint UAF and unmount
   hangs)

 - general client improvements (fix read request leaks, stats loops,
   handle servers that don't support O_TMPFILE)

* tag 'cifs-fixes-7.3-rc1' of https://git.manguebit.org/linux: (33 commits)
  cifs: fix loff_t underflow in cifs_remap_file_range() when len == 0
  smb: client: reject a tree connect response whose byte count is too small
  cifs: call pagecache_isize_extended() in cifs_setsize() when extending
  smb: client: fix copy-paste error in WSL EA length accounting for $LXDEV
  smb: client: remove redundant NULL check before kfree()
  smb: client: restore the data_offset bound in is_valid_oplock_break()
  cifs: clear tcon after cifsFileInfo_put() in cifs_file_set_size()
  smb: client: Avoid leaking sensitive data to the heap in connect.c
  smb: client: Clear sensitive stack data in smb1encrypt.c
  smb: client: Clear sensitive stack data in cifsencrypt.c
  smb: client: Clear sensitive stack and heap data in smb2ops.c
  smb: client: Clear sensitive stack data in smb2transport.c
  Revert "cifs: remove all cifs files before kill super"
  smb: client: fix use-before-check of ReparseDataLength in reparse_buf_ptr()
  smb: client: fix ALIGN() overflow in symlink_data() error context loop
  smb: client: simplify __build_path_from_dentry_optional_prefix()
  smb: client: fix UAF and buffer leak in cifs_check_trans2() for malformed secondary T2
  smb: client: fix OOB read/write from unvalidated DataOffset in coalesce_t2()
  smb/client: decode reparse metadata using its payload type
  smb/client: preserve open info type across compound queries
  ...
Commit
ce14fe4cd756d2ad75a1f5b53816872b4e69f7cc
Parents
66498c75 · 6c322f5c

Merge commit. Changes below are compared with the first parent: 66498c75.

Changes

22 files changed · +223 −108

Only the first 600 diff lines are shown. Download the complete patch.

fs/smb/client/cifs_debug.c

View file
diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
index 4ed4f55..3761d3a 100644
--- a/fs/smb/client/cifs_debug.c
+++ b/fs/smb/client/cifs_debug.c
@@ -754,7 +754,7 @@ static ssize_t cifs_stats_proc_write(struct file *file,
atomic_set(&server->smb2slowcmd[i], 0);
server->time_per_cmd[i] = 0;
server->slowest_cmd[i] = 0;
- server->fastest_cmd[0] = 0;
+ server->fastest_cmd[i] = 0;
}
#endif /* CONFIG_CIFS_STATS2 */
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {

fs/smb/client/cifsencrypt.c

View file
diff --git a/fs/smb/client/cifsencrypt.c b/fs/smb/client/cifsencrypt.c
index 34804e9..71a2a59 100644
--- a/fs/smb/client/cifsencrypt.c
+++ b/fs/smb/client/cifsencrypt.c
@@ -249,12 +249,13 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
E_md4hash(ses->password, nt_hash, nls_cp);
hmac_md5_init_usingrawkey(&hmac_ctx, nt_hash, CIFS_NTHASH_SIZE);
+ memzero_explicit(nt_hash, sizeof(nt_hash));
/* convert ses->user_name to unicode */
len = ses->user_name ? strlen(ses->user_name) : 0;
user = kmalloc(2 + (len * 2), GFP_KERNEL);
if (user == NULL)
- return -ENOMEM;
+ goto out_nomem;
if (len) {
len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp);
@@ -272,7 +273,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
domain = kmalloc(2 + (len * 2), GFP_KERNEL);
if (domain == NULL)
- return -ENOMEM;
+ goto out_nomem;
len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
nls_cp);
@@ -284,7 +285,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
server = kmalloc(2 + (len * 2), GFP_KERNEL);
if (server == NULL)
- return -ENOMEM;
+ goto out_nomem;
len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len, nls_cp);
hmac_md5_update(&hmac_ctx, (const u8 *)server, 2 * len);
@@ -293,6 +294,10 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
hmac_md5_final(&hmac_ctx, ntlmv2_hash);
return 0;
+
+out_nomem:
+ memzero_explicit(&hmac_ctx, sizeof(hmac_ctx));
+ return -ENOMEM;
}
static void CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
@@ -463,6 +468,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
rc = 0;
unlock:
cifs_server_unlock(ses->server);
+ memzero_explicit(ntlmv2_hash, sizeof(ntlmv2_hash));
setup_ntlmv2_rsp_ret:
kfree_sensitive(tiblob);

fs/smb/client/cifsfs.c

View file
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index a1dacc7..7ecd70e 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -1413,8 +1413,19 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
*/
lock_two_nondirectories(target_inode, src_inode);
- if (len == 0)
- len = src_inode->i_size - off;
+ if (len == 0) {
+ loff_t src_size = i_size_read(src_inode);
+
+ if (off > src_size) {
+ rc = -EINVAL;
+ goto unlock;
+ }
+ len = src_size - off;
+ if (!len) {
+ rc = 0;
+ goto unlock;
+ }
+ }
cifs_dbg(FYI, "clone range\n");
@@ -1466,11 +1477,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
if (target_tcon->ses->server->ops->duplicate_extents) {
rc = target_tcon->ses->server->ops->duplicate_extents(xid,
smb_file_src, smb_file_target, off, len, destoff);
- if (rc == 0 && new_size > i_size) {
- truncate_setsize(target_inode, new_size);
- fscache_resize_cookie(cifs_inode_cookie(target_inode),
- new_size);
- } else if (rc == -EOPNOTSUPP) {
+ if (rc == -EOPNOTSUPP) {
/*
* copy_file_range syscall man page indicates EINVAL
* is returned e.g when "fd_in and fd_out refer to the

fs/smb/client/cifsfs.h

View file
diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h
index 287c632..0c85daa 100644
--- a/fs/smb/client/cifsfs.h
+++ b/fs/smb/client/cifsfs.h
@@ -147,6 +147,7 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, struct file *src_file,
long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg);
void cifs_setsize(struct inode *inode, loff_t offset);
+void cifs_resize_file_locked(struct inode *inode, loff_t offset);
struct fs_context;
struct smb3_fs_context;

fs/smb/client/cifssmb.c

View file
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index 1f77512..f5aad5f 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -615,6 +615,11 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
tcon->tid = smb_buffer_response->Tid;
bcc_ptr = pByteArea(smb_buffer_response);
bytes_left = get_bcc(smb_buffer_response);
+ if (bytes_left < 2) {
+ rc = smb_EIO2(smb_eio_trace_tcon_bcc_too_small,
+ bytes_left, 2);
+ goto out;
+ }
length = strnlen(bcc_ptr, bytes_left - 2);
if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
is_unicode = true;
@@ -670,6 +675,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
reset_cifs_unix_caps(xid, tcon, NULL, NULL);
}
}
+out:
cifs_buf_release(smb_buffer);
return rc;
}

fs/smb/client/connect.c

View file
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index ba749ec..bcd7f1a 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -1143,7 +1143,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
put_net(cifs_net_ns(server));
kfree(server->leaf_fullpath);
kfree(server->hostname);
- kfree(server);
+ kfree_sensitive(server);
length = atomic_dec_return(&tcpSesAllocCount);
if (length > 0)
@@ -4003,9 +4003,6 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
}
spin_unlock(&cifs_sb->tlink_tree_lock);
- flush_workqueue(serverclose_wq);
- flush_workqueue(fileinfo_put_wq);
-
kfree(cifs_sb->prepath);
call_rcu(&cifs_sb->rcu, delayed_free);
}

fs/smb/client/dfs_cache.c

View file
diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c
index 8cd93cd..86dba25 100644
--- a/fs/smb/client/dfs_cache.c
+++ b/fs/smb/client/dfs_cache.c
@@ -122,6 +122,8 @@ static inline void free_tgts(struct cache_entry *ce)
kfree(t->name);
kfree(t);
}
+
+ WRITE_ONCE(ce->tgthint, NULL);
}
static inline void flush_cache_ent(struct cache_entry *ce)
@@ -869,13 +871,22 @@ int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses, const struct nl
goto out_free_path;
}
- if (ref)
- rc = setup_referral(path, ce, ref, get_tgt_name(ce));
- else
+ if (ref) {
+ char *target = get_tgt_name(ce);
+
+ if (IS_ERR(target)) {
+ rc = PTR_ERR(target);
+ goto out_unlock;
+ }
+ rc = setup_referral(path, ce, ref, target);
+ } else {
rc = 0;
+ }
+
if (!rc && tgt_list)
rc = get_targets(ce, tgt_list);
+out_unlock:
up_read(&htable_rw_lock);
out_free_path:
@@ -915,10 +926,17 @@ int dfs_cache_noreq_find(const char *path, struct dfs_info3_param *ref,
goto out_unlock;
}
- if (ref)
- rc = setup_referral(path, ce, ref, get_tgt_name(ce));
- else
+ if (ref) {
+ char *target = get_tgt_name(ce);
+
+ if (IS_ERR(target)) {
+ rc = PTR_ERR(target);
+ goto out_unlock;
+ }
+ rc = setup_referral(path, ce, ref, target);
+ } else {
rc = 0;
+ }
if (!rc && tgt_list)
rc = get_targets(ce, tgt_list);
@@ -959,7 +977,8 @@ void dfs_cache_noreq_update_tgthint(const char *path, const struct dfs_cache_tgt
t = READ_ONCE(ce->tgthint);
- if (unlikely(!strcasecmp(it->it_name, t->name)))
+ /* Check 't' in case ce->tgthint was cleared by free_tgts() */
+ if (t && unlikely(!strcasecmp(it->it_name, t->name)))
goto out_unlock;
list_for_each_entry(t, &ce->tlist, list) {

fs/smb/client/dir.c

View file
diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
index 7803bd5..6fa6d48 100644
--- a/fs/smb/client/dir.c
+++ b/fs/smb/client/dir.c
@@ -115,11 +115,7 @@ char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *pa
}
if (dirsep != '/') {
/* BB test paths to Windows with '/' in the midst of prepath */
- char *p;
-
- for (p = s; *p; p++)
- if (*p == '/')
- *p = dirsep;
+ strreplace(s, '/', dirsep);
}
if (dfsplen) {
s -= dfsplen;
@@ -1138,6 +1134,8 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
} while (unlikely(rc == -EEXIST) && ++retries < max_retries);
if (rc) {
+ if (rc == -ENOENT)
+ rc = -EOPNOTSUPP;
cifs_del_pending_open(&open);
goto out;
}

fs/smb/client/file.c

View file
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index ac89c1b..389083f 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -1016,6 +1016,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
if (!rc) {
netfs_resize_file(&cinode->netfs, 0, true);
cifs_setsize(inode, 0);
+ cifs_invalidate_cache(inode, 0);
}
}
if (cfile)

fs/smb/client/inode.c

View file
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index 18f562a..12ed8db 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -1215,7 +1215,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
break;
case IO_REPARSE_TAG_INTERNAL:
rc = 0;
- if (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY) {
+ if (cifs_open_data_attrs(data) & ATTR_DIRECTORY) {
cifs_create_junction_fattr(fattr, sb);
goto out;
}
@@ -1239,7 +1239,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
*/
if (rc == -EOPNOTSUPP &&
IS_REPARSE_TAG_NAME_SURROGATE(data->reparse.tag) &&
- (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY)) {
+ (cifs_open_data_attrs(data) & ATTR_DIRECTORY)) {
rc = 0;
cifs_create_junction_fattr(fattr, sb);
goto out;
@@ -1257,13 +1257,14 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
}
if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK && !rc) {
- bool directory = le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY;
+ bool directory = cifs_open_data_attrs(data) & ATTR_DIRECTORY;
+
rc = smb2_fix_symlink_target_type(&data->symlink_target, directory, cifs_sb);
}
break;
}
- if (tcon->posix_extensions)
+ if (data->contains_posix_file_info)
smb311_posix_info_to_fattr(fattr, data, sb);
else
cifs_open_info_to_fattr(fattr, data, sb);
@@ -2655,11 +2656,8 @@ unlink_target:
if (d_really_is_positive(target_dentry)) {
if (!rc) {
struct inode *inode = d_inode(target_dentry);
- /*
- * Samba and ksmbd servers allow renaming a target
- * directory that is open, so make sure to update
- * ->i_nlink and then mark it as delete pending.
- */
+
+ /* Update the target link count after rename. */
if (S_ISDIR(inode->i_mode)) {
drop_cached_dir_by_name(xid, tcon, to_name, cifs_sb);
spin_lock(&inode->i_lock);
@@ -2670,6 +2668,10 @@ unlink_target:
CIFS_I(inode)->time = 0; /* force reval */
inode_set_ctime_current(inode);
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
+ } else {
+ cifs_mark_open_handles_for_deleted_file(inode, to_name);
+ cifs_drop_nlink(inode);
+ inode_set_ctime_current(inode);
}
} else if (rc == -EACCES || rc == -EEXIST) {
/*
@@ -3064,9 +3066,27 @@ void cifs_setsize(struct inode *inode, loff_t offset)
inode->i_blocks = blocks;
spin_unlock(&inode->i_lock);
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
+ if (offset > old_size)
+ pagecache_isize_extended(inode, old_size, offset);
truncate_pagecache(inode, offset);
netfs_wait_for_outstanding_io(inode);
- fscache_resize_cookie(cifs_inode_cookie(inode), offset);
+}
+
+void cifs_resize_file_locked(struct inode *inode, loff_t offset)
+{
+ struct fscache_cookie *cookie = cifs_inode_cookie(inode);
+
+ lockdep_assert_held_write(&inode->i_rwsem);
+
+ netfs_resize_file(netfs_inode(inode), offset, true);
+ cifs_setsize(inode, offset);
+
+ if (!cookie)
+ return;
+
+ fscache_use_cookie(cookie, true);
+ fscache_resize_cookie(cookie, offset);
+ cifs_fscache_unuse_inode_cookie(inode, true);
}
int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
@@ -3107,6 +3127,7 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
size, false);
cifs_dbg(FYI, "%s: set_file_size: rc = %d\n", __func__, rc);
cifsFileInfo_put(open_file);
+ tcon = NULL;
}
}
@@ -3132,10 +3153,8 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
cifs_put_tlink(tlink);
set_size_out:
- if (rc == 0) {
- netfs_resize_file(&cifsInode->netfs, size, true);
- cifs_setsize(inode, size);
- }
+ if (rc == 0)
+ cifs_resize_file_locked(inode, size);
return rc;
}
@@ -3221,9 +3240,13 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
attrs->ia_valid &= ~(ATTR_CTIME | ATTR_MTIME);
}
- /* skip mode change if it's just for clearing setuid/setgid */
- if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
- attrs->ia_valid &= ~ATTR_MODE;
+ /*
+ * This function is only called when Unix extensions are in effect,
+ * so the mode is always sent to and stored on the server. Do not
+ * skip the mode change when clearing setuid/setgid bits: dropping
+ * ATTR_MODE here would leave those bits set on the server after a
+ * write, which is a security issue.
+ */
args = kmalloc_obj(*args);
if (args == NULL) {
@@ -3296,13 +3319,6 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
if (rc)
goto out;
- if ((attrs->ia_valid & ATTR_SIZE) &&
- attrs->ia_size != i_size_read(inode)) {
- truncate_setsize(inode, attrs->ia_size);
- netfs_resize_file(&cifsInode->netfs, attrs->ia_size, true);
- fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size);
- }
-
setattr_copy(&nop_mnt_idmap, inode, attrs);
mark_inode_dirty(inode);
@@ -3432,8 +3448,23 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
}
- /* skip mode change if it's just for clearing setuid/setgid */
- if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+ /*
+ * Skip the mode change if it is only being done to clear the
+ * setuid/setgid bits *and* the mode is emulated via the DOS
+ * read-only attribute (the default, non-ACL case), which cannot
+ * represent the setuid/setgid bits anyway.
+ *
+ * When the mode is instead stored on the server - i.e. with the
+ * cifsacl or modefromsid mount options (via an ACL) or with the
+ * SMB3.1.1 POSIX extensions - the cleared mode must be pushed to
+ * the server. Dropping ATTR_MODE here would leave the setuid/
+ * setgid bit set on the server after a write, which is a security
+ * issue (the bits are not stripped as they are on local
+ * filesystems).
+ */
+ if ((attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID)) &&
+ !((sbflags & (CIFS_MOUNT_CIFS_ACL | CIFS_MOUNT_MODE_FROM_SID)) ||
+ cifs_sb_master_tcon(cifs_sb)->posix_extensions))
attrs->ia_valid &= ~ATTR_MODE;
if (attrs->ia_valid & ATTR_MODE) {
@@ -3508,13 +3539,6 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
if (rc)
goto cifs_setattr_exit;
- if ((attrs->ia_valid & ATTR_SIZE) &&
- attrs->ia_size != i_size_read(inode)) {
- truncate_setsize(inode, attrs->ia_size);
- netfs_resize_file(&cifsInode->netfs, attrs->ia_size, true);
- fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size);
- }
-
setattr_copy(&nop_mnt_idmap, inode, attrs);
mark_inode_dirty(inode);

fs/smb/client/ioctl.c

View file
diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c
index 9fa743b..2f152d7 100644
--- a/fs/smb/client/ioctl.c
+++ b/fs/smb/client/ioctl.c
@@ -133,8 +133,7 @@ static int cifs_set_compression_by_path(unsigned int xid, struct file *filep,
close:
server->ops->close(xid, tcon, &fid);
- if (tmp_cfile)
- kfree(tmp_cfile);
+ kfree(tmp_cfile);
cifs_free_open_info(&data);
out:
free_dentry_path(page);

fs/smb/client/reparse.h

View file
diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
index 0164dc4..49efd85 100644
--- a/fs/smb/client/reparse.h
+++ b/fs/smb/client/reparse.h
@@ -98,15 +98,21 @@ static inline bool reparse_inode_match(struct inode *inode,
timespec64_equal(&ctime, &fattr->cf_ctime);
}
+static inline u32 cifs_open_data_attrs(const struct cifs_open_info_data *data)
+{
+ if (data->contains_posix_file_info)
+ return le32_to_cpu(data->posix_fi.DosAttributes);
+
+ return le32_to_cpu(data->fi.Attributes);
+}
+
static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
{
- u32 attrs;
- bool ret;
+ u32 attrs = cifs_open_data_attrs(data);
if (data->contains_posix_file_info) {
struct smb311_posix_qinfo *fi = &data->posix_fi;
- attrs = le32_to_cpu(fi->DosAttributes);
if (data->reparse_point) {
attrs |= ATTR_REPARSE_POINT;
fi->DosAttributes = cpu_to_le32(attrs);
@@ -115,16 +121,13 @@ static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
} else {
struct smb2_file_all_info *fi = &data->fi;
- attrs = le32_to_cpu(fi->Attributes);
if (data->reparse_point) {
attrs |= ATTR_REPARSE_POINT;
fi->Attributes = cpu_to_le32(attrs);
}
}
- ret = attrs & ATTR_REPARSE_POINT;
-
- return ret;
+ return attrs & ATTR_REPARSE_POINT;
}
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,

fs/smb/client/smb1encrypt.c

View file
diff --git a/fs/smb/client/smb1encrypt.c b/fs/smb/client/smb1encrypt.c
index bf10fde..c9eb68f 100644
--- a/fs/smb/client/smb1encrypt.c
+++ b/fs/smb/client/smb1encrypt.c
@@ -81,6 +81,7 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
else
memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+ memzero_explicit(smb_signature, sizeof(smb_signature));
return rc;
}
@@ -126,15 +127,13 @@ int cifs_verify_signature(struct smb_rqst *rqst,
rc = cifs_calc_signature(rqst, server, what_we_think_sig_should_be);
cifs_server_unlock(server);
- if (rc)
- return rc;
-
-/* cifs_dump_mem("what we think it should be: ",
- what_we_think_sig_should_be, 16); */
-
- if (crypto_memneq(server_response_sig, what_we_think_sig_should_be, 8))
- return -EACCES;
- else
- return 0;
+ if (!rc) {
+ if (crypto_memneq(server_response_sig,
+ what_we_think_sig_should_be, 8))
+ rc = -EACCES;
+ }
+ memzero_explicit(what_we_think_sig_should_be,
+ sizeof(what_we_think_sig_should_be));
+ return rc;
}

fs/smb/client/smb1misc.c

View file
diff --git a/fs/smb/client/smb1misc.c b/fs/smb/client/smb1misc.c
index ba56023..cdfbbff 100644
--- a/fs/smb/client/smb1misc.c
+++ b/fs/smb/client/smb1misc.c
@@ -80,7 +80,8 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
(struct smb_com_transaction_change_notify_rsp *)buf;
struct file_notify_information *pnotify;
__u32 data_offset = 0;
- size_t len = srv->total_read - srv->pdu_size;
+ /* total_read excludes the RFC1002 preamble */
+ size_t len = srv->total_read;
if (get_bcc(buf) > sizeof(struct file_notify_information)) {
data_offset = le32_to_cpu(pSMBr->DataOffset);

fs/smb/client/smb1ops.c

View file
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index dc5a8c1..3ac4126 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -542,6 +542,7 @@ static int cifs_query_path_info(const unsigned int xid,
data->reparse_point = false;
data->adjust_tz = false;
+ data->unknown_nlink = false;
/*
* First try CIFSSMBQPathInfo() function which returns more info
@@ -608,6 +609,7 @@ static int cifs_query_path_info(const unsigned int xid,
fi.EASize = di->EaSize;
}
fi.NumberOfLinks = cpu_to_le32(1);
+ data->unknown_nlink = true;
fi.DeletePending = 0;
fi.Directory = !!(le32_to_cpu(fi.Attributes) & ATTR_DIRECTORY);
cifs_buf_release(search_info.ntwrk_buf_start);
@@ -630,6 +632,8 @@ static int cifs_query_path_info(const unsigned int xid,
rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls,
cifs_remap(cifs_sb));
data->adjust_tz = true;
+ if (!rc)
+ data->unknown_nlink = true;
} else if ((rc == -EOPNOTSUPP || rc == -EINVAL) && non_unicode_wildcard) {
/* Path with non-UNICODE wildcard character cannot exist. */
rc = -ENOENT;

This diff is incomplete. Download the complete patch.

fs/smb/client/smb1transport.c

View file

This diff is incomplete. Download the complete patch.

fs/smb/client/smb2file.c

View file

This diff is incomplete. Download the complete patch.

fs/smb/client/smb2inode.c

View file

This diff is incomplete. Download the complete patch.

fs/smb/client/smb2ops.c

View file

This diff is incomplete. Download the complete patch.

fs/smb/client/smb2pdu.c

View file

This diff is incomplete. Download the complete patch.

fs/smb/client/smb2transport.c

View file

This diff is incomplete. Download the complete patch.

fs/smb/client/trace.h

View file

This diff is incomplete. Download the complete patch.