Skip to content

Commit

Permalink
Merge tag '5.16-rc-part1-smb3-client-fixes' of git://git.samba.org/sf…
Browse files Browse the repository at this point in the history
…rench/cifs-2.6

Pull cifs updates from Steve French:

 - reconnect fix for stable

 - minor mount option fix

 - debugging improvement for (TCP) connection issues

 - refactoring of common code to help ksmbd

* tag '5.16-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  smb3: add dynamic trace points for socket connection
  cifs: Move SMB2_Create definitions to the shared area
  cifs: Move more definitions into the shared area
  cifs: move NEGOTIATE_PROTOCOL definitions out into the common area
  cifs: Create a new shared file holding smb2 pdu definitions
  cifs: add mount parameter tcpnodelay
  cifs: To match file servers, make sure the server hostname matches
  • Loading branch information
torvalds committed Nov 6, 2021
2 parents 2acda75 + d7171cd commit b5013d0
Show file tree
Hide file tree
Showing 15 changed files with 1,299 additions and 1,091 deletions.
1 change: 0 additions & 1 deletion fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
#include <linux/key-type.h>
#include "cifs_spnego.h"
#include "fscache.h"
#include "smb2pdu.h"
#ifdef CONFIG_CIFS_DFS_UPCALL
#include "dfs_cache.h"
#endif
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <crypto/internal/hash.h>
#include <linux/scatterlist.h>
#include <uapi/linux/cifs/cifs_mount.h>
#include "../smbfs_common/smb2pdu.h"
#include "smb2pdu.h"

#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
Expand Down Expand Up @@ -776,7 +777,7 @@ revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)

static inline void
revert_current_mid_from_hdr(struct TCP_Server_Info *server,
const struct smb2_sync_hdr *shdr)
const struct smb2_hdr *shdr)
{
unsigned int num = le16_to_cpu(shdr->CreditCharge);

Expand Down
26 changes: 15 additions & 11 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ dequeue_mid(struct mid_q_entry *mid, bool malformed)
static unsigned int
smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
struct smb2_hdr *shdr = (struct smb2_hdr *)buffer;

/*
* SMB1 does not use credits.
Expand Down Expand Up @@ -794,7 +794,6 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server)
*/
}

kfree(server->hostname);
kfree(server);

length = atomic_dec_return(&tcpSesAllocCount);
Expand Down Expand Up @@ -878,7 +877,7 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
static void
smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
{
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buffer;
struct smb2_hdr *shdr = (struct smb2_hdr *)buffer;
int scredits, in_flight;

/*
Expand Down Expand Up @@ -1235,6 +1234,9 @@ static int match_server(struct TCP_Server_Info *server, struct smb3_fs_context *
if (!net_eq(cifs_net_ns(server), current->nsproxy->net_ns))
return 0;

if (strcasecmp(server->hostname, ctx->server_hostname))
return 0;

if (!match_address(server, addr,
(struct sockaddr *)&ctx->srcaddr))
return 0;
Expand Down Expand Up @@ -1336,6 +1338,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
kfree(server->session_key.response);
server->session_key.response = NULL;
server->session_key.len = 0;
kfree(server->hostname);

task = xchg(&server->tsk, NULL);
if (task)
Expand All @@ -1361,14 +1364,15 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx)
goto out_err;
}

tcp_ses->hostname = kstrdup(ctx->server_hostname, GFP_KERNEL);
if (!tcp_ses->hostname) {
rc = -ENOMEM;
goto out_err;
}

tcp_ses->ops = ctx->ops;
tcp_ses->vals = ctx->vals;
cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
tcp_ses->hostname = extract_hostname(ctx->UNC);
if (IS_ERR(tcp_ses->hostname)) {
rc = PTR_ERR(tcp_ses->hostname);
goto out_err_crypto_release;
}

tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId);
tcp_ses->noblockcnt = ctx->rootfs;
Expand Down Expand Up @@ -1497,8 +1501,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx)

out_err:
if (tcp_ses) {
if (!IS_ERR(tcp_ses->hostname))
kfree(tcp_ses->hostname);
kfree(tcp_ses->hostname);
if (tcp_ses->ssocket)
sock_release(tcp_ses->ssocket);
kfree(tcp_ses);
Expand Down Expand Up @@ -2646,11 +2649,12 @@ generic_ip_connect(struct TCP_Server_Info *server)
rc = 0;
if (rc < 0) {
cifs_dbg(FYI, "Error %d connecting to server\n", rc);
trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc);
sock_release(socket);
server->ssocket = NULL;
return rc;
}

trace_smb3_connect_done(server->hostname, server->conn_id, &server->dstaddr);
if (sport == htons(RFC1001_PORT))
rc = ip_rfc1001_connect(server);

Expand Down
16 changes: 16 additions & 0 deletions fs/cifs/fs_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
fsparam_flag("nosharesock", Opt_nosharesock),
fsparam_flag_no("persistenthandles", Opt_persistent),
fsparam_flag_no("resilienthandles", Opt_resilient),
fsparam_flag_no("tcpnodelay", Opt_tcp_nodelay),
fsparam_flag("domainauto", Opt_domainauto),
fsparam_flag("rdma", Opt_rdma),
fsparam_flag("modesid", Opt_modesid),
Expand Down Expand Up @@ -318,6 +319,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
DUP_CTX_STR(mount_options);
DUP_CTX_STR(username);
DUP_CTX_STR(password);
DUP_CTX_STR(server_hostname);
DUP_CTX_STR(UNC);
DUP_CTX_STR(source);
DUP_CTX_STR(domainname);
Expand Down Expand Up @@ -456,6 +458,11 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx)
if (!pos)
return -EINVAL;

/* record the server hostname */
ctx->server_hostname = kstrndup(devname + 2, pos - devname - 2, GFP_KERNEL);
if (!ctx->server_hostname)
return -ENOMEM;

/* skip past delimiter */
++pos;

Expand Down Expand Up @@ -1383,6 +1390,13 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
}
}
break;
case Opt_tcp_nodelay:
/* tcp nodelay should not usually be needed since we CORK/UNCORK the socket */
if (result.negated)
ctx->sockopt_tcp_nodelay = false;
else
ctx->sockopt_tcp_nodelay = true;
break;
case Opt_domainauto:
ctx->domainauto = true;
break;
Expand Down Expand Up @@ -1496,6 +1510,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
ctx->username = NULL;
kfree_sensitive(ctx->password);
ctx->password = NULL;
kfree(ctx->server_hostname);
ctx->server_hostname = NULL;
kfree(ctx->UNC);
ctx->UNC = NULL;
kfree(ctx->source);
Expand Down
2 changes: 2 additions & 0 deletions fs/cifs/fs_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ enum cifs_param {
Opt_nosharesock,
Opt_persistent,
Opt_resilient,
Opt_tcp_nodelay,
Opt_domainauto,
Opt_rdma,
Opt_modesid,
Expand Down Expand Up @@ -166,6 +167,7 @@ struct smb3_fs_context {
char *password;
char *domainname;
char *source;
char *server_hostname;
char *UNC;
char *nodename;
char *iocharset; /* local code page for mapping to and from Unicode */
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ cifs_buf_get(void)
* SMB2 header is bigger than CIFS one - no problems to clean some
* more bytes for CIFS.
*/
size_t buf_size = sizeof(struct smb2_sync_hdr);
size_t buf_size = sizeof(struct smb2_hdr);

/*
* We could use negotiated size instead of max_msgsize -
Expand Down
16 changes: 10 additions & 6 deletions fs/cifs/smb2maperror.c
Original file line number Diff line number Diff line change
Expand Up @@ -2439,14 +2439,16 @@ smb2_print_status(__le32 status)
int
map_smb2_to_linux_error(char *buf, bool log_err)
{
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
unsigned int i;
int rc = -EIO;
__le32 smb2err = shdr->Status;

if (smb2err == 0) {
trace_smb3_cmd_done(shdr->TreeId, shdr->SessionId,
le16_to_cpu(shdr->Command), le64_to_cpu(shdr->MessageId));
trace_smb3_cmd_done(le32_to_cpu(shdr->Id.SyncId.TreeId),
le64_to_cpu(shdr->SessionId),
le16_to_cpu(shdr->Command),
le64_to_cpu(shdr->MessageId));
return 0;
}

Expand All @@ -2470,8 +2472,10 @@ map_smb2_to_linux_error(char *buf, bool log_err)
cifs_dbg(FYI, "Mapping SMB2 status code 0x%08x to POSIX err %d\n",
__le32_to_cpu(smb2err), rc);

trace_smb3_cmd_err(shdr->TreeId, shdr->SessionId,
le16_to_cpu(shdr->Command),
le64_to_cpu(shdr->MessageId), le32_to_cpu(smb2err), rc);
trace_smb3_cmd_err(le32_to_cpu(shdr->Id.SyncId.TreeId),
le64_to_cpu(shdr->SessionId),
le16_to_cpu(shdr->Command),
le64_to_cpu(shdr->MessageId),
le32_to_cpu(smb2err), rc);
return rc;
}
47 changes: 23 additions & 24 deletions fs/cifs/smb2misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
*
*/
#include <linux/ctype.h>
#include "smb2pdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
#include "smb2proto.h"
Expand All @@ -19,7 +18,7 @@
#include "nterr.h"

static int
check_smb2_hdr(struct smb2_sync_hdr *shdr, __u64 mid)
check_smb2_hdr(struct smb2_hdr *shdr, __u64 mid)
{
__u64 wire_mid = le64_to_cpu(shdr->MessageId);

Expand Down Expand Up @@ -81,9 +80,9 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
/* SMB2_OPLOCK_BREAK */ cpu_to_le16(24)
};

#define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_sync_hdr) + sizeof(struct smb2_negotiate_rsp))
#define SMB311_NEGPROT_BASE_SIZE (sizeof(struct smb2_hdr) + sizeof(struct smb2_negotiate_rsp))

static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len,
__u32 non_ctxlen)
{
__u16 neg_count;
Expand Down Expand Up @@ -135,13 +134,13 @@ static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
int
smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
{
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
struct smb2_pdu *pdu = (struct smb2_pdu *)shdr;
__u64 mid;
__u32 clc_len; /* calculated length */
int command;
int pdu_size = sizeof(struct smb2_sync_pdu);
int hdr_size = sizeof(struct smb2_sync_hdr);
int pdu_size = sizeof(struct smb2_pdu);
int hdr_size = sizeof(struct smb2_hdr);

/*
* Add function to do table lookup of StructureSize by command
Expand All @@ -155,7 +154,7 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
/* decrypt frame now that it is completely read in */
spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &srvr->smb_ses_list, smb_ses_list) {
if (ses->Suid == thdr->SessionId)
if (ses->Suid == le64_to_cpu(thdr->SessionId))
break;
}
spin_unlock(&cifs_tcp_ses_lock);
Expand Down Expand Up @@ -296,7 +295,7 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
* area and the offset to it (from the beginning of the smb are also returned.
*/
char *
smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *shdr)
{
*off = 0;
*len = 0;
Expand Down Expand Up @@ -401,8 +400,8 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
unsigned int
smb2_calc_size(void *buf, struct TCP_Server_Info *srvr)
{
struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf;
struct smb2_sync_hdr *shdr = &pdu->sync_hdr;
struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
struct smb2_hdr *shdr = &pdu->hdr;
int offset; /* the offset from the beginning of SMB to data area */
int data_length; /* the length of the variable length data area */
/* Structure Size has already been checked to make sure it is 64 */
Expand Down Expand Up @@ -669,7 +668,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)

cifs_dbg(FYI, "Checking for oplock break\n");

if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
if (rsp->hdr.Command != SMB2_OPLOCK_BREAK)
return false;

if (rsp->StructureSize !=
Expand Down Expand Up @@ -816,25 +815,25 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
int
smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server)
{
struct smb2_sync_hdr *sync_hdr = mid->resp_buf;
struct smb2_hdr *hdr = mid->resp_buf;
struct smb2_create_rsp *rsp = mid->resp_buf;
struct cifs_tcon *tcon;
int rc;

if ((mid->optype & CIFS_CP_CREATE_CLOSE_OP) || sync_hdr->Command != SMB2_CREATE ||
sync_hdr->Status != STATUS_SUCCESS)
if ((mid->optype & CIFS_CP_CREATE_CLOSE_OP) || hdr->Command != SMB2_CREATE ||
hdr->Status != STATUS_SUCCESS)
return 0;

tcon = smb2_find_smb_tcon(server, sync_hdr->SessionId,
sync_hdr->TreeId);
tcon = smb2_find_smb_tcon(server, le64_to_cpu(hdr->SessionId),
le32_to_cpu(hdr->Id.SyncId.TreeId));
if (!tcon)
return -ENOENT;

rc = __smb2_handle_cancelled_cmd(tcon,
le16_to_cpu(sync_hdr->Command),
le64_to_cpu(sync_hdr->MessageId),
rsp->PersistentFileId,
rsp->VolatileFileId);
le16_to_cpu(hdr->Command),
le64_to_cpu(hdr->MessageId),
le64_to_cpu(rsp->PersistentFileId),
le64_to_cpu(rsp->VolatileFileId));
if (rc)
cifs_put_tcon(tcon);

Expand All @@ -856,10 +855,10 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec)
{
int i, rc;
struct sdesc *d;
struct smb2_sync_hdr *hdr;
struct smb2_hdr *hdr;
struct TCP_Server_Info *server = cifs_ses_server(ses);

hdr = (struct smb2_sync_hdr *)iov[0].iov_base;
hdr = (struct smb2_hdr *)iov[0].iov_base;
/* neg prot are always taken */
if (hdr->Command == SMB2_NEGOTIATE)
goto ok;
Expand Down
Loading

0 comments on commit b5013d0

Please sign in to comment.