21 cifs/smb3 fixes, including 4 for stable

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmNCWv0ACgkQiiy9cAdy
 T1EaIAv/bkcILC2M6pFdAp4i5hDuJoJvYnuh3Yc9P19uUsFWhHlZsG0rZLwRmQ2e
 kGzvO3fmS1V8iE72ZXYqj1ARAahMm2T6HsxcpLQ39bH645WsAAFUoapqUQZcENif
 u+faCJXK2ALTUoB3hSqxfZ4Ck9ILxXBeQTi4G2XQ0yf8jlXePM38Q8mo+qSN5pSQ
 8XVui3vHIi8u7JZnSuhcxRm8WCLBj2Dbuod5uJALKwl90WVD/HvHZUdiMiz4OnG2
 s3+MkXvAdg7QmaF+3jhpSkzeQl3EDToMg6zqI+mi0K4CHRpeQbm+kRu3lQYwh7nR
 gbAyQH/tgz2QlqkLbW5FpsOC3v3KtsrgqfYWPA8o6pMh2zs8p1EBJ/hX4e5EbzaF
 bOgQVi/sY1tfILB1q7B1JfB/0HFUy+vnGiNowJleoKF5Lw/fJSwgb5aY/YDTqwA0
 B6tXAHo0srPz4h8PMdZZqJQeue13zhKKpMxW/3i2o/fkOXJvTjp6Y2k6IzRYubtv
 28sgtq6x
 =8GDQ
 -----END PGP SIGNATURE-----

Merge tag '6.1-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs updates from Steve French:

 - data corruption fix when cache disabled

 - four RDMA (smbdirect) improvements, including enabling support for
   SoftiWARP

 - four signing improvements

 - three directory lease improvements

 - four cleanup fixes

 - minor security fix

 - two debugging improvements

* tag '6.1-rc-smb3-client-fixes-part1' of git://git.samba.org/sfrench/cifs-2.6: (21 commits)
  smb3: fix oops in calculating shash_setkey
  cifs: secmech: use shash_desc directly, remove sdesc
  smb3: rename encryption/decryption TFMs
  cifs: replace kfree() with kfree_sensitive() for sensitive data
  cifs: remove initialization value
  cifs: Replace a couple of one-element arrays with flexible-array members
  smb3: do not log confusing message when server returns no network interfaces
  smb3: define missing create contexts
  cifs: store a pointer to a fid in the cfid structure instead of the struct
  cifs: improve handlecaching
  cifs: Make tcon contain a wrapper structure cached_fids instead of cached_fid
  smb3: add dynamic trace points for tree disconnect
  Fix formatting of client smbdirect RDMA logging
  Handle variable number of SGEs in client smbdirect send.
  Reduce client smbdirect max receive segment size
  Decrease the number of SMB3 smbdirect client SGEs
  cifs: Fix the error length of VALIDATE_NEGOTIATE_INFO message
  cifs: destage dirty pages before re-reading them for cache=none
  cifs: return correct error in ->calc_signature()
  MAINTAINERS: Add Tom Talpey as cifs.ko reviewer
  ...
This commit is contained in:
Linus Torvalds 2022-10-10 20:04:22 -07:00
commit ac1e8c6c95
30 changed files with 447 additions and 426 deletions

View file

@ -5170,6 +5170,7 @@ M: Steve French <sfrench@samba.org>
R: Paulo Alcantara <pc@cjr.nz> (DFS, global name space)
R: Ronnie Sahlberg <lsahlber@redhat.com> (directory leases, sparse files)
R: Shyam Prasad N <sprasad@microsoft.com> (multichannel)
R: Tom Talpey <tom@talpey.com> (RDMA, smbdirect)
L: linux-cifs@vger.kernel.org
L: samba-technical@lists.samba.org (moderated for non-subscribers)
S: Supported

View file

@ -11,6 +11,8 @@
#include "smb2proto.h"
#include "cached_dir.h"
struct cached_fid *init_cached_dir(const char *path);
/*
* Open the and cache a directory handle.
* If error then *cfid is not initialized.
@ -47,12 +49,19 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
if (cifs_sb->root == NULL)
return -ENOENT;
if (strlen(path))
if (!path[0])
dentry = cifs_sb->root;
else
return -ENOENT;
dentry = cifs_sb->root;
cfid = tcon->cfids->cfid;
if (cfid == NULL) {
cfid = init_cached_dir(path);
tcon->cfids->cfid = cfid;
}
if (cfid == NULL)
return -ENOMEM;
cfid = tcon->cfid;
mutex_lock(&cfid->fid_mutex);
if (cfid->is_valid) {
cifs_dbg(FYI, "found a cached root file handle\n");
@ -160,7 +169,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
if (rc == -EREMCHG) {
tcon->need_reconnect = true;
pr_warn_once("server share %s deleted\n",
tcon->treeName);
tcon->tree_name);
}
goto oshr_exit;
}
@ -177,7 +186,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
cfid->tcon = tcon;
cfid->is_valid = true;
cfid->dentry = dentry;
dget(dentry);
if (dentry)
dget(dentry);
kref_init(&cfid->refcount);
/* BB TBD check to see if oplock level check can be removed below */
@ -226,7 +236,9 @@ int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
{
struct cached_fid *cfid;
cfid = tcon->cfid;
cfid = tcon->cfids->cfid;
if (cfid == NULL)
return -ENOENT;
mutex_lock(&cfid->fid_mutex);
if (cfid->dentry == dentry) {
@ -320,7 +332,9 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
tcon = tlink_tcon(tlink);
if (IS_ERR(tcon))
continue;
cfid = tcon->cfid;
cfid = tcon->cfids->cfid;
if (cfid == NULL)
continue;
mutex_lock(&cfid->fid_mutex);
if (cfid->dentry) {
dput(cfid->dentry);
@ -336,12 +350,17 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
*/
void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
{
mutex_lock(&tcon->cfid->fid_mutex);
tcon->cfid->is_valid = false;
struct cached_fid *cfid = tcon->cfids->cfid;
if (cfid == NULL)
return;
mutex_lock(&cfid->fid_mutex);
cfid->is_valid = false;
/* cached handle is not valid, so SMB2_CLOSE won't be sent below */
close_cached_dir_lease_locked(tcon->cfid);
memset(&tcon->cfid->fid, 0, sizeof(struct cifs_fid));
mutex_unlock(&tcon->cfid->fid_mutex);
close_cached_dir_lease_locked(cfid);
memset(&cfid->fid, 0, sizeof(struct cifs_fid));
mutex_unlock(&cfid->fid_mutex);
}
static void
@ -355,34 +374,67 @@ smb2_cached_lease_break(struct work_struct *work)
int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
{
if (tcon->cfid->is_valid &&
struct cached_fid *cfid = tcon->cfids->cfid;
if (cfid == NULL)
return false;
if (cfid->is_valid &&
!memcmp(lease_key,
tcon->cfid->fid.lease_key,
cfid->fid.lease_key,
SMB2_LEASE_KEY_SIZE)) {
tcon->cfid->time = 0;
INIT_WORK(&tcon->cfid->lease_break,
cfid->time = 0;
INIT_WORK(&cfid->lease_break,
smb2_cached_lease_break);
queue_work(cifsiod_wq,
&tcon->cfid->lease_break);
&cfid->lease_break);
return true;
}
return false;
}
struct cached_fid *init_cached_dir(void)
struct cached_fid *init_cached_dir(const char *path)
{
struct cached_fid *cfid;
cfid = kzalloc(sizeof(*cfid), GFP_KERNEL);
if (!cfid)
return NULL;
cfid->path = kstrdup(path, GFP_KERNEL);
if (!cfid->path) {
kfree(cfid);
return NULL;
}
INIT_LIST_HEAD(&cfid->dirents.entries);
mutex_init(&cfid->dirents.de_mutex);
mutex_init(&cfid->fid_mutex);
return cfid;
}
void free_cached_dir(struct cifs_tcon *tcon)
void free_cached_dir(struct cached_fid *cfid)
{
kfree(tcon->cfid);
kfree(cfid->path);
cfid->path = NULL;
kfree(cfid);
}
struct cached_fids *init_cached_dirs(void)
{
struct cached_fids *cfids;
cfids = kzalloc(sizeof(*cfids), GFP_KERNEL);
if (!cfids)
return NULL;
mutex_init(&cfids->cfid_list_mutex);
return cfids;
}
void free_cached_dirs(struct cached_fids *cfids)
{
if (cfids->cfid) {
free_cached_dir(cfids->cfid);
cfids->cfid = NULL;
}
kfree(cfids);
}

View file

@ -31,6 +31,7 @@ struct cached_dirents {
};
struct cached_fid {
const char *path;
bool is_valid:1; /* Do we have a useable root fid */
bool file_all_info_is_valid:1;
bool has_lease:1;
@ -45,8 +46,13 @@ struct cached_fid {
struct cached_dirents dirents;
};
extern struct cached_fid *init_cached_dir(void);
extern void free_cached_dir(struct cifs_tcon *tcon);
struct cached_fids {
struct mutex cfid_list_mutex;
struct cached_fid *cfid;
};
extern struct cached_fids *init_cached_dirs(void);
extern void free_cached_dirs(struct cached_fids *cfids);
extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
const char *path,
struct cifs_sb_info *cifs_sb,

View file

@ -87,7 +87,7 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
{
__u32 dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
seq_printf(m, "%s Mounts: %d ", tcon->treeName, tcon->tc_count);
seq_printf(m, "%s Mounts: %d ", tcon->tree_name, tcon->tc_count);
if (tcon->nativeFileSystem)
seq_printf(m, "Type: %s ", tcon->nativeFileSystem);
seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x\n\tPathComponentMax: %d Status: %d",
@ -601,7 +601,7 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
i++;
seq_printf(m, "\n%d) %s", i, tcon->treeName);
seq_printf(m, "\n%d) %s", i, tcon->tree_name);
if (tcon->need_reconnect)
seq_puts(m, "\tDISCONNECTED ");
seq_printf(m, "\nSMBs: %d",

View file

@ -108,8 +108,8 @@ do { \
#define cifs_tcon_dbg_func(ratefunc, type, fmt, ...) \
do { \
const char *tn = ""; \
if (tcon && tcon->treeName) \
tn = tcon->treeName; \
if (tcon && tcon->tree_name) \
tn = tcon->tree_name; \
if ((type) & FYI && cifsFYI & CIFS_INFO) { \
pr_debug_ ## ratefunc("%s: %s " fmt, \
__FILE__, tn, ##__VA_ARGS__); \
@ -150,7 +150,7 @@ do { \
#define cifs_tcon_dbg(type, fmt, ...) \
do { \
if (0) \
pr_debug("%s " fmt, tcon->treeName, ##__VA_ARGS__); \
pr_debug("%s " fmt, tcon->tree_name, ##__VA_ARGS__); \
} while (0)
#define cifs_info(fmt, ...) \

View file

@ -256,23 +256,23 @@ static struct cifs_swn_reg *cifs_find_swn_reg(struct cifs_tcon *tcon)
const char *share_name;
const char *net_name;
net_name = extract_hostname(tcon->treeName);
net_name = extract_hostname(tcon->tree_name);
if (IS_ERR(net_name)) {
int ret;
ret = PTR_ERR(net_name);
cifs_dbg(VFS, "%s: failed to extract host name from target '%s': %d\n",
__func__, tcon->treeName, ret);
__func__, tcon->tree_name, ret);
return ERR_PTR(-EINVAL);
}
share_name = extract_sharename(tcon->treeName);
share_name = extract_sharename(tcon->tree_name);
if (IS_ERR(share_name)) {
int ret;
ret = PTR_ERR(share_name);
cifs_dbg(VFS, "%s: failed to extract share name from target '%s': %d\n",
__func__, tcon->treeName, ret);
__func__, tcon->tree_name, ret);
kfree(net_name);
return ERR_PTR(-EINVAL);
}
@ -335,14 +335,14 @@ static struct cifs_swn_reg *cifs_get_swn_reg(struct cifs_tcon *tcon)
goto fail;
}
reg->net_name = extract_hostname(tcon->treeName);
reg->net_name = extract_hostname(tcon->tree_name);
if (IS_ERR(reg->net_name)) {
ret = PTR_ERR(reg->net_name);
cifs_dbg(VFS, "%s: failed to extract host name from target: %d\n", __func__, ret);
goto fail_idr;
}
reg->share_name = extract_sharename(tcon->treeName);
reg->share_name = extract_sharename(tcon->tree_name);
if (IS_ERR(reg->share_name)) {
ret = PTR_ERR(reg->share_name);
cifs_dbg(VFS, "%s: failed to extract share name from target: %d\n", __func__, ret);

View file

@ -103,26 +103,24 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
if (!rqst->rq_iov || !signature || !server)
return -EINVAL;
rc = cifs_alloc_hash("md5", &server->secmech.md5,
&server->secmech.sdescmd5);
rc = cifs_alloc_hash("md5", &server->secmech.md5);
if (rc)
return -1;
rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
rc = crypto_shash_init(server->secmech.md5);
if (rc) {
cifs_dbg(VFS, "%s: Could not init md5\n", __func__);
return rc;
}
rc = crypto_shash_update(&server->secmech.sdescmd5->shash,
rc = crypto_shash_update(server->secmech.md5,
server->session_key.response, server->session_key.len);
if (rc) {
cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
return rc;
}
return __cifs_calc_signature(rqst, server, signature,
&server->secmech.sdescmd5->shash);
return __cifs_calc_signature(rqst, server, signature, server->secmech.md5);
}
/* must be called with server->srv_mutex held */
@ -412,7 +410,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
wchar_t *domain;
wchar_t *server;
if (!ses->server->secmech.sdeschmacmd5) {
if (!ses->server->secmech.hmacmd5) {
cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
return -1;
}
@ -420,14 +418,14 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
/* calculate md4 hash of password */
E_md4hash(ses->password, nt_hash, nls_cp);
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash,
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm, nt_hash,
CIFS_NTHASH_SIZE);
if (rc) {
cifs_dbg(VFS, "%s: Could not set NT Hash as a key\n", __func__);
return rc;
}
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
rc = crypto_shash_init(ses->server->secmech.hmacmd5);
if (rc) {
cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
return rc;
@ -448,7 +446,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
memset(user, '\0', 2);
}
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
rc = crypto_shash_update(ses->server->secmech.hmacmd5,
(char *)user, 2 * len);
kfree(user);
if (rc) {
@ -468,7 +466,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
nls_cp);
rc =
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
crypto_shash_update(ses->server->secmech.hmacmd5,
(char *)domain, 2 * len);
kfree(domain);
if (rc) {
@ -488,7 +486,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
len = cifs_strtoUTF16((__le16 *)server, ses->ip_addr, len,
nls_cp);
rc =
crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
crypto_shash_update(ses->server->secmech.hmacmd5,
(char *)server, 2 * len);
kfree(server);
if (rc) {
@ -498,7 +496,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
}
}
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
rc = crypto_shash_final(ses->server->secmech.hmacmd5,
ntlmv2_hash);
if (rc)
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
@ -518,12 +516,12 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
hash_len = ses->auth_key.len - (CIFS_SESS_KEY_SIZE +
offsetof(struct ntlmv2_resp, challenge.key[0]));
if (!ses->server->secmech.sdeschmacmd5) {
if (!ses->server->secmech.hmacmd5) {
cifs_dbg(VFS, "%s: can't generate ntlmv2 hash\n", __func__);
return -1;
}
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm,
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
if (rc) {
cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
@ -531,7 +529,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
return rc;
}
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
rc = crypto_shash_init(ses->server->secmech.hmacmd5);
if (rc) {
cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
return rc;
@ -543,7 +541,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
else
memcpy(ntlmv2->challenge.key,
ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE);
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
rc = crypto_shash_update(ses->server->secmech.hmacmd5,
ntlmv2->challenge.key, hash_len);
if (rc) {
cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
@ -551,7 +549,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash)
}
/* Note that the MD5 digest over writes anon.challenge_key.key */
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
rc = crypto_shash_final(ses->server->secmech.hmacmd5,
ntlmv2->ntlmv2_hash);
if (rc)
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
@ -627,9 +625,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
cifs_server_lock(ses->server);
rc = cifs_alloc_hash("hmac(md5)",
&ses->server->secmech.hmacmd5,
&ses->server->secmech.sdeschmacmd5);
rc = cifs_alloc_hash("hmac(md5)", &ses->server->secmech.hmacmd5);
if (rc) {
goto unlock;
}
@ -649,7 +645,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
}
/* now calculate the session key for NTLMv2 */
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5,
rc = crypto_shash_setkey(ses->server->secmech.hmacmd5->tfm,
ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
if (rc) {
cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
@ -657,13 +653,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
goto unlock;
}
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
rc = crypto_shash_init(ses->server->secmech.hmacmd5);
if (rc) {
cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
goto unlock;
}
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
rc = crypto_shash_update(ses->server->secmech.hmacmd5,
ntlmv2->ntlmv2_hash,
CIFS_HMAC_MD5_HASH_SIZE);
if (rc) {
@ -671,7 +667,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
goto unlock;
}
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
rc = crypto_shash_final(ses->server->secmech.hmacmd5,
ses->auth_key.response);
if (rc)
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
@ -679,7 +675,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
unlock:
cifs_server_unlock(ses->server);
setup_ntlmv2_rsp_ret:
kfree(tiblob);
kfree_sensitive(tiblob);
return rc;
}
@ -718,49 +714,19 @@ calc_seckey(struct cifs_ses *ses)
void
cifs_crypto_secmech_release(struct TCP_Server_Info *server)
{
if (server->secmech.cmacaes) {
crypto_free_shash(server->secmech.cmacaes);
server->secmech.cmacaes = NULL;
cifs_free_hash(&server->secmech.aes_cmac);
cifs_free_hash(&server->secmech.hmacsha256);
cifs_free_hash(&server->secmech.md5);
cifs_free_hash(&server->secmech.sha512);
cifs_free_hash(&server->secmech.hmacmd5);
if (server->secmech.enc) {
crypto_free_aead(server->secmech.enc);
server->secmech.enc = NULL;
}
if (server->secmech.hmacsha256) {
crypto_free_shash(server->secmech.hmacsha256);
server->secmech.hmacsha256 = NULL;
if (server->secmech.dec) {
crypto_free_aead(server->secmech.dec);
server->secmech.dec = NULL;
}
if (server->secmech.md5) {
crypto_free_shash(server->secmech.md5);
server->secmech.md5 = NULL;
}
if (server->secmech.sha512) {
crypto_free_shash(server->secmech.sha512);
server->secmech.sha512 = NULL;
}
if (server->secmech.hmacmd5) {
crypto_free_shash(server->secmech.hmacmd5);
server->secmech.hmacmd5 = NULL;
}
if (server->secmech.ccmaesencrypt) {
crypto_free_aead(server->secmech.ccmaesencrypt);
server->secmech.ccmaesencrypt = NULL;
}
if (server->secmech.ccmaesdecrypt) {
crypto_free_aead(server->secmech.ccmaesdecrypt);
server->secmech.ccmaesdecrypt = NULL;
}
kfree(server->secmech.sdesccmacaes);
server->secmech.sdesccmacaes = NULL;
kfree(server->secmech.sdeschmacsha256);
server->secmech.sdeschmacsha256 = NULL;
kfree(server->secmech.sdeschmacmd5);
server->secmech.sdeschmacmd5 = NULL;
kfree(server->secmech.sdescmd5);
server->secmech.sdescmd5 = NULL;
kfree(server->secmech.sdescsha512);
server->secmech.sdescsha512 = NULL;
}

View file

@ -153,26 +153,16 @@ struct session_key {
char *response;
};
/* crypto security descriptor definition */
struct sdesc {
struct shash_desc shash;
char ctx[];
};
/* crypto hashing related structure/fields, not specific to a sec mech */
struct cifs_secmech {
struct crypto_shash *hmacmd5; /* hmac-md5 hash function */
struct crypto_shash *md5; /* md5 hash function */
struct crypto_shash *hmacsha256; /* hmac-sha256 hash function */
struct crypto_shash *cmacaes; /* block-cipher based MAC function */
struct crypto_shash *sha512; /* sha512 hash function */
struct sdesc *sdeschmacmd5; /* ctxt to generate ntlmv2 hash, CR1 */
struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */
struct sdesc *sdeschmacsha256; /* ctxt to generate smb2 signature */
struct sdesc *sdesccmacaes; /* ctxt to generate smb3 signature */
struct sdesc *sdescsha512; /* ctxt to generate smb3.11 signing key */
struct crypto_aead *ccmaesencrypt; /* smb3 encryption aead */
struct crypto_aead *ccmaesdecrypt; /* smb3 decryption aead */
struct shash_desc *hmacmd5; /* hmacmd5 hash function, for NTLMv2/CR1 hashes */
struct shash_desc *md5; /* md5 hash function, for CIFS/SMB1 signatures */
struct shash_desc *hmacsha256; /* hmac-sha256 hash function, for SMB2 signatures */
struct shash_desc *sha512; /* sha512 hash function, for SMB3.1.1 preauth hash */
struct shash_desc *aes_cmac; /* block-cipher based MAC function, for SMB3 signatures */
struct crypto_aead *enc; /* smb3 encryption AEAD TFM (AES-CCM and AES-GCM) */
struct crypto_aead *dec; /* smb3 decryption AEAD TFM (AES-CCM and AES-GCM) */
};
/* per smb session structure/fields */
@ -1149,7 +1139,7 @@ struct cifs_tcon {
struct list_head openFileList;
spinlock_t open_file_lock; /* protects list above */
struct cifs_ses *ses; /* pointer to session associated with */
char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
char tree_name[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
char *nativeFileSystem;
char *password; /* for share-level security */
__u32 tid; /* The 4 byte tree id */
@ -1228,7 +1218,7 @@ struct cifs_tcon {
struct fscache_volume *fscache; /* cookie for share */
#endif
struct list_head pending_opens; /* list of incomplete opens */
struct cached_fid *cfid; /* Cached root fid */
struct cached_fids *cfids;
/* BB add field for back pointer to sb struct(s)? */
#ifdef CONFIG_CIFS_DFS_UPCALL
struct list_head ulist; /* cache update list */

View file

@ -483,7 +483,7 @@ put_bcc(__u16 count, struct smb_hdr *hdr)
typedef struct negotiate_req {
struct smb_hdr hdr; /* wct = 0 */
__le16 ByteCount;
unsigned char DialectsArray[1];
unsigned char DialectsArray[];
} __attribute__((packed)) NEGOTIATE_REQ;
#define MIN_TZ_ADJ (15 * 60) /* minimum grid for timezones in seconds */
@ -508,13 +508,14 @@ typedef struct negotiate_rsp {
__u8 EncryptionKeyLength;
__u16 ByteCount;
union {
unsigned char EncryptionKey[1]; /* cap extended security off */
/* cap extended security off */
DECLARE_FLEX_ARRAY(unsigned char, EncryptionKey);
/* followed by Domain name - if extended security is off */
/* followed by 16 bytes of server GUID */
/* then security blob if cap_extended_security negotiated */
struct {
unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
unsigned char SecurityBlob[1];
unsigned char SecurityBlob[];
} __attribute__((packed)) extended_response;
} __attribute__((packed)) u;
} __attribute__((packed)) NEGOTIATE_RSP;

View file

@ -598,9 +598,8 @@ struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
void cifs_aio_ctx_release(struct kref *refcount);
int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
struct sdesc **sdesc);
void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
int cifs_alloc_hash(const char *name, struct shash_desc **sdesc);
void cifs_free_hash(struct shash_desc **sdesc);
extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
unsigned int *len, unsigned int *offset);
@ -639,7 +638,7 @@ cifs_chan_is_iface_active(struct cifs_ses *ses,
int
cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server);
int
SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon);
SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount);
void extract_unc_hostname(const char *unc, const char **h, size_t *len);
int copy_path_name(char *dst, const char *src);

View file

@ -465,7 +465,7 @@ CIFSSMBNegotiate(const unsigned int xid,
for (i = 0; i < CIFS_NUM_PROT; i++) {
size_t len = strlen(protocols[i].name) + 1;
memcpy(pSMB->DialectsArray+count, protocols[i].name, len);
memcpy(&pSMB->DialectsArray[count], protocols[i].name, len);
count += len;
}
inc_rfc1001_len(pSMB, count);

View file

@ -155,7 +155,7 @@ static void smb2_query_server_interfaces(struct work_struct *work)
/*
* query server network interfaces, in case they change
*/
rc = SMB3_request_interfaces(0, tcon);
rc = SMB3_request_interfaces(0, tcon, false);
if (rc) {
cifs_dbg(FYI, "%s: failed to query server interfaces: %d\n",
__func__, rc);
@ -311,7 +311,7 @@ cifs_abort_connection(struct TCP_Server_Info *server)
}
server->sequence_number = 0;
server->session_estab = false;
kfree(server->session_key.response);
kfree_sensitive(server->session_key.response);
server->session_key.response = NULL;
server->session_key.len = 0;
server->lstrp = jiffies;
@ -1580,7 +1580,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
cifs_crypto_secmech_release(server);
kfree(server->session_key.response);
kfree_sensitive(server->session_key.response);
server->session_key.response = NULL;
server->session_key.len = 0;
kfree(server->hostname);
@ -1940,7 +1940,8 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
spin_unlock(&ses->ses_lock);
cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
cifs_dbg(FYI, "%s: ses ipc: %s\n", __func__, ses->tcon_ipc ? ses->tcon_ipc->treeName : "NONE");
cifs_dbg(FYI,
"%s: ses ipc: %s\n", __func__, ses->tcon_ipc ? ses->tcon_ipc->tree_name : "NONE");
spin_lock(&cifs_tcp_ses_lock);
if (--ses->ses_count > 0) {
@ -2293,7 +2294,7 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
{
if (tcon->status == TID_EXITING)
return 0;
if (strncmp(tcon->treeName, ctx->UNC, MAX_TREE_SIZE))
if (strncmp(tcon->tree_name, ctx->UNC, MAX_TREE_SIZE))
return 0;
if (tcon->seal != ctx->seal)
return 0;
@ -3989,7 +3990,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
}
bcc_ptr += length + 1;
bytes_left -= (length + 1);
strscpy(tcon->treeName, tree, sizeof(tcon->treeName));
strscpy(tcon->tree_name, tree, sizeof(tcon->tree_name));
/* mostly informational -- no need to fail on error here */
kfree(tcon->nativeFileSystem);
@ -4134,7 +4135,7 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
if (ses->auth_key.response) {
cifs_dbg(FYI, "Free previous auth_key.response = %p\n",
ses->auth_key.response);
kfree(ses->auth_key.response);
kfree_sensitive(ses->auth_key.response);
ses->auth_key.response = NULL;
ses->auth_key.len = 0;
}
@ -4197,7 +4198,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
ctx->local_nls = cifs_sb->local_nls;
ctx->linux_uid = fsuid;
ctx->cred_uid = fsuid;
ctx->UNC = master_tcon->treeName;
ctx->UNC = master_tcon->tree_name;
ctx->retry = master_tcon->retry;
ctx->nocase = master_tcon->nocase;
ctx->nohandlecache = master_tcon->nohandlecache;
@ -4663,7 +4664,7 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
/* If it is not dfs or there was no cached dfs referral, then reconnect to same share */
if (!server->current_fullpath ||
dfs_cache_noreq_find(server->current_fullpath + 1, &ref, &tl)) {
rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, cifs_sb->local_nls);
rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, cifs_sb->local_nls);
goto out;
}
@ -4707,7 +4708,7 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
tcon->status = TID_IN_TCON;
spin_unlock(&tcon->tc_lock);
rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc);
rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, nlsc);
if (rc) {
spin_lock(&tcon->tc_lock);
if (tcon->status == TID_IN_TCON)

View file

@ -98,7 +98,7 @@ static struct cifs_ses *find_ipc_from_server_path(struct cifs_ses **ses, const c
get_ipc_unc(path, unc, sizeof(unc));
for (; *ses; ses++) {
if (!strcasecmp(unc, (*ses)->tcon_ipc->treeName))
if (!strcasecmp(unc, (*ses)->tcon_ipc->tree_name))
return *ses;
}
return ERR_PTR(-ENOENT);

View file

@ -50,7 +50,7 @@ cifs_build_path_to_root(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_s
}
if (add_treename)
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
@ -59,7 +59,7 @@ cifs_build_path_to_root(struct smb3_fs_context *ctx, struct cifs_sb_info *cifs_s
return full_path;
if (dfsplen)
memcpy(full_path, tcon->treeName, dfsplen);
memcpy(full_path, tcon->tree_name, dfsplen);
full_path[dfsplen] = CIFS_DIR_SEP(cifs_sb);
memcpy(full_path + dfsplen + 1, ctx->prepath, pplen);
convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
@ -93,7 +93,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
return ERR_PTR(-ENOMEM);
if (prefix)
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
@ -123,7 +123,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
}
if (dfsplen) {
s -= dfsplen;
memcpy(s, tcon->treeName, dfsplen);
memcpy(s, tcon->tree_name, dfsplen);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
int i;
for (i = 0; i < dfsplen; i++) {

View file

@ -4271,6 +4271,15 @@ static ssize_t __cifs_readv(
len = ctx->len;
}
if (direct) {
rc = filemap_write_and_wait_range(file->f_inode->i_mapping,
offset, offset + len - 1);
if (rc) {
kref_put(&ctx->refcount, cifs_aio_ctx_release);
return -EAGAIN;
}
}
/* grab a lock here due to read response handlers can access ctx */
mutex_lock(&ctx->aio_mutex);

View file

@ -791,6 +791,13 @@ do { \
cifs_sb->ctx->field = NULL; \
} while (0)
#define STEAL_STRING_SENSITIVE(cifs_sb, ctx, field) \
do { \
kfree_sensitive(ctx->field); \
ctx->field = cifs_sb->ctx->field; \
cifs_sb->ctx->field = NULL; \
} while (0)
static int smb3_reconfigure(struct fs_context *fc)
{
struct smb3_fs_context *ctx = smb3_fc2context(fc);
@ -811,7 +818,7 @@ static int smb3_reconfigure(struct fs_context *fc)
STEAL_STRING(cifs_sb, ctx, UNC);
STEAL_STRING(cifs_sb, ctx, source);
STEAL_STRING(cifs_sb, ctx, username);
STEAL_STRING(cifs_sb, ctx, password);
STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
STEAL_STRING(cifs_sb, ctx, domainname);
STEAL_STRING(cifs_sb, ctx, nodename);
STEAL_STRING(cifs_sb, ctx, iocharset);
@ -1162,7 +1169,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
}
break;
case Opt_pass:
kfree(ctx->password);
kfree_sensitive(ctx->password);
ctx->password = NULL;
if (strlen(param->string) == 0)
break;
@ -1470,6 +1477,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
return 0;
cifs_parse_mount_err:
kfree_sensitive(ctx->password);
return -EINVAL;
}

View file

@ -45,7 +45,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
memset(&key, 0, sizeof(key));
sharename = extract_sharename(tcon->treeName);
sharename = extract_sharename(tcon->tree_name);
if (IS_ERR(sharename)) {
cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
return -EINVAL;

View file

@ -913,7 +913,7 @@ cifs_set_fattr_ino(int xid,
} else {
/* make an ino by hashing the UNC */
fattr->cf_flags |= CIFS_FATTR_FAKE_ROOT_INO;
fattr->cf_uniqueid = simple_hashstr(tcon->treeName);
fattr->cf_uniqueid = simple_hashstr(tcon->tree_name);
}
}
}

View file

@ -38,29 +38,28 @@ static int
symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
{
int rc;
struct crypto_shash *md5 = NULL;
struct sdesc *sdescmd5 = NULL;
struct shash_desc *md5 = NULL;
rc = cifs_alloc_hash("md5", &md5, &sdescmd5);
rc = cifs_alloc_hash("md5", &md5);
if (rc)
goto symlink_hash_err;
rc = crypto_shash_init(&sdescmd5->shash);
rc = crypto_shash_init(md5);
if (rc) {
cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__);
goto symlink_hash_err;
}
rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
rc = crypto_shash_update(md5, link_str, link_len);
if (rc) {
cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
goto symlink_hash_err;
}
rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
rc = crypto_shash_final(md5, md5_hash);
if (rc)
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
symlink_hash_err:
cifs_free_hash(&md5, &sdescmd5);
cifs_free_hash(&md5);
return rc;
}

View file

@ -117,8 +117,8 @@ tconInfoAlloc(void)
ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL);
if (!ret_buf)
return NULL;
ret_buf->cfid = init_cached_dir();
if (!ret_buf->cfid) {
ret_buf->cfids = init_cached_dirs();
if (!ret_buf->cfids) {
kfree(ret_buf);
return NULL;
}
@ -144,7 +144,7 @@ tconInfoFree(struct cifs_tcon *tcon)
cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n");
return;
}
free_cached_dir(tcon);
free_cached_dirs(tcon->cfids);
atomic_dec(&tconInfoAllocCount);
kfree(tcon->nativeFileSystem);
kfree_sensitive(tcon->password);
@ -525,7 +525,7 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb)
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
cifs_sb->mnt_cifs_serverino_autodisabled = true;
cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s\n",
tcon ? tcon->treeName : "new server");
tcon ? tcon->tree_name : "new server");
cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS)\n");
cifs_dbg(VFS, "Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message.\n");
@ -824,7 +824,7 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
free_dentry_path(page);
}
/* parses DFS refferal V3 structure
/* parses DFS referral V3 structure
* caller is responsible for freeing target_nodes
* returns:
* - on success - 0
@ -1071,59 +1071,58 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
/**
* cifs_alloc_hash - allocate hash and hash context together
* @name: The name of the crypto hash algo
* @shash: Where to put the pointer to the hash algo
* @sdesc: Where to put the pointer to the hash descriptor
* @sdesc: SHASH descriptor where to put the pointer to the hash TFM
*
* The caller has to make sure @sdesc is initialized to either NULL or
* a valid context. Both can be freed via cifs_free_hash().
* a valid context. It can be freed via cifs_free_hash().
*/
int
cifs_alloc_hash(const char *name,
struct crypto_shash **shash, struct sdesc **sdesc)
cifs_alloc_hash(const char *name, struct shash_desc **sdesc)
{
int rc = 0;
size_t size;
struct crypto_shash *alg = NULL;
if (*sdesc != NULL)
if (*sdesc)
return 0;
*shash = crypto_alloc_shash(name, 0, 0);
if (IS_ERR(*shash)) {
cifs_dbg(VFS, "Could not allocate crypto %s\n", name);
rc = PTR_ERR(*shash);
*shash = NULL;
alg = crypto_alloc_shash(name, 0, 0);
if (IS_ERR(alg)) {
cifs_dbg(VFS, "Could not allocate shash TFM '%s'\n", name);
rc = PTR_ERR(alg);
*sdesc = NULL;
return rc;
}
size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash);
*sdesc = kmalloc(size, GFP_KERNEL);
*sdesc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(alg), GFP_KERNEL);
if (*sdesc == NULL) {
cifs_dbg(VFS, "no memory left to allocate crypto %s\n", name);
crypto_free_shash(*shash);
*shash = NULL;
cifs_dbg(VFS, "no memory left to allocate shash TFM '%s'\n", name);
crypto_free_shash(alg);
return -ENOMEM;
}
(*sdesc)->shash.tfm = *shash;
(*sdesc)->tfm = alg;
return 0;
}
/**
* cifs_free_hash - free hash and hash context together
* @shash: Where to find the pointer to the hash algo
* @sdesc: Where to find the pointer to the hash descriptor
* @sdesc: Where to find the pointer to the hash TFM
*
* Freeing a NULL hash or context is safe.
* Freeing a NULL descriptor is safe.
*/
void
cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
cifs_free_hash(struct shash_desc **sdesc)
{
kfree(*sdesc);
if (unlikely(!sdesc) || !*sdesc)
return;
if ((*sdesc)->tfm) {
crypto_free_shash((*sdesc)->tfm);
(*sdesc)->tfm = NULL;
}
kfree_sensitive(*sdesc);
*sdesc = NULL;
if (*shash)
crypto_free_shash(*shash);
*shash = NULL;
}
/**
@ -1328,7 +1327,7 @@ int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid,
char *treename, *dfspath, sep;
int treenamelen, linkpathlen, rc;
treename = tcon->treeName;
treename = tcon->tree_name;
/* MS-DFSC: All paths in REQ_GET_DFS_REFERRAL and RESP_GET_DFS_REFERRAL
* messages MUST be encoded with exactly one leading backslash, not two
* leading backslashes.

View file

@ -1213,6 +1213,12 @@ sess_alloc_buffer(struct sess_data *sess_data, int wct)
static void
sess_free_buffer(struct sess_data *sess_data)
{
int i;
/* zero the session data before freeing, as it might contain sensitive info (keys, etc) */
for (i = 0; i < 3; i++)
if (sess_data->iov[i].iov_base)
memzero_explicit(sess_data->iov[i].iov_base, sess_data->iov[i].iov_len);
free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
sess_data->buf0_type = CIFS_NO_BUFFER;
@ -1374,7 +1380,7 @@ sess_auth_ntlmv2(struct sess_data *sess_data)
sess_data->result = rc;
sess_data->func = NULL;
sess_free_buffer(sess_data);
kfree(ses->auth_key.response);
kfree_sensitive(ses->auth_key.response);
ses->auth_key.response = NULL;
}
@ -1513,7 +1519,7 @@ sess_auth_kerberos(struct sess_data *sess_data)
sess_data->result = rc;
sess_data->func = NULL;
sess_free_buffer(sess_data);
kfree(ses->auth_key.response);
kfree_sensitive(ses->auth_key.response);
ses->auth_key.response = NULL;
}
@ -1648,7 +1654,7 @@ sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
out_free_ntlmsspblob:
kfree(ntlmsspblob);
kfree_sensitive(ntlmsspblob);
out:
sess_free_buffer(sess_data);
@ -1658,9 +1664,9 @@ sess_auth_rawntlmssp_negotiate(struct sess_data *sess_data)
}
/* Else error. Cleanup */
kfree(ses->auth_key.response);
kfree_sensitive(ses->auth_key.response);
ses->auth_key.response = NULL;
kfree(ses->ntlmssp);
kfree_sensitive(ses->ntlmssp);
ses->ntlmssp = NULL;
sess_data->func = NULL;
@ -1759,7 +1765,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
}
out_free_ntlmsspblob:
kfree(ntlmsspblob);
kfree_sensitive(ntlmsspblob);
out:
sess_free_buffer(sess_data);
@ -1767,9 +1773,9 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
rc = sess_establish_session(sess_data);
/* Cleanup */
kfree(ses->auth_key.response);
kfree_sensitive(ses->auth_key.response);
ses->auth_key.response = NULL;
kfree(ses->ntlmssp);
kfree_sensitive(ses->ntlmssp);
ses->ntlmssp = NULL;
sess_data->func = NULL;
@ -1845,7 +1851,7 @@ int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
rc = sess_data->result;
out:
kfree(sess_data);
kfree_sensitive(sess_data);
return rc;
}
#endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */

View file

@ -379,7 +379,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
SMB2_open_free(&rqst[0]);
if (rc == -EREMCHG) {
pr_warn_once("server share %s deleted\n", tcon->treeName);
pr_warn_once("server share %s deleted\n", tcon->tree_name);
tcon->need_reconnect = true;
}

View file

@ -870,8 +870,8 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct TCP_Server_Info *server,
struct kvec *iov, int nvec)
{
int i, rc;
struct sdesc *d;
struct smb2_hdr *hdr;
struct shash_desc *sha512 = NULL;
hdr = (struct smb2_hdr *)iov[0].iov_base;
/* neg prot are always taken */
@ -901,14 +901,14 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct TCP_Server_Info *server,
if (rc)
return rc;
d = server->secmech.sdescsha512;
rc = crypto_shash_init(&d->shash);
sha512 = server->secmech.sha512;
rc = crypto_shash_init(sha512);
if (rc) {
cifs_dbg(VFS, "%s: Could not init sha512 shash\n", __func__);
return rc;
}
rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash,
rc = crypto_shash_update(sha512, ses->preauth_sha_hash,
SMB2_PREAUTH_HASH_SIZE);
if (rc) {
cifs_dbg(VFS, "%s: Could not update sha512 shash\n", __func__);
@ -916,8 +916,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct TCP_Server_Info *server,
}
for (i = 0; i < nvec; i++) {
rc = crypto_shash_update(&d->shash,
iov[i].iov_base, iov[i].iov_len);
rc = crypto_shash_update(sha512, iov[i].iov_base, iov[i].iov_len);
if (rc) {
cifs_dbg(VFS, "%s: Could not update sha512 shash\n",
__func__);
@ -925,7 +924,7 @@ smb311_update_preauth_hash(struct cifs_ses *ses, struct TCP_Server_Info *server,
}
}
rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash);
rc = crypto_shash_final(sha512, ses->preauth_sha_hash);
if (rc) {
cifs_dbg(VFS, "%s: Could not finalize sha512 shash\n",
__func__);

View file

@ -512,8 +512,7 @@ smb3_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
static int
parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
size_t buf_len,
struct cifs_ses *ses)
size_t buf_len, struct cifs_ses *ses, bool in_mount)
{
struct network_interface_info_ioctl_rsp *p;
struct sockaddr_in *addr4;
@ -543,6 +542,20 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
}
spin_unlock(&ses->iface_lock);
/*
* Samba server e.g. can return an empty interface list in some cases,
* which would only be a problem if we were requesting multichannel
*/
if (bytes_left == 0) {
/* avoid spamming logs every 10 minutes, so log only in mount */
if ((ses->chan_max > 1) && in_mount)
cifs_dbg(VFS,
"empty network interface list returned by server %s\n",
ses->server->hostname);
rc = -EINVAL;
goto out;
}
while (bytes_left >= sizeof(*p)) {
memset(&tmp_iface, 0, sizeof(tmp_iface));
tmp_iface.speed = le64_to_cpu(p->LinkSpeed);
@ -673,7 +686,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
}
int
SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount)
{
int rc;
unsigned int ret_data_len = 0;
@ -693,7 +706,7 @@ SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
goto out;
}
rc = parse_server_interfaces(out_buf, ret_data_len, ses);
rc = parse_server_interfaces(out_buf, ret_data_len, ses, in_mount);
if (rc)
goto out;
@ -729,7 +742,7 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon,
if (rc)
return;
SMB3_request_interfaces(xid, tcon);
SMB3_request_interfaces(xid, tcon, true /* called during mount */);
SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
FS_ATTRIBUTE_INFORMATION);
@ -1327,7 +1340,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
CIFSMaxBufSize, (char **)&res_key, &ret_data_len);
if (rc == -EOPNOTSUPP) {
pr_warn_once("Server share %s does not support copy range\n", tcon->treeName);
pr_warn_once("Server share %s does not support copy range\n", tcon->tree_name);
goto req_res_key_exit;
} else if (rc) {
cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc);
@ -2289,7 +2302,7 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
spin_unlock(&tcon->tc_lock);
spin_unlock(&cifs_tcp_ses_lock);
pr_warn_once("Server share %s deleted.\n",
tcon->treeName);
tcon->tree_name);
return;
}
}
@ -2498,7 +2511,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
if (rc == -EREMCHG) {
tcon->need_reconnect = true;
pr_warn_once("server share %s deleted\n",
tcon->treeName);
tcon->tree_name);
}
goto qic_exit;
}
@ -4344,8 +4357,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
return rc;
}
tfm = enc ? server->secmech.ccmaesencrypt :
server->secmech.ccmaesdecrypt;
tfm = enc ? server->secmech.enc : server->secmech.dec;
if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
@ -4410,11 +4422,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
if (!rc && enc)
memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
kfree(iv);
kfree_sensitive(iv);
free_sg:
kfree(sg);
kfree_sensitive(sg);
free_req:
kfree(req);
kfree_sensitive(req);
return rc;
}

View file

@ -873,7 +873,7 @@ SMB2_negotiate(const unsigned int xid,
struct smb2_negotiate_rsp *rsp;
struct kvec iov[1];
struct kvec rsp_iov;
int rc = 0;
int rc;
int resp_buftype;
int blob_offset, blob_length;
char *security_blob;
@ -1169,9 +1169,9 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
pneg_inbuf->Dialects[0] =
cpu_to_le16(server->vals->protocol_id);
pneg_inbuf->DialectCount = cpu_to_le16(1);
/* structure is big enough for 3 dialects, sending only 1 */
/* structure is big enough for 4 dialects, sending only 1 */
inbuflen = sizeof(*pneg_inbuf) -
sizeof(pneg_inbuf->Dialects[0]) * 2;
sizeof(pneg_inbuf->Dialects[0]) * 3;
}
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
@ -1345,6 +1345,13 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
static void
SMB2_sess_free_buffer(struct SMB2_sess_data *sess_data)
{
int i;
/* zero the session data before freeing, as it might contain sensitive info (keys, etc) */
for (i = 0; i < 2; i++)
if (sess_data->iov[i].iov_base)
memzero_explicit(sess_data->iov[i].iov_base, sess_data->iov[i].iov_len);
free_rsp_buf(sess_data->buf0_type, sess_data->iov[0].iov_base);
sess_data->buf0_type = CIFS_NO_BUFFER;
}
@ -1477,6 +1484,8 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
out_put_spnego_key:
key_invalidate(spnego_key);
key_put(spnego_key);
if (rc)
kfree_sensitive(ses->auth_key.response);
out:
sess_data->result = rc;
sess_data->func = NULL;
@ -1573,7 +1582,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
}
out:
kfree(ntlmssp_blob);
memzero_explicit(ntlmssp_blob, blob_length);
SMB2_sess_free_buffer(sess_data);
if (!rc) {
sess_data->result = 0;
@ -1581,7 +1590,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
return;
}
out_err:
kfree(ses->ntlmssp);
kfree_sensitive(ses->ntlmssp);
ses->ntlmssp = NULL;
sess_data->result = rc;
sess_data->func = NULL;
@ -1657,9 +1666,9 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
}
#endif
out:
kfree(ntlmssp_blob);
memzero_explicit(ntlmssp_blob, blob_length);
SMB2_sess_free_buffer(sess_data);
kfree(ses->ntlmssp);
kfree_sensitive(ses->ntlmssp);
ses->ntlmssp = NULL;
sess_data->result = rc;
sess_data->func = NULL;
@ -1737,7 +1746,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
cifs_server_dbg(VFS, "signing requested but authenticated as guest\n");
rc = sess_data->result;
out:
kfree(sess_data);
kfree_sensitive(sess_data);
return rc;
}
@ -1930,7 +1939,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */
tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
tcon->tid = le32_to_cpu(rsp->hdr.Id.SyncId.TreeId);
strscpy(tcon->treeName, tree, sizeof(tcon->treeName));
strscpy(tcon->tree_name, tree, sizeof(tcon->tree_name));
if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
@ -1973,6 +1982,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
if (!ses || !(ses->server))
return -EIO;
trace_smb3_tdis_enter(xid, tcon->tid, ses->Suid, tcon->tree_name);
spin_lock(&ses->chan_lock);
if ((tcon->need_reconnect) ||
(CIFS_ALL_CHANS_NEED_RECONNECT(tcon->ses))) {
@ -2004,8 +2014,11 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
rc = cifs_send_recv(xid, ses, ses->server,
&rqst, &resp_buf_type, flags, &rsp_iov);
cifs_small_buf_release(req);
if (rc)
if (rc) {
cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE);
trace_smb3_tdis_err(xid, tcon->tid, ses->Suid, rc);
}
trace_smb3_tdis_done(xid, tcon->tid, ses->Suid);
return rc;
}
@ -2674,7 +2687,7 @@ int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
req->hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
&name_len,
tcon->treeName, utf16_path);
tcon->tree_name, utf16_path);
if (rc)
goto err_free_req;
@ -2816,7 +2829,7 @@ SMB2_open_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
req->hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
&name_len,
tcon->treeName, path);
tcon->tree_name, path);
if (rc)
return rc;
req->NameLength = cpu_to_le16(name_len * 2);
@ -3011,7 +3024,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
oparms->create_options, oparms->desired_access, rc);
if (rc == -EREMCHG) {
pr_warn_once("server share %s deleted\n",
tcon->treeName);
tcon->tree_name);
tcon->need_reconnect = true;
}
goto creat_exit;
@ -4429,7 +4442,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
wdata->bytes, wdata->result);
if (wdata->result == -ENOSPC)
pr_warn_once("Out of space writing to %s\n",
tcon->treeName);
tcon->tree_name);
} else
trace_smb3_write_done(0 /* no xid */,
wdata->cfile->fid.persistent_fid,

View file

@ -32,19 +32,17 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
struct cifs_secmech *p = &server->secmech;
int rc;
rc = cifs_alloc_hash("hmac(sha256)",
&p->hmacsha256,
&p->sdeschmacsha256);
rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);
if (rc)
goto err;
rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);
if (rc)
goto err;
return 0;
err:
cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
cifs_free_hash(&p->hmacsha256);
return rc;
}
@ -54,25 +52,23 @@ smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
struct cifs_secmech *p = &server->secmech;
int rc = 0;
rc = cifs_alloc_hash("hmac(sha256)",
&p->hmacsha256,
&p->sdeschmacsha256);
rc = cifs_alloc_hash("hmac(sha256)", &p->hmacsha256);
if (rc)
return rc;
rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
rc = cifs_alloc_hash("cmac(aes)", &p->aes_cmac);
if (rc)
goto err;
rc = cifs_alloc_hash("sha512", &p->sha512, &p->sdescsha512);
rc = cifs_alloc_hash("sha512", &p->sha512);
if (rc)
goto err;
return 0;
err:
cifs_free_hash(&p->cmacaes, &p->sdesccmacaes);
cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
cifs_free_hash(&p->aes_cmac);
cifs_free_hash(&p->hmacsha256);
return rc;
}
@ -219,34 +215,30 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
struct kvec *iov = rqst->rq_iov;
struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
struct cifs_ses *ses;
struct shash_desc *shash;
struct crypto_shash *hash;
struct sdesc *sdesc = NULL;
struct shash_desc *shash = NULL;
struct smb_rqst drqst;
ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId));
if (!ses) {
if (unlikely(!ses)) {
cifs_server_dbg(VFS, "%s: Could not find session\n", __func__);
return 0;
return -ENOENT;
}
memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
if (allocate_crypto) {
rc = cifs_alloc_hash("hmac(sha256)", &hash, &sdesc);
rc = cifs_alloc_hash("hmac(sha256)", &shash);
if (rc) {
cifs_server_dbg(VFS,
"%s: sha256 alloc failed\n", __func__);
goto out;
}
shash = &sdesc->shash;
} else {
hash = server->secmech.hmacsha256;
shash = &server->secmech.sdeschmacsha256->shash;
shash = server->secmech.hmacsha256;
}
rc = crypto_shash_setkey(hash, ses->auth_key.response,
rc = crypto_shash_setkey(shash->tfm, ses->auth_key.response,
SMB2_NTLMV2_SESSKEY_SIZE);
if (rc) {
cifs_server_dbg(VFS,
@ -288,7 +280,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
out:
if (allocate_crypto)
cifs_free_hash(&hash, &sdesc);
cifs_free_hash(&shash);
if (ses)
cifs_put_smb_ses(ses);
return rc;
@ -315,42 +307,38 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
goto smb3signkey_ret;
}
rc = crypto_shash_setkey(server->secmech.hmacsha256,
rc = crypto_shash_setkey(server->secmech.hmacsha256->tfm,
ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not set with session key\n", __func__);
goto smb3signkey_ret;
}
rc = crypto_shash_init(&server->secmech.sdeschmacsha256->shash);
rc = crypto_shash_init(server->secmech.hmacsha256);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not init sign hmac\n", __func__);
goto smb3signkey_ret;
}
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
i, 4);
rc = crypto_shash_update(server->secmech.hmacsha256, i, 4);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not update with n\n", __func__);
goto smb3signkey_ret;
}
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
label.iov_base, label.iov_len);
rc = crypto_shash_update(server->secmech.hmacsha256, label.iov_base, label.iov_len);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not update with label\n", __func__);
goto smb3signkey_ret;
}
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
&zero, 1);
rc = crypto_shash_update(server->secmech.hmacsha256, &zero, 1);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not update with zero\n", __func__);
goto smb3signkey_ret;
}
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
context.iov_base, context.iov_len);
rc = crypto_shash_update(server->secmech.hmacsha256, context.iov_base, context.iov_len);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not update with context\n", __func__);
goto smb3signkey_ret;
@ -358,19 +346,16 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
L256, 4);
rc = crypto_shash_update(server->secmech.hmacsha256, L256, 4);
} else {
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
L128, 4);
rc = crypto_shash_update(server->secmech.hmacsha256, L128, 4);
}
if (rc) {
cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
goto smb3signkey_ret;
}
rc = crypto_shash_final(&server->secmech.sdeschmacsha256->shash,
hashptr);
rc = crypto_shash_final(server->secmech.hmacsha256, hashptr);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not generate sha256 hash\n", __func__);
goto smb3signkey_ret;
@ -550,38 +535,35 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
unsigned char *sigptr = smb3_signature;
struct kvec *iov = rqst->rq_iov;
struct smb2_hdr *shdr = (struct smb2_hdr *)iov[0].iov_base;
struct shash_desc *shash;
struct crypto_shash *hash;
struct sdesc *sdesc = NULL;
struct shash_desc *shash = NULL;
struct smb_rqst drqst;
u8 key[SMB3_SIGN_KEY_SIZE];
rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key);
if (rc)
return 0;
if (unlikely(rc)) {
cifs_server_dbg(VFS, "%s: Could not get signing key\n", __func__);
return rc;
}
if (allocate_crypto) {
rc = cifs_alloc_hash("cmac(aes)", &hash, &sdesc);
rc = cifs_alloc_hash("cmac(aes)", &shash);
if (rc)
return rc;
shash = &sdesc->shash;
} else {
hash = server->secmech.cmacaes;
shash = &server->secmech.sdesccmacaes->shash;
shash = server->secmech.aes_cmac;
}
memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
rc = crypto_shash_setkey(hash, key, SMB2_CMACAES_SIZE);
rc = crypto_shash_setkey(shash->tfm, key, SMB2_CMACAES_SIZE);
if (rc) {
cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
goto out;
}
/*
* we already allocate sdesccmacaes when we init smb3 signing key,
* we already allocate aes_cmac when we init smb3 signing key,
* so unlike smb2 case we do not have to check here if secmech are
* initialized
*/
@ -617,7 +599,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
out:
if (allocate_crypto)
cifs_free_hash(&hash, &sdesc);
cifs_free_hash(&shash);
return rc;
}
@ -902,7 +884,7 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
{
struct crypto_aead *tfm;
if (!server->secmech.ccmaesencrypt) {
if (!server->secmech.enc) {
if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
@ -913,23 +895,23 @@ smb3_crypto_aead_allocate(struct TCP_Server_Info *server)
__func__);
return PTR_ERR(tfm);
}
server->secmech.ccmaesencrypt = tfm;
server->secmech.enc = tfm;
}
if (!server->secmech.ccmaesdecrypt) {
if (!server->secmech.dec) {
if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) ||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
else
tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
if (IS_ERR(tfm)) {
crypto_free_aead(server->secmech.ccmaesencrypt);
server->secmech.ccmaesencrypt = NULL;
crypto_free_aead(server->secmech.enc);
server->secmech.enc = NULL;
cifs_server_dbg(VFS, "%s: Failed to alloc decrypt aead\n",
__func__);
return PTR_ERR(tfm);
}
server->secmech.ccmaesdecrypt = tfm;
server->secmech.dec = tfm;
}
return 0;

View file

@ -90,7 +90,7 @@ int smbd_max_send_size = 1364;
int smbd_max_fragmented_recv_size = 1024 * 1024;
/* The maximum single-message size which can be received */
int smbd_max_receive_size = 8192;
int smbd_max_receive_size = 1364;
/* The timeout to initiate send of a keepalive message on idle */
int smbd_keep_alive_interval = 120;
@ -99,7 +99,7 @@ int smbd_keep_alive_interval = 120;
* User configurable initial values for RDMA transport
* The actual values used may be lower and are limited to hardware capabilities
*/
/* Default maximum number of SGEs in a RDMA write/read */
/* Default maximum number of pages in a single RDMA write/read */
int smbd_max_frmr_depth = 2048;
/* If payload is less than this byte, use RDMA send/recv not read/write */
@ -270,7 +270,7 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc)
struct smbd_request *request =
container_of(wc->wr_cqe, struct smbd_request, cqe);
log_rdma_send(INFO, "smbd_request %p completed wc->status=%d\n",
log_rdma_send(INFO, "smbd_request 0x%p completed wc->status=%d\n",
request, wc->status);
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) {
@ -448,7 +448,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
struct smbd_connection *info = response->info;
int data_length = 0;
log_rdma_recv(INFO, "response=%p type=%d wc status=%d wc opcode %d byte_len=%d pkey_index=%x\n",
log_rdma_recv(INFO, "response=0x%p type=%d wc status=%d wc opcode %d byte_len=%d pkey_index=%u\n",
response, response->type, wc->status, wc->opcode,
wc->byte_len, wc->pkey_index);
@ -723,7 +723,7 @@ static int smbd_post_send_negotiate_req(struct smbd_connection *info)
send_wr.opcode = IB_WR_SEND;
send_wr.send_flags = IB_SEND_SIGNALED;
log_rdma_send(INFO, "sge addr=%llx length=%x lkey=%x\n",
log_rdma_send(INFO, "sge addr=0x%llx length=%u lkey=0x%x\n",
request->sge[0].addr,
request->sge[0].length, request->sge[0].lkey);
@ -792,7 +792,7 @@ static int smbd_post_send(struct smbd_connection *info,
for (i = 0; i < request->num_sge; i++) {
log_rdma_send(INFO,
"rdma_request sge[%d] addr=%llu length=%u\n",
"rdma_request sge[%d] addr=0x%llx length=%u\n",
i, request->sge[i].addr, request->sge[i].length);
ib_dma_sync_single_for_device(
info->id->device,
@ -1017,9 +1017,9 @@ static int smbd_post_send_data(
{
int i;
u32 data_length = 0;
struct scatterlist sgl[SMBDIRECT_MAX_SGE];
struct scatterlist sgl[SMBDIRECT_MAX_SEND_SGE - 1];
if (n_vec > SMBDIRECT_MAX_SGE) {
if (n_vec > SMBDIRECT_MAX_SEND_SGE - 1) {
cifs_dbg(VFS, "Can't fit data to SGL, n_vec=%d\n", n_vec);
return -EINVAL;
}
@ -1079,7 +1079,7 @@ static int smbd_negotiate(struct smbd_connection *info)
response->type = SMBD_NEGOTIATE_RESP;
rc = smbd_post_recv(info, response);
log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=%llx iov.length=%x iov.lkey=%x\n",
log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=0x%llx iov.length=%u iov.lkey=0x%x\n",
rc, response->sge.addr,
response->sge.length, response->sge.lkey);
if (rc)
@ -1539,7 +1539,7 @@ static struct smbd_connection *_smbd_get_connection(
if (smbd_send_credit_target > info->id->device->attrs.max_cqe ||
smbd_send_credit_target > info->id->device->attrs.max_qp_wr) {
log_rdma_event(ERR, "consider lowering send_credit_target = %d. Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n",
log_rdma_event(ERR, "consider lowering send_credit_target = %d. Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
smbd_send_credit_target,
info->id->device->attrs.max_cqe,
info->id->device->attrs.max_qp_wr);
@ -1548,7 +1548,7 @@ static struct smbd_connection *_smbd_get_connection(
if (smbd_receive_credit_max > info->id->device->attrs.max_cqe ||
smbd_receive_credit_max > info->id->device->attrs.max_qp_wr) {
log_rdma_event(ERR, "consider lowering receive_credit_max = %d. Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n",
log_rdma_event(ERR, "consider lowering receive_credit_max = %d. Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n",
smbd_receive_credit_max,
info->id->device->attrs.max_cqe,
info->id->device->attrs.max_qp_wr);
@ -1562,17 +1562,15 @@ static struct smbd_connection *_smbd_get_connection(
info->max_receive_size = smbd_max_receive_size;
info->keep_alive_interval = smbd_keep_alive_interval;
if (info->id->device->attrs.max_send_sge < SMBDIRECT_MAX_SGE) {
if (info->id->device->attrs.max_send_sge < SMBDIRECT_MAX_SEND_SGE ||
info->id->device->attrs.max_recv_sge < SMBDIRECT_MAX_RECV_SGE) {
log_rdma_event(ERR,
"warning: device max_send_sge = %d too small\n",
info->id->device->attrs.max_send_sge);
log_rdma_event(ERR, "Queue Pair creation may fail\n");
}
if (info->id->device->attrs.max_recv_sge < SMBDIRECT_MAX_SGE) {
log_rdma_event(ERR,
"warning: device max_recv_sge = %d too small\n",
"device %.*s max_send_sge/max_recv_sge = %d/%d too small\n",
IB_DEVICE_NAME_MAX,
info->id->device->name,
info->id->device->attrs.max_send_sge,
info->id->device->attrs.max_recv_sge);
log_rdma_event(ERR, "Queue Pair creation may fail\n");
goto config_failed;
}
info->send_cq = NULL;
@ -1598,8 +1596,8 @@ static struct smbd_connection *_smbd_get_connection(
qp_attr.qp_context = info;
qp_attr.cap.max_send_wr = info->send_credit_target;
qp_attr.cap.max_recv_wr = info->receive_credit_max;
qp_attr.cap.max_send_sge = SMBDIRECT_MAX_SGE;
qp_attr.cap.max_recv_sge = SMBDIRECT_MAX_SGE;
qp_attr.cap.max_send_sge = SMBDIRECT_MAX_SEND_SGE;
qp_attr.cap.max_recv_sge = SMBDIRECT_MAX_RECV_SGE;
qp_attr.cap.max_inline_data = 0;
qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
qp_attr.qp_type = IB_QPT_RC;
@ -1986,10 +1984,11 @@ int smbd_send(struct TCP_Server_Info *server,
int num_rqst, struct smb_rqst *rqst_array)
{
struct smbd_connection *info = server->smbd_conn;
struct kvec vec;
struct kvec vecs[SMBDIRECT_MAX_SEND_SGE - 1];
int nvecs;
int size;
unsigned int buflen, remaining_data_length;
unsigned int offset, remaining_vec_data_length;
int start, i, j;
int max_iov_size =
info->max_send_size - sizeof(struct smbd_data_transfer);
@ -1998,10 +1997,8 @@ int smbd_send(struct TCP_Server_Info *server,
struct smb_rqst *rqst;
int rqst_idx;
if (info->transport_status != SMBD_CONNECTED) {
rc = -EAGAIN;
goto done;
}
if (info->transport_status != SMBD_CONNECTED)
return -EAGAIN;
/*
* Add in the page array if there is one. The caller needs to set
@ -2012,125 +2009,95 @@ int smbd_send(struct TCP_Server_Info *server,
for (i = 0; i < num_rqst; i++)
remaining_data_length += smb_rqst_len(server, &rqst_array[i]);
if (remaining_data_length > info->max_fragmented_send_size) {
if (unlikely(remaining_data_length > info->max_fragmented_send_size)) {
/* assertion: payload never exceeds negotiated maximum */
log_write(ERR, "payload size %d > max size %d\n",
remaining_data_length, info->max_fragmented_send_size);
rc = -EINVAL;
goto done;
return -EINVAL;
}
log_write(INFO, "num_rqst=%d total length=%u\n",
num_rqst, remaining_data_length);
rqst_idx = 0;
next_rqst:
rqst = &rqst_array[rqst_idx];
iov = rqst->rq_iov;
do {
rqst = &rqst_array[rqst_idx];
iov = rqst->rq_iov;
cifs_dbg(FYI, "Sending smb (RDMA): idx=%d smb_len=%lu\n",
rqst_idx, smb_rqst_len(server, rqst));
for (i = 0; i < rqst->rq_nvec; i++)
dump_smb(iov[i].iov_base, iov[i].iov_len);
log_write(INFO, "rqst_idx=%d nvec=%d rqst->rq_npages=%d rq_pagesz=%d rq_tailsz=%d buflen=%lu\n",
rqst_idx, rqst->rq_nvec, rqst->rq_npages, rqst->rq_pagesz,
rqst->rq_tailsz, smb_rqst_len(server, rqst));
start = i = 0;
buflen = 0;
while (true) {
buflen += iov[i].iov_len;
if (buflen > max_iov_size) {
if (i > start) {
remaining_data_length -=
(buflen-iov[i].iov_len);
log_write(INFO, "sending iov[] from start=%d i=%d nvecs=%d remaining_data_length=%d\n",
start, i, i - start,
remaining_data_length);
rc = smbd_post_send_data(
info, &iov[start], i-start,
remaining_data_length);
if (rc)
goto done;
} else {
/* iov[start] is too big, break it */
nvecs = (buflen+max_iov_size-1)/max_iov_size;
log_write(INFO, "iov[%d] iov_base=%p buflen=%d break to %d vectors\n",
start, iov[start].iov_base,
buflen, nvecs);
for (j = 0; j < nvecs; j++) {
vec.iov_base =
(char *)iov[start].iov_base +
j*max_iov_size;
vec.iov_len = max_iov_size;
if (j == nvecs-1)
vec.iov_len =
buflen -
max_iov_size*(nvecs-1);
remaining_data_length -= vec.iov_len;
log_write(INFO,
"sending vec j=%d iov_base=%p iov_len=%zu remaining_data_length=%d\n",
j, vec.iov_base, vec.iov_len,
remaining_data_length);
rc = smbd_post_send_data(
info, &vec, 1,
remaining_data_length);
if (rc)
goto done;
}
i++;
if (i == rqst->rq_nvec)
break;
}
start = i;
buflen = 0;
} else {
i++;
if (i == rqst->rq_nvec) {
/* send out all remaining vecs */
remaining_data_length -= buflen;
log_write(INFO, "sending iov[] from start=%d i=%d nvecs=%d remaining_data_length=%d\n",
start, i, i - start,
remaining_data_length);
rc = smbd_post_send_data(info, &iov[start],
i-start, remaining_data_length);
if (rc)
goto done;
break;
}
cifs_dbg(FYI, "Sending smb (RDMA): idx=%d smb_len=%lu\n",
rqst_idx, smb_rqst_len(server, rqst));
remaining_vec_data_length = 0;
for (i = 0; i < rqst->rq_nvec; i++) {
remaining_vec_data_length += iov[i].iov_len;
dump_smb(iov[i].iov_base, iov[i].iov_len);
}
log_write(INFO, "looping i=%d buflen=%d\n", i, buflen);
}
/* now sending pages if there are any */
for (i = 0; i < rqst->rq_npages; i++) {
unsigned int offset;
log_write(INFO, "rqst_idx=%d nvec=%d rqst->rq_npages=%d rq_pagesz=%d rq_tailsz=%d buflen=%lu\n",
rqst_idx, rqst->rq_nvec,
rqst->rq_npages, rqst->rq_pagesz,
rqst->rq_tailsz, smb_rqst_len(server, rqst));
rqst_page_get_length(rqst, i, &buflen, &offset);
nvecs = (buflen + max_iov_size - 1) / max_iov_size;
log_write(INFO, "sending pages buflen=%d nvecs=%d\n",
buflen, nvecs);
for (j = 0; j < nvecs; j++) {
size = max_iov_size;
if (j == nvecs-1)
size = buflen - j*max_iov_size;
remaining_data_length -= size;
log_write(INFO, "sending pages i=%d offset=%d size=%d remaining_data_length=%d\n",
i, j * max_iov_size + offset, size,
remaining_data_length);
rc = smbd_post_send_page(
info, rqst->rq_pages[i],
j*max_iov_size + offset,
size, remaining_data_length);
start = 0;
offset = 0;
do {
buflen = 0;
i = start;
j = 0;
while (i < rqst->rq_nvec &&
j < SMBDIRECT_MAX_SEND_SGE - 1 &&
buflen < max_iov_size) {
vecs[j].iov_base = iov[i].iov_base + offset;
if (buflen + iov[i].iov_len > max_iov_size) {
vecs[j].iov_len =
max_iov_size - iov[i].iov_len;
buflen = max_iov_size;
offset = vecs[j].iov_len;
} else {
vecs[j].iov_len =
iov[i].iov_len - offset;
buflen += vecs[j].iov_len;
offset = 0;
++i;
}
++j;
}
remaining_vec_data_length -= buflen;
remaining_data_length -= buflen;
log_write(INFO, "sending %s iov[%d] from start=%d nvecs=%d remaining_data_length=%d\n",
remaining_vec_data_length > 0 ?
"partial" : "complete",
rqst->rq_nvec, start, j,
remaining_data_length);
start = i;
rc = smbd_post_send_data(info, vecs, j, remaining_data_length);
if (rc)
goto done;
}
}
} while (remaining_vec_data_length > 0);
rqst_idx++;
if (rqst_idx < num_rqst)
goto next_rqst;
/* now sending pages if there are any */
for (i = 0; i < rqst->rq_npages; i++) {
rqst_page_get_length(rqst, i, &buflen, &offset);
nvecs = (buflen + max_iov_size - 1) / max_iov_size;
log_write(INFO, "sending pages buflen=%d nvecs=%d\n",
buflen, nvecs);
for (j = 0; j < nvecs; j++) {
size = min_t(unsigned int, max_iov_size, remaining_data_length);
remaining_data_length -= size;
log_write(INFO, "sending pages i=%d offset=%d size=%d remaining_data_length=%d\n",
i, j * max_iov_size + offset, size,
remaining_data_length);
rc = smbd_post_send_page(
info, rqst->rq_pages[i],
j*max_iov_size + offset,
size, remaining_data_length);
if (rc)
goto done;
}
}
} while (++rqst_idx < num_rqst);
done:
/*

View file

@ -91,7 +91,7 @@ struct smbd_connection {
/* Memory registrations */
/* Maximum number of RDMA read/write outstanding on this connection */
int responder_resources;
/* Maximum number of SGEs in a RDMA write/read */
/* Maximum number of pages in a single RDMA write/read on this connection */
int max_frmr_depth;
/*
* If payload is less than or equal to the threshold,
@ -225,21 +225,25 @@ struct smbd_buffer_descriptor_v1 {
__le32 length;
} __packed;
/* Default maximum number of SGEs in a RDMA send/recv */
#define SMBDIRECT_MAX_SGE 16
/* Maximum number of SGEs used by smbdirect.c in any send work request */
#define SMBDIRECT_MAX_SEND_SGE 6
/* The context for a SMBD request */
struct smbd_request {
struct smbd_connection *info;
struct ib_cqe cqe;
/* the SGE entries for this packet */
struct ib_sge sge[SMBDIRECT_MAX_SGE];
/* the SGE entries for this work request */
struct ib_sge sge[SMBDIRECT_MAX_SEND_SGE];
int num_sge;
/* SMBD packet header follows this structure */
u8 packet[];
};
/* Maximum number of SGEs used by smbdirect.c in any receive work request */
#define SMBDIRECT_MAX_RECV_SGE 1
/* The context for a SMBD response */
struct smbd_response {
struct smbd_connection *info;

View file

@ -372,6 +372,7 @@ DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter);
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter);
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(delete_enter);
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter);
DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(tdis_enter);
DECLARE_EVENT_CLASS(smb3_inf_compound_done_class,
@ -409,6 +410,7 @@ DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done);
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done);
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(delete_done);
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done);
DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(tdis_done);
DECLARE_EVENT_CLASS(smb3_inf_compound_err_class,
@ -451,6 +453,7 @@ DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err);
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err);
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err);
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(delete_err);
DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(tdis_err);
/*
* For logging SMB3 Status code and Command for responses which return errors

View file

@ -1101,7 +1101,11 @@ struct smb2_change_notify_rsp {
#define SMB2_CREATE_REQUEST_LEASE "RqLs"
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C"
#define SMB2_CREATE_TAG_POSIX "\x93\xAD\x25\x50\x9C\xB4\x11\xE7\xB4\x23\x83\xDE\x96\x8B\xCD\x7C"
#define SMB2_CREATE_TAG_POSIX "\x93\xAD\x25\x50\x9C\xB4\x11\xE7\xB4\x23\x83\xDE\x96\x8B\xCD\x7C"
#define SMB2_CREATE_APP_INSTANCE_ID "\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74"
#define SMB2_CREATE_APP_INSTANCE_VERSION "\xB9\x82\xD0\xB7\x3B\x56\x07\x4F\xA0\x7B\x52\x4A\x81\x16\xA0\x10"
#define SVHDX_OPEN_DEVICE_CONTEXT "\x9C\xCB\xCF\x9E\x04\xC1\xE6\x43\x98\x0E\x15\x8D\xA1\xF6\xEC\x83"
#define SMB2_CREATE_TAG_AAPL "AAPL"
/* Flag (SMB3 open response) values */
#define SMB2_CREATE_FLAG_REPARSEPOINT 0x01