Merge tag 'v7.0-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:
 - Fix reconnect when using non-default port
 - Fix default retransmission behavior
 - Fix open handle reuse in cifs_open
 - Fix export for smb2-mapperror-test
 - Fix potential corruption on write retry
 - Fix potentially uninitialized superblock flags
 - Fix missing O_DIRECT and O_SYNC flags on create

* tag 'v7.0-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: make default value of retrans as zero
  smb: client: fix open handle lookup in cifs_open()
  smb: client: fix iface port assignment in parse_server_interfaces
  smb/client: only export symbol for 'smb2maperror-test' module
  smb: client: fix in-place encryption corruption in SMB2_write()
  smb: client: fix sbflags initialization
  smb: client: fix atomic open with O_DIRECT & O_SYNC
This commit is contained in:
Linus Torvalds
2026-03-13 10:46:32 -07:00
13 changed files with 151 additions and 99 deletions

View File

@@ -1489,7 +1489,7 @@ struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
struct cifsFileInfo *open_file = NULL;
if (inode)
open_file = find_readable_file(CIFS_I(inode), true);
open_file = find_readable_file(CIFS_I(inode), FIND_FSUID_ONLY);
if (!open_file)
return get_cifs_acl_by_path(cifs_sb, path, pacllen, info);

View File

@@ -1269,7 +1269,7 @@ static int cifs_precopy_set_eof(struct inode *src_inode, struct cifsInodeInfo *s
struct cifsFileInfo *writeable_srcfile;
int rc = -EINVAL;
writeable_srcfile = find_writable_file(src_cifsi, FIND_WR_FSUID_ONLY);
writeable_srcfile = find_writable_file(src_cifsi, FIND_FSUID_ONLY);
if (writeable_srcfile) {
if (src_tcon->ses->server->ops->set_file_size)
rc = src_tcon->ses->server->ops->set_file_size(

View File

@@ -20,6 +20,7 @@
#include <linux/utsname.h>
#include <linux/sched/mm.h>
#include <linux/netfs.h>
#include <linux/fcntl.h>
#include "cifs_fs_sb.h"
#include "cifsacl.h"
#include <crypto/internal/hash.h>
@@ -1884,12 +1885,12 @@ static inline bool is_replayable_error(int error)
}
/* cifs_get_writable_file() flags */
enum cifs_writable_file_flags {
FIND_WR_ANY = 0U,
FIND_WR_FSUID_ONLY = (1U << 0),
FIND_WR_WITH_DELETE = (1U << 1),
FIND_WR_NO_PENDING_DELETE = (1U << 2),
enum cifs_find_flags {
FIND_ANY = 0U,
FIND_FSUID_ONLY = (1U << 0),
FIND_WITH_DELETE = (1U << 1),
FIND_NO_PENDING_DELETE = (1U << 2),
FIND_OPEN_FLAGS = (1U << 3),
};
#define MID_FREE 0
@@ -2375,4 +2376,14 @@ static inline bool cifs_forced_shutdown(const struct cifs_sb_info *sbi)
return cifs_sb_flags(sbi) & CIFS_MOUNT_SHUTDOWN;
}
static inline int cifs_open_create_options(unsigned int oflags, int opts)
{
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
if (oflags & O_SYNC)
opts |= CREATE_WRITE_THROUGH;
if (oflags & O_DIRECT)
opts |= CREATE_NO_BUFFER;
return opts;
}
#endif /* _CIFS_GLOB_H */

View File

@@ -138,12 +138,14 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata,
ssize_t result);
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
int flags);
int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
unsigned int find_flags, unsigned int open_flags,
struct cifsFileInfo **ret_file);
int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, int flags,
struct cifsFileInfo **ret_file);
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
bool fsuid_only);
struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,
unsigned int find_flags,
unsigned int open_flags);
int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
struct cifsFileInfo **ret_file);
int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode,
@@ -596,4 +598,20 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable,
}
}
static inline int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
unsigned int find_flags,
struct cifsFileInfo **ret_file)
{
find_flags &= ~FIND_OPEN_FLAGS;
return __cifs_get_writable_file(cifs_inode, find_flags, 0, ret_file);
}
static inline struct cifsFileInfo *
find_readable_file(struct cifsInodeInfo *cinode, unsigned int find_flags)
{
find_flags &= ~FIND_OPEN_FLAGS;
find_flags |= FIND_NO_PENDING_DELETE;
return __find_readable_file(cinode, find_flags, 0);
}
#endif /* _CIFSPROTO_H */

View File

@@ -187,7 +187,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
const char *full_path;
void *page = alloc_dentry_path();
struct inode *newinode = NULL;
unsigned int sbflags;
unsigned int sbflags = cifs_sb_flags(cifs_sb);
int disposition;
struct TCP_Server_Info *server = tcon->ses->server;
struct cifs_open_parms oparms;
@@ -308,6 +308,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
goto out;
}
create_options |= cifs_open_create_options(oflags, create_options);
/*
* if we're not using unix extensions, see if we need to set
* ATTR_READONLY on the create call
@@ -367,7 +368,6 @@ retry_open:
* If Open reported that we actually created a file then we now have to
* set the mode if possible.
*/
sbflags = cifs_sb_flags(cifs_sb);
if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
struct cifs_unix_set_info_args args = {
.mode = mode,

View File

@@ -255,7 +255,7 @@ static void cifs_begin_writeback(struct netfs_io_request *wreq)
struct cifs_io_request *req = container_of(wreq, struct cifs_io_request, rreq);
int ret;
ret = cifs_get_writable_file(CIFS_I(wreq->inode), FIND_WR_ANY, &req->cfile);
ret = cifs_get_writable_file(CIFS_I(wreq->inode), FIND_ANY, &req->cfile);
if (ret) {
cifs_dbg(VFS, "No writable handle in writepages ret=%d\n", ret);
return;
@@ -584,15 +584,8 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_
*********************************************************************/
disposition = cifs_get_disposition(f_flags);
/* BB pass O_SYNC flag through on file attributes .. BB */
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
if (f_flags & O_SYNC)
create_options |= CREATE_WRITE_THROUGH;
if (f_flags & O_DIRECT)
create_options |= CREATE_NO_BUFFER;
create_options |= cifs_open_create_options(f_flags, create_options);
retry_open:
oparms = (struct cifs_open_parms) {
@@ -963,7 +956,7 @@ int cifs_file_flush(const unsigned int xid, struct inode *inode,
return tcon->ses->server->ops->flush(xid, tcon,
&cfile->fid);
}
rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile);
rc = cifs_get_writable_file(CIFS_I(inode), FIND_ANY, &cfile);
if (!rc) {
tcon = tlink_tcon(cfile->tlink);
rc = tcon->ses->server->ops->flush(xid, tcon, &cfile->fid);
@@ -988,7 +981,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry)
return -ERESTARTSYS;
mapping_set_error(inode->i_mapping, rc);
cfile = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
cfile = find_writable_file(cinode, FIND_FSUID_ONLY);
rc = cifs_file_flush(xid, inode, cfile);
if (!rc) {
if (cfile) {
@@ -1068,32 +1061,29 @@ int cifs_open(struct inode *inode, struct file *file)
/* Get the cached handle as SMB2 close is deferred */
if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) {
rc = cifs_get_writable_path(tcon, full_path,
FIND_WR_FSUID_ONLY |
FIND_WR_NO_PENDING_DELETE,
&cfile);
rc = __cifs_get_writable_file(CIFS_I(inode),
FIND_FSUID_ONLY |
FIND_NO_PENDING_DELETE |
FIND_OPEN_FLAGS,
file->f_flags, &cfile);
} else {
rc = cifs_get_readable_path(tcon, full_path, &cfile);
cfile = __find_readable_file(CIFS_I(inode),
FIND_NO_PENDING_DELETE |
FIND_OPEN_FLAGS,
file->f_flags);
rc = cfile ? 0 : -ENOENT;
}
if (rc == 0) {
unsigned int oflags = file->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC);
unsigned int cflags = cfile->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC);
if (cifs_convert_flags(oflags, 0) == cifs_convert_flags(cflags, 0) &&
(oflags & (O_SYNC|O_DIRECT)) == (cflags & (O_SYNC|O_DIRECT))) {
file->private_data = cfile;
spin_lock(&CIFS_I(inode)->deferred_lock);
cifs_del_deferred_close(cfile);
spin_unlock(&CIFS_I(inode)->deferred_lock);
goto use_cache;
}
_cifsFileInfo_put(cfile, true, false);
} else {
/* hard link on the defeered close file */
/* hard link on the deferred close file */
rc = cifs_get_hardlink_path(tcon, inode, file);
if (rc)
cifs_close_deferred_file(CIFS_I(inode));
}
if (server->oplocks)
oplock = REQ_OPLOCK;
@@ -1314,13 +1304,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
rdwr_for_fscache = 1;
desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache);
/* O_SYNC also has bit for O_DSYNC so following check picks up either */
if (cfile->f_flags & O_SYNC)
create_options |= CREATE_WRITE_THROUGH;
if (cfile->f_flags & O_DIRECT)
create_options |= CREATE_NO_BUFFER;
create_options |= cifs_open_create_options(cfile->f_flags,
create_options);
if (server->ops->get_lease_key)
server->ops->get_lease_key(inode, &cfile->fid);
@@ -2524,10 +2509,33 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t
netfs_write_subrequest_terminated(&wdata->subreq, result);
}
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
bool fsuid_only)
static bool open_flags_match(struct cifsInodeInfo *cinode,
unsigned int oflags, unsigned int cflags)
{
struct inode *inode = &cinode->netfs.inode;
int crw = 0, orw = 0;
oflags &= ~(O_CREAT | O_EXCL | O_TRUNC);
cflags &= ~(O_CREAT | O_EXCL | O_TRUNC);
if (cifs_fscache_enabled(inode)) {
if (OPEN_FMODE(cflags) & FMODE_WRITE)
crw = 1;
if (OPEN_FMODE(oflags) & FMODE_WRITE)
orw = 1;
}
if (cifs_convert_flags(oflags, orw) != cifs_convert_flags(cflags, crw))
return false;
return (oflags & (O_SYNC | O_DIRECT)) == (cflags & (O_SYNC | O_DIRECT));
}
struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,
unsigned int find_flags,
unsigned int open_flags)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode);
bool fsuid_only = find_flags & FIND_FSUID_ONLY;
struct cifsFileInfo *open_file = NULL;
/* only filter by fsuid on multiuser mounts */
@@ -2541,6 +2549,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
continue;
if ((find_flags & FIND_NO_PENDING_DELETE) &&
open_file->status_file_deleted)
continue;
if ((find_flags & FIND_OPEN_FLAGS) &&
!open_flags_match(cifs_inode, open_flags,
open_file->f_flags))
continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
if ((!open_file->invalidHandle)) {
/* found a good file */
@@ -2559,8 +2574,8 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
}
/* Return -EBADF if no handle is found and general rc otherwise */
int
cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
unsigned int find_flags, unsigned int open_flags,
struct cifsFileInfo **ret_file)
{
struct cifsFileInfo *open_file, *inv_file = NULL;
@@ -2568,8 +2583,8 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags,
bool any_available = false;
int rc = -EBADF;
unsigned int refind = 0;
bool fsuid_only = flags & FIND_WR_FSUID_ONLY;
bool with_delete = flags & FIND_WR_WITH_DELETE;
bool fsuid_only = find_flags & FIND_FSUID_ONLY;
bool with_delete = find_flags & FIND_WITH_DELETE;
*ret_file = NULL;
/*
@@ -2603,9 +2618,13 @@ refind_writable:
continue;
if (with_delete && !(open_file->fid.access & DELETE))
continue;
if ((flags & FIND_WR_NO_PENDING_DELETE) &&
if ((find_flags & FIND_NO_PENDING_DELETE) &&
open_file->status_file_deleted)
continue;
if ((find_flags & FIND_OPEN_FLAGS) &&
!open_flags_match(cifs_inode, open_flags,
open_file->f_flags))
continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
if (!open_file->invalidHandle) {
/* found a good writable file */
@@ -2722,17 +2741,7 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
cinode = CIFS_I(d_inode(cfile->dentry));
spin_unlock(&tcon->open_file_lock);
free_dentry_path(page);
*ret_file = find_readable_file(cinode, 0);
if (*ret_file) {
spin_lock(&cinode->open_file_lock);
if ((*ret_file)->status_file_deleted) {
spin_unlock(&cinode->open_file_lock);
cifsFileInfo_put(*ret_file);
*ret_file = NULL;
} else {
spin_unlock(&cinode->open_file_lock);
}
}
*ret_file = find_readable_file(cinode, FIND_ANY);
return *ret_file ? 0 : -ENOENT;
}
@@ -2804,7 +2813,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
}
if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
smbfile = find_writable_file(CIFS_I(inode), FIND_ANY);
if (smbfile) {
rc = server->ops->flush(xid, tcon, &smbfile->fid);
cifsFileInfo_put(smbfile);

View File

@@ -1997,7 +1997,7 @@ int smb3_init_fs_context(struct fs_context *fc)
ctx->backupuid_specified = false; /* no backup intent for a user */
ctx->backupgid_specified = false; /* no backup intent for a group */
ctx->retrans = 1;
ctx->retrans = 0;
ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT;
ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT;
ctx->nonativesocket = 0;

View File

@@ -2997,7 +2997,7 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
}
}
cfile = find_readable_file(cifs_i, false);
cfile = find_readable_file(cifs_i, FIND_ANY);
if (cfile == NULL)
return -EINVAL;
@@ -3050,7 +3050,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);
} else {
open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY);
if (open_file) {
tcon = tlink_tcon(open_file->tlink);
server = tcon->ses->server;
@@ -3219,7 +3219,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
open_file->fid.netfid,
open_file->pid);
} else {
open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY);
open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY);
if (open_file) {
pTcon = tlink_tcon(open_file->tlink);
rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args,

View File

@@ -960,7 +960,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
struct cifs_tcon *tcon;
/* if the file is already open for write, just use that fileid */
open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY);
open_file = find_writable_file(cinode, FIND_FSUID_ONLY);
if (open_file) {
fid.netfid = open_file->fid.netfid;

View File

@@ -1156,7 +1156,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
cifs_i = CIFS_I(inode);
dosattrs = cifs_i->cifsAttrs | ATTR_READONLY;
data.Attributes = cpu_to_le32(dosattrs);
cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile);
cifs_get_writable_path(tcon, name, FIND_ANY, &cfile);
oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES,
FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE);
tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
@@ -1336,14 +1336,13 @@ int smb2_rename_path(const unsigned int xid,
__u32 co = file_create_options(source_dentry);
drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
cifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile);
int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
if (rc == -EINVAL) {
cifs_dbg(FYI, "invalid lease key, resending request without lease");
cifs_get_writable_path(tcon, from_name,
FIND_WR_WITH_DELETE, &cfile);
cifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile);
rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
co, DELETE, SMB2_OP_RENAME, cfile, NULL);
}
@@ -1377,7 +1376,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
in_iov.iov_base = &eof;
in_iov.iov_len = sizeof(eof);
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA,
FILE_OPEN, 0, ACL_NO_MODE);
@@ -1387,7 +1386,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
cfile, NULL, NULL, dentry);
if (rc == -EINVAL) {
cifs_dbg(FYI, "invalid lease key, resending request without lease");
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb,
full_path, &oparms, &in_iov,
&(int){SMB2_OP_SET_EOF}, 1,
@@ -1417,7 +1416,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
(buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) {
if (buf->Attributes == 0)
goto out; /* would be a no op, no sense sending this */
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
}
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES,
@@ -1476,7 +1475,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
if (tcon->posix_extensions) {
cmds[1] = SMB2_OP_POSIX_QUERY_INFO;
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
if (!rc) {
@@ -1485,7 +1484,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
}
} else {
cmds[1] = SMB2_OP_QUERY_INFO;
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms,
in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL);
if (!rc) {
@@ -1636,13 +1635,12 @@ int smb2_rename_pending_delete(const char *full_path,
iov[1].iov_base = utf16_path;
iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path);
cifs_get_writable_path(tcon, full_path, FIND_WR_WITH_DELETE, &cfile);
cifs_get_writable_path(tcon, full_path, FIND_WITH_DELETE, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,
cmds, num_cmds, cfile, NULL, NULL, dentry);
if (rc == -EINVAL) {
cifs_dbg(FYI, "invalid lease key, resending request without lease\n");
cifs_get_writable_path(tcon, full_path,
FIND_WR_WITH_DELETE, &cfile);
cifs_get_writable_path(tcon, full_path, FIND_WITH_DELETE, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov,
cmds, num_cmds, cfile, NULL, NULL, NULL);
}

View File

@@ -109,6 +109,9 @@ int __init smb2_init_maperror(void)
}
#if IS_ENABLED(CONFIG_SMB_KUNIT_TESTS)
#define EXPORT_SYMBOL_FOR_SMB_TEST(sym) \
EXPORT_SYMBOL_FOR_MODULES(sym, "smb2maperror_test")
/* Previous prototype for eliminating the build warning. */
const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status);
@@ -116,11 +119,11 @@ const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status)
{
return smb2_get_err_map(smb2_status);
}
EXPORT_SYMBOL_GPL(smb2_get_err_map_test);
EXPORT_SYMBOL_FOR_SMB_TEST(smb2_get_err_map_test);
const struct status_to_posix_error *smb2_error_map_table_test = smb2_error_map_table;
EXPORT_SYMBOL_GPL(smb2_error_map_table_test);
EXPORT_SYMBOL_FOR_SMB_TEST(smb2_error_map_table_test);
unsigned int smb2_error_map_num = ARRAY_SIZE(smb2_error_map_table);
EXPORT_SYMBOL_GPL(smb2_error_map_num);
EXPORT_SYMBOL_FOR_SMB_TEST(smb2_error_map_num);
#endif

View File

@@ -628,6 +628,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
struct smb_sockaddr_in6 *p6;
struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL;
struct cifs_server_iface tmp_iface;
__be16 port;
ssize_t bytes_left;
size_t next = 0;
int nb_iface = 0;
@@ -662,6 +663,15 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
goto out;
}
spin_lock(&ses->server->srv_lock);
if (ses->server->dstaddr.ss_family == AF_INET)
port = ((struct sockaddr_in *)&ses->server->dstaddr)->sin_port;
else if (ses->server->dstaddr.ss_family == AF_INET6)
port = ((struct sockaddr_in6 *)&ses->server->dstaddr)->sin6_port;
else
port = cpu_to_be16(CIFS_PORT);
spin_unlock(&ses->server->srv_lock);
while (bytes_left >= (ssize_t)sizeof(*p)) {
memset(&tmp_iface, 0, sizeof(tmp_iface));
/* default to 1Gbps when link speed is unset */
@@ -682,7 +692,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
/* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */
addr4->sin_port = cpu_to_be16(CIFS_PORT);
addr4->sin_port = port;
cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__,
&addr4->sin_addr);
@@ -696,7 +706,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
/* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */
addr6->sin6_flowinfo = 0;
addr6->sin6_scope_id = 0;
addr6->sin6_port = cpu_to_be16(CIFS_PORT);
addr6->sin6_port = port;
cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__,
&addr6->sin6_addr);
@@ -3352,7 +3362,7 @@ get_smb2_acl(struct cifs_sb_info *cifs_sb,
struct cifsFileInfo *open_file = NULL;
if (inode && !(info & SACL_SECINFO))
open_file = find_readable_file(CIFS_I(inode), true);
open_file = find_readable_file(CIFS_I(inode), FIND_FSUID_ONLY);
if (!open_file || (info & SACL_SECINFO))
return get_smb2_acl_by_path(cifs_sb, path, pacllen, info);
@@ -3898,7 +3908,7 @@ static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offs
* some servers (Windows2016) will not reflect recent writes in
* QUERY_ALLOCATED_RANGES until SMB2_flush is called.
*/
wrcfile = find_writable_file(cifsi, FIND_WR_ANY);
wrcfile = find_writable_file(cifsi, FIND_ANY);
if (wrcfile) {
filemap_write_and_wait(inode->i_mapping);
smb2_flush_file(xid, tcon, &wrcfile->fid);

View File

@@ -5307,7 +5307,10 @@ replay_again:
memset(&rqst, 0, sizeof(struct smb_rqst));
rqst.rq_iov = iov;
rqst.rq_nvec = n_vec + 1;
/* iov[0] is the SMB header; move payload to rq_iter for encryption safety */
rqst.rq_nvec = 1;
iov_iter_kvec(&rqst.rq_iter, ITER_SOURCE, &iov[1], n_vec,
io_parms->length);
if (retries) {
/* Back-off before retry */