Skip to content

Commit 4119bf9

Browse files
committed
Merge tag '5.7-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Ten cifs/smb fixes: - five RDMA (smbdirect) related fixes - add experimental support for swap over SMB3 mounts - also a fix which improves performance of signed connections" * tag '5.7-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6: smb3: enable swap on SMB3 mounts smb3: change noisy error message to FYI smb3: smbdirect support can be configured by default cifs: smbd: Do not schedule work to send immediate packet on every receive cifs: smbd: Properly process errors on ib_post_send cifs: Allocate crypto structures on the fly for calculating signatures of incoming packets cifs: smbd: Update receive credits before sending and deal with credits roll back on failure before sending cifs: smbd: Check send queue size before posting a send cifs: smbd: Merge code to track pending packets cifs: ignore cached share root handle closing errors
2 parents 50bda5f + 4e8aea3 commit 4119bf9

File tree

12 files changed

+272
-238
lines changed

12 files changed

+272
-238
lines changed

fs/cifs/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ config CIFS_SMB_DIRECT
202202
help
203203
Enables SMB Direct support for SMB 3.0, 3.02 and 3.1.1.
204204
SMB Direct allows transferring SMB packets over RDMA. If unsure,
205-
say N.
205+
say Y.
206206

207207
config CIFS_FSCACHE
208208
bool "Provide CIFS client caching support"

fs/cifs/cifs_debug.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
323323
atomic_read(&server->smbd_conn->send_credits),
324324
atomic_read(&server->smbd_conn->receive_credits),
325325
server->smbd_conn->receive_credit_target);
326-
seq_printf(m, "\nPending send_pending: %x "
327-
"send_payload_pending: %x",
328-
atomic_read(&server->smbd_conn->send_pending),
329-
atomic_read(&server->smbd_conn->send_payload_pending));
326+
seq_printf(m, "\nPending send_pending: %x ",
327+
atomic_read(&server->smbd_conn->send_pending));
330328
seq_printf(m, "\nReceive buffers count_receive_queue: %x "
331329
"count_empty_packet_queue: %x",
332330
server->smbd_conn->count_receive_queue,

fs/cifs/cifsfs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,10 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
12081208
{
12091209
unsigned int xid = get_xid();
12101210
ssize_t rc;
1211+
struct cifsFileInfo *cfile = dst_file->private_data;
1212+
1213+
if (cfile->swapfile)
1214+
return -EOPNOTSUPP;
12111215

12121216
rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
12131217
len, flags);

fs/cifs/cifsglob.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,8 @@ struct smb_version_operations {
426426
/* generate new lease key */
427427
void (*new_lease_key)(struct cifs_fid *);
428428
int (*generate_signingkey)(struct cifs_ses *);
429-
int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
429+
int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *,
430+
bool allocate_crypto);
430431
int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
431432
struct cifsFileInfo *src_file);
432433
int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon,
@@ -1312,6 +1313,7 @@ struct cifsFileInfo {
13121313
struct tcon_link *tlink;
13131314
unsigned int f_flags;
13141315
bool invalidHandle:1; /* file closed via session abend */
1316+
bool swapfile:1;
13151317
bool oplock_break_cancelled:1;
13161318
unsigned int oplock_epoch; /* epoch from the lease break */
13171319
__u32 oplock_level; /* oplock/lease level from the lease break */

fs/cifs/file.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4808,6 +4808,60 @@ cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter)
48084808
return -EINVAL;
48094809
}
48104810

4811+
static int cifs_swap_activate(struct swap_info_struct *sis,
4812+
struct file *swap_file, sector_t *span)
4813+
{
4814+
struct cifsFileInfo *cfile = swap_file->private_data;
4815+
struct inode *inode = swap_file->f_mapping->host;
4816+
unsigned long blocks;
4817+
long long isize;
4818+
4819+
cifs_dbg(FYI, "swap activate\n");
4820+
4821+
spin_lock(&inode->i_lock);
4822+
blocks = inode->i_blocks;
4823+
isize = inode->i_size;
4824+
spin_unlock(&inode->i_lock);
4825+
if (blocks*512 < isize) {
4826+
pr_warn("swap activate: swapfile has holes\n");
4827+
return -EINVAL;
4828+
}
4829+
*span = sis->pages;
4830+
4831+
printk_once(KERN_WARNING "Swap support over SMB3 is experimental\n");
4832+
4833+
/*
4834+
* TODO: consider adding ACL (or documenting how) to prevent other
4835+
* users (on this or other systems) from reading it
4836+
*/
4837+
4838+
4839+
/* TODO: add sk_set_memalloc(inet) or similar */
4840+
4841+
if (cfile)
4842+
cfile->swapfile = true;
4843+
/*
4844+
* TODO: Since file already open, we can't open with DENY_ALL here
4845+
* but we could add call to grab a byte range lock to prevent others
4846+
* from reading or writing the file
4847+
*/
4848+
4849+
return 0;
4850+
}
4851+
4852+
static void cifs_swap_deactivate(struct file *file)
4853+
{
4854+
struct cifsFileInfo *cfile = file->private_data;
4855+
4856+
cifs_dbg(FYI, "swap deactivate\n");
4857+
4858+
/* TODO: undo sk_set_memalloc(inet) will eventually be needed */
4859+
4860+
if (cfile)
4861+
cfile->swapfile = false;
4862+
4863+
/* do we need to unpin (or unlock) the file */
4864+
}
48114865

48124866
const struct address_space_operations cifs_addr_ops = {
48134867
.readpage = cifs_readpage,
@@ -4821,6 +4875,13 @@ const struct address_space_operations cifs_addr_ops = {
48214875
.direct_IO = cifs_direct_io,
48224876
.invalidatepage = cifs_invalidate_page,
48234877
.launder_page = cifs_launder_page,
4878+
/*
4879+
* TODO: investigate and if useful we could add an cifs_migratePage
4880+
* helper (under an CONFIG_MIGRATION) in the future, and also
4881+
* investigate and add an is_dirty_writeback helper if needed
4882+
*/
4883+
.swap_activate = cifs_swap_activate,
4884+
.swap_deactivate = cifs_swap_deactivate,
48244885
};
48254886

48264887
/*

fs/cifs/inode.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,6 +2026,10 @@ cifs_revalidate_mapping(struct inode *inode)
20262026
int rc;
20272027
unsigned long *flags = &CIFS_I(inode)->flags;
20282028

2029+
/* swapfiles are not supposed to be shared */
2030+
if (IS_SWAPFILE(inode))
2031+
return 0;
2032+
20292033
rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
20302034
TASK_KILLABLE);
20312035
if (rc)

fs/cifs/readdir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
246246
*/
247247
fattr->cf_mode = le32_to_cpu(info->Mode) & ~S_IFMT;
248248

249-
cifs_dbg(VFS, "XXX dev %d, reparse %d, mode %o",
249+
cifs_dbg(FYI, "posix fattr: dev %d, reparse %d, mode %o",
250250
le32_to_cpu(info->DeviceId),
251251
le32_to_cpu(info->ReparseTag),
252252
le32_to_cpu(info->Mode));

fs/cifs/smb2misc.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,20 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid,
766766

767767
cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count);
768768
spin_lock(&cifs_tcp_ses_lock);
769+
if (tcon->tc_count <= 0) {
770+
struct TCP_Server_Info *server = NULL;
771+
772+
WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative");
773+
spin_unlock(&cifs_tcp_ses_lock);
774+
775+
if (tcon->ses)
776+
server = tcon->ses->server;
777+
778+
cifs_server_dbg(FYI, "tid=%u: tcon is closing, skipping async close retry of fid %llu %llu\n",
779+
tcon->tid, persistent_fid, volatile_fid);
780+
781+
return 0;
782+
}
769783
tcon->tc_count++;
770784
spin_unlock(&cifs_tcp_ses_lock);
771785

fs/cifs/smb2proto.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
5555
extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
5656
__u64 ses_id, __u32 tid);
5757
extern int smb2_calc_signature(struct smb_rqst *rqst,
58-
struct TCP_Server_Info *server);
58+
struct TCP_Server_Info *server,
59+
bool allocate_crypto);
5960
extern int smb3_calc_signature(struct smb_rqst *rqst,
60-
struct TCP_Server_Info *server);
61+
struct TCP_Server_Info *server,
62+
bool allocate_crypto);
6163
extern void smb2_echo_request(struct work_struct *work);
6264
extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode);
6365
extern bool smb2_is_valid_oplock_break(char *buffer,

fs/cifs/smb2transport.c

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,6 @@
4040
#include "smb2status.h"
4141
#include "smb2glob.h"
4242

43-
static int
44-
smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
45-
{
46-
return cifs_alloc_hash("hmac(sha256)",
47-
&server->secmech.hmacsha256,
48-
&server->secmech.sdeschmacsha256);
49-
}
50-
5143
static int
5244
smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
5345
{
@@ -219,7 +211,8 @@ smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
219211
}
220212

221213
int
222-
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
214+
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
215+
bool allocate_crypto)
223216
{
224217
int rc;
225218
unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
@@ -228,6 +221,8 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
228221
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
229222
struct cifs_ses *ses;
230223
struct shash_desc *shash;
224+
struct crypto_shash *hash;
225+
struct sdesc *sdesc = NULL;
231226
struct smb_rqst drqst;
232227

233228
ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -239,24 +234,32 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
239234
memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
240235
memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
241236

242-
rc = smb2_crypto_shash_allocate(server);
243-
if (rc) {
244-
cifs_server_dbg(VFS, "%s: sha256 alloc failed\n", __func__);
245-
return rc;
237+
if (allocate_crypto) {
238+
rc = cifs_alloc_hash("hmac(sha256)", &hash, &sdesc);
239+
if (rc) {
240+
cifs_server_dbg(VFS,
241+
"%s: sha256 alloc failed\n", __func__);
242+
return rc;
243+
}
244+
shash = &sdesc->shash;
245+
} else {
246+
hash = server->secmech.hmacsha256;
247+
shash = &server->secmech.sdeschmacsha256->shash;
246248
}
247249

248-
rc = crypto_shash_setkey(server->secmech.hmacsha256,
249-
ses->auth_key.response, SMB2_NTLMV2_SESSKEY_SIZE);
250+
rc = crypto_shash_setkey(hash, ses->auth_key.response,
251+
SMB2_NTLMV2_SESSKEY_SIZE);
250252
if (rc) {
251-
cifs_server_dbg(VFS, "%s: Could not update with response\n", __func__);
252-
return rc;
253+
cifs_server_dbg(VFS,
254+
"%s: Could not update with response\n",
255+
__func__);
256+
goto out;
253257
}
254258

255-
shash = &server->secmech.sdeschmacsha256->shash;
256259
rc = crypto_shash_init(shash);
257260
if (rc) {
258261
cifs_server_dbg(VFS, "%s: Could not init sha256", __func__);
259-
return rc;
262+
goto out;
260263
}
261264

262265
/*
@@ -271,9 +274,10 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
271274
rc = crypto_shash_update(shash, iov[0].iov_base,
272275
iov[0].iov_len);
273276
if (rc) {
274-
cifs_server_dbg(VFS, "%s: Could not update with payload\n",
275-
__func__);
276-
return rc;
277+
cifs_server_dbg(VFS,
278+
"%s: Could not update with payload\n",
279+
__func__);
280+
goto out;
277281
}
278282
drqst.rq_iov++;
279283
drqst.rq_nvec--;
@@ -283,6 +287,9 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
283287
if (!rc)
284288
memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
285289

290+
out:
291+
if (allocate_crypto)
292+
cifs_free_hash(&hash, &sdesc);
286293
return rc;
287294
}
288295

@@ -504,29 +511,42 @@ generate_smb311signingkey(struct cifs_ses *ses)
504511
}
505512

506513
int
507-
smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
514+
smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
515+
bool allocate_crypto)
508516
{
509517
int rc;
510518
unsigned char smb3_signature[SMB2_CMACAES_SIZE];
511519
unsigned char *sigptr = smb3_signature;
512520
struct kvec *iov = rqst->rq_iov;
513521
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
514-
struct shash_desc *shash = &server->secmech.sdesccmacaes->shash;
522+
struct shash_desc *shash;
523+
struct crypto_shash *hash;
524+
struct sdesc *sdesc = NULL;
515525
struct smb_rqst drqst;
516526
u8 key[SMB3_SIGN_KEY_SIZE];
517527

518528
rc = smb2_get_sign_key(shdr->SessionId, server, key);
519529
if (rc)
520530
return 0;
521531

532+
if (allocate_crypto) {
533+
rc = cifs_alloc_hash("cmac(aes)", &hash, &sdesc);
534+
if (rc)
535+
return rc;
536+
537+
shash = &sdesc->shash;
538+
} else {
539+
hash = server->secmech.cmacaes;
540+
shash = &server->secmech.sdesccmacaes->shash;
541+
}
542+
522543
memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
523544
memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
524545

525-
rc = crypto_shash_setkey(server->secmech.cmacaes,
526-
key, SMB2_CMACAES_SIZE);
546+
rc = crypto_shash_setkey(hash, key, SMB2_CMACAES_SIZE);
527547
if (rc) {
528548
cifs_server_dbg(VFS, "%s: Could not set key for cmac aes\n", __func__);
529-
return rc;
549+
goto out;
530550
}
531551

532552
/*
@@ -537,7 +557,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
537557
rc = crypto_shash_init(shash);
538558
if (rc) {
539559
cifs_server_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
540-
return rc;
560+
goto out;
541561
}
542562

543563
/*
@@ -554,7 +574,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
554574
if (rc) {
555575
cifs_server_dbg(VFS, "%s: Could not update with payload\n",
556576
__func__);
557-
return rc;
577+
goto out;
558578
}
559579
drqst.rq_iov++;
560580
drqst.rq_nvec--;
@@ -564,6 +584,9 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
564584
if (!rc)
565585
memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
566586

587+
out:
588+
if (allocate_crypto)
589+
cifs_free_hash(&hash, &sdesc);
567590
return rc;
568591
}
569592

@@ -593,7 +616,7 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
593616
return 0;
594617
}
595618

596-
rc = server->ops->calc_signature(rqst, server);
619+
rc = server->ops->calc_signature(rqst, server, false);
597620

598621
return rc;
599622
}
@@ -631,9 +654,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
631654

632655
memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
633656

634-
mutex_lock(&server->srv_mutex);
635-
rc = server->ops->calc_signature(rqst, server);
636-
mutex_unlock(&server->srv_mutex);
657+
rc = server->ops->calc_signature(rqst, server, true);
637658

638659
if (rc)
639660
return rc;

0 commit comments

Comments
 (0)