Skip to content

Commit e0c505c

Browse files
committed
Merge tag 'v7.0-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client fixes from Steve French: - Fix potential oops on open failure - Fix unmount to better free deferred closes - Use proper constant-time MAC comparison function - Two buffer allocation size fixes - Two minor cleanups - make SMB2 kunit tests a distinct module * tag 'v7.0-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: smb: client: fix oops due to uninitialised var in smb2_unlink() cifs: open files should not hold ref on superblock smb: client: Compare MACs in constant time smb/client: remove unused SMB311_posix_query_info() smb/client: fix buffer size for smb311_posix_qinfo in SMB311_posix_query_info() smb/client: fix buffer size for smb311_posix_qinfo in smb2_compound_op() smb: update some doc references smb/client: make SMB2 maperror KUnit tests a separate module
2 parents 325a118 + 048efe1 commit e0c505c

16 files changed

Lines changed: 107 additions & 58 deletions

fs/smb/client/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,6 @@ $(obj)/smb2maperror.o: $(obj)/smb2_mapping_table.c
5656
quiet_cmd_gen_smb2_mapping = GEN $@
5757
cmd_gen_smb2_mapping = perl $(src)/gen_smb2_mapping $< $@
5858

59+
obj-$(CONFIG_SMB_KUNIT_TESTS) += smb2maperror_test.o
60+
5961
clean-files += smb2_mapping_table.c

fs/smb/client/cifsfs.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,14 @@ static void cifs_kill_sb(struct super_block *sb)
332332

333333
/*
334334
* We need to release all dentries for the cached directories
335-
* before we kill the sb.
335+
* and close all deferred file handles before we kill the sb.
336336
*/
337337
if (cifs_sb->root) {
338338
close_all_cached_dirs(cifs_sb);
339+
cifs_close_all_deferred_files_sb(cifs_sb);
340+
341+
/* Wait for all pending oplock breaks to complete */
342+
flush_workqueue(cifsoplockd_wq);
339343

340344
/* finally release root dentry */
341345
dput(cifs_sb->root);
@@ -868,7 +872,6 @@ static void cifs_umount_begin(struct super_block *sb)
868872
spin_unlock(&tcon->tc_lock);
869873
spin_unlock(&cifs_tcp_ses_lock);
870874

871-
cifs_close_all_deferred_files(tcon);
872875
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
873876
/* cancel_notify_requests(tcon); */
874877
if (tcon->ses && tcon->ses->server) {

fs/smb/client/cifsproto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
261261

262262
void cifs_close_all_deferred_files(struct cifs_tcon *tcon);
263263

264+
void cifs_close_all_deferred_files_sb(struct cifs_sb_info *cifs_sb);
264265
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
265266
struct dentry *dentry);
266267

fs/smb/client/file.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
711711
mutex_init(&cfile->fh_mutex);
712712
spin_lock_init(&cfile->file_info_lock);
713713

714-
cifs_sb_active(inode->i_sb);
715-
716714
/*
717715
* If the server returned a read oplock and we have mandatory brlocks,
718716
* set oplock level to None.
@@ -767,7 +765,6 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
767765
struct inode *inode = d_inode(cifs_file->dentry);
768766
struct cifsInodeInfo *cifsi = CIFS_I(inode);
769767
struct cifsLockInfo *li, *tmp;
770-
struct super_block *sb = inode->i_sb;
771768

772769
/*
773770
* Delete any outstanding lock records. We'll lose them when the file
@@ -785,7 +782,6 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
785782

786783
cifs_put_tlink(cifs_file->tlink);
787784
dput(cifs_file->dentry);
788-
cifs_sb_deactive(sb);
789785
kfree(cifs_file->symlink_target);
790786
kfree(cifs_file);
791787
}
@@ -3163,12 +3159,6 @@ void cifs_oplock_break(struct work_struct *work)
31633159
__u64 persistent_fid, volatile_fid;
31643160
__u16 net_fid;
31653161

3166-
/*
3167-
* Hold a reference to the superblock to prevent it and its inodes from
3168-
* being freed while we are accessing cinode. Otherwise, _cifsFileInfo_put()
3169-
* may release the last reference to the sb and trigger inode eviction.
3170-
*/
3171-
cifs_sb_active(sb);
31723162
wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
31733163
TASK_UNINTERRUPTIBLE);
31743164

@@ -3253,7 +3243,6 @@ void cifs_oplock_break(struct work_struct *work)
32533243
cifs_put_tlink(tlink);
32543244
out:
32553245
cifs_done_oplock_break(cinode);
3256-
cifs_sb_deactive(sb);
32573246
}
32583247

32593248
static int cifs_swap_activate(struct swap_info_struct *sis,

fs/smb/client/misc.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
#include "fs_context.h"
2929
#include "cached_dir.h"
3030

31+
struct tcon_list {
32+
struct list_head entry;
33+
struct cifs_tcon *tcon;
34+
};
35+
3136
/* The xid serves as a useful identifier for each incoming vfs request,
3237
in a similar way to the mid which is useful to track each sent smb,
3338
and CurrentXid can also provide a running counter (although it
@@ -554,6 +559,43 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
554559
}
555560
}
556561

562+
void cifs_close_all_deferred_files_sb(struct cifs_sb_info *cifs_sb)
563+
{
564+
struct rb_root *root = &cifs_sb->tlink_tree;
565+
struct rb_node *node;
566+
struct cifs_tcon *tcon;
567+
struct tcon_link *tlink;
568+
struct tcon_list *tmp_list, *q;
569+
LIST_HEAD(tcon_head);
570+
571+
spin_lock(&cifs_sb->tlink_tree_lock);
572+
for (node = rb_first(root); node; node = rb_next(node)) {
573+
tlink = rb_entry(node, struct tcon_link, tl_rbnode);
574+
tcon = tlink_tcon(tlink);
575+
if (IS_ERR(tcon))
576+
continue;
577+
tmp_list = kmalloc_obj(struct tcon_list, GFP_ATOMIC);
578+
if (tmp_list == NULL)
579+
break;
580+
tmp_list->tcon = tcon;
581+
/* Take a reference on tcon to prevent it from being freed */
582+
spin_lock(&tcon->tc_lock);
583+
++tcon->tc_count;
584+
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
585+
netfs_trace_tcon_ref_get_close_defer_files);
586+
spin_unlock(&tcon->tc_lock);
587+
list_add_tail(&tmp_list->entry, &tcon_head);
588+
}
589+
spin_unlock(&cifs_sb->tlink_tree_lock);
590+
591+
list_for_each_entry_safe(tmp_list, q, &tcon_head, entry) {
592+
cifs_close_all_deferred_files(tmp_list->tcon);
593+
list_del(&tmp_list->entry);
594+
cifs_put_tcon(tmp_list->tcon, netfs_trace_tcon_ref_put_close_defer_files);
595+
kfree(tmp_list);
596+
}
597+
}
598+
557599
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
558600
struct dentry *dentry)
559601
{

fs/smb/client/smb1encrypt.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <linux/fips.h>
1313
#include <crypto/md5.h>
14+
#include <crypto/utils.h>
1415
#include "cifsproto.h"
1516
#include "smb1proto.h"
1617
#include "cifs_debug.h"
@@ -131,7 +132,7 @@ int cifs_verify_signature(struct smb_rqst *rqst,
131132
/* cifs_dump_mem("what we think it should be: ",
132133
what_we_think_sig_should_be, 16); */
133134

134-
if (memcmp(server_response_sig, what_we_think_sig_should_be, 8))
135+
if (crypto_memneq(server_response_sig, what_we_think_sig_should_be, 8))
135136
return -EACCES;
136137
else
137138
return 0;

fs/smb/client/smb2glob.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,16 @@ enum smb2_compound_ops {
4646
#define END_OF_CHAIN 4
4747
#define RELATED_REQUEST 8
4848

49+
/*
50+
*****************************************************************
51+
* Struct definitions go here
52+
*****************************************************************
53+
*/
54+
55+
struct status_to_posix_error {
56+
__u32 smb2_status;
57+
int posix_error;
58+
char *status_string;
59+
};
60+
4961
#endif /* _SMB2_GLOB_H */

fs/smb/client/smb2inode.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
325325
cfile->fid.volatile_fid,
326326
SMB_FIND_FILE_POSIX_INFO,
327327
SMB2_O_INFO_FILE, 0,
328-
sizeof(struct smb311_posix_qinfo *) +
328+
sizeof(struct smb311_posix_qinfo) +
329329
(PATH_MAX * 2) +
330330
(sizeof(struct smb_sid) * 2), 0, NULL);
331331
} else {
@@ -335,7 +335,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
335335
COMPOUND_FID,
336336
SMB_FIND_FILE_POSIX_INFO,
337337
SMB2_O_INFO_FILE, 0,
338-
sizeof(struct smb311_posix_qinfo *) +
338+
sizeof(struct smb311_posix_qinfo) +
339339
(PATH_MAX * 2) +
340340
(sizeof(struct smb_sid) * 2), 0, NULL);
341341
}
@@ -1216,6 +1216,7 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
12161216
memset(resp_buftype, 0, sizeof(resp_buftype));
12171217
memset(rsp_iov, 0, sizeof(rsp_iov));
12181218

1219+
memset(open_iov, 0, sizeof(open_iov));
12191220
rqst[0].rq_iov = open_iov;
12201221
rqst[0].rq_nvec = ARRAY_SIZE(open_iov);
12211222

@@ -1240,14 +1241,15 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
12401241
creq = rqst[0].rq_iov[0].iov_base;
12411242
creq->ShareAccess = FILE_SHARE_DELETE_LE;
12421243

1244+
memset(&close_iov, 0, sizeof(close_iov));
12431245
rqst[1].rq_iov = &close_iov;
12441246
rqst[1].rq_nvec = 1;
12451247

12461248
rc = SMB2_close_init(tcon, server, &rqst[1],
12471249
COMPOUND_FID, COMPOUND_FID, false);
1248-
smb2_set_related(&rqst[1]);
12491250
if (rc)
12501251
goto err_free;
1252+
smb2_set_related(&rqst[1]);
12511253

12521254
if (retries) {
12531255
/* Back-off before retry */

fs/smb/client/smb2maperror.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,13 @@
88
*
99
*/
1010
#include <linux/errno.h>
11-
#include "cifsglob.h"
1211
#include "cifsproto.h"
1312
#include "cifs_debug.h"
1413
#include "smb2proto.h"
1514
#include "smb2glob.h"
1615
#include "../common/smb2status.h"
1716
#include "trace.h"
1817

19-
struct status_to_posix_error {
20-
__u32 smb2_status;
21-
int posix_error;
22-
char *status_string;
23-
};
24-
2518
static const struct status_to_posix_error smb2_error_map_table[] = {
2619
/*
2720
* Automatically generated by the `gen_smb2_mapping` script,
@@ -115,10 +108,19 @@ int __init smb2_init_maperror(void)
115108
return 0;
116109
}
117110

118-
#define SMB_CLIENT_KUNIT_AVAILABLE \
119-
((IS_MODULE(CONFIG_CIFS) && IS_ENABLED(CONFIG_KUNIT)) || \
120-
(IS_BUILTIN(CONFIG_CIFS) && IS_BUILTIN(CONFIG_KUNIT)))
111+
#if IS_ENABLED(CONFIG_SMB_KUNIT_TESTS)
112+
/* Previous prototype for eliminating the build warning. */
113+
const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status);
114+
115+
const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status)
116+
{
117+
return smb2_get_err_map(smb2_status);
118+
}
119+
EXPORT_SYMBOL_GPL(smb2_get_err_map_test);
120+
121+
const struct status_to_posix_error *smb2_error_map_table_test = smb2_error_map_table;
122+
EXPORT_SYMBOL_GPL(smb2_error_map_table_test);
121123

122-
#if SMB_CLIENT_KUNIT_AVAILABLE && IS_ENABLED(CONFIG_SMB_KUNIT_TESTS)
123-
#include "smb2maperror_test.c"
124-
#endif /* CONFIG_SMB_KUNIT_TESTS */
124+
unsigned int smb2_error_map_num = ARRAY_SIZE(smb2_error_map_table);
125+
EXPORT_SYMBOL_GPL(smb2_error_map_num);
126+
#endif

fs/smb/client/smb2maperror_test.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@
99
*/
1010

1111
#include <kunit/test.h>
12+
#include "smb2glob.h"
13+
14+
const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status);
15+
extern const struct status_to_posix_error *smb2_error_map_table_test;
16+
extern unsigned int smb2_error_map_num;
1217

1318
static void
1419
test_cmp_map(struct kunit *test, const struct status_to_posix_error *expect)
1520
{
1621
const struct status_to_posix_error *result;
1722

18-
result = smb2_get_err_map(expect->smb2_status);
23+
result = smb2_get_err_map_test(expect->smb2_status);
1924
KUNIT_EXPECT_PTR_NE(test, NULL, result);
2025
KUNIT_EXPECT_EQ(test, expect->smb2_status, result->smb2_status);
2126
KUNIT_EXPECT_EQ(test, expect->posix_error, result->posix_error);
@@ -26,8 +31,8 @@ static void maperror_test_check_search(struct kunit *test)
2631
{
2732
unsigned int i;
2833

29-
for (i = 0; i < ARRAY_SIZE(smb2_error_map_table); i++)
30-
test_cmp_map(test, &smb2_error_map_table[i]);
34+
for (i = 0; i < smb2_error_map_num; i++)
35+
test_cmp_map(test, &smb2_error_map_table_test[i]);
3136
}
3237

3338
static struct kunit_case maperror_test_cases[] = {
@@ -43,3 +48,4 @@ static struct kunit_suite maperror_suite = {
4348
kunit_test_suite(maperror_suite);
4449

4550
MODULE_LICENSE("GPL");
51+
MODULE_DESCRIPTION("KUnit tests of SMB2 maperror");

0 commit comments

Comments
 (0)