Skip to content

Commit 0c14e43

Browse files
committed
Merge tag '4.18-fixes-smb3' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: - one smb3 (ACL related) fix for stable - one SMB3 security enhancement (when mounting -t smb3 forbid less secure dialects) - some RDMA and compounding fixes * tag '4.18-fixes-smb3' of git://git.samba.org/sfrench/cifs-2.6: cifs: fix a buffer leak in smb2_query_symlink smb3: do not allow insecure cifs mounts when using smb3 CIFS: Fix NULL ptr deref CIFS: fix encryption in SMB3.1.1 CIFS: Pass page offset for encrypting CIFS: Pass page offset for calculating signature CIFS: SMBD: Support page offset in memory registration CIFS: SMBD: Support page offset in RDMA recv CIFS: SMBD: Support page offset in RDMA send CIFS: When sending data on socket, pass the correct page offset CIFS: Introduce helper function to get page offset and length in smb_rqst CIFS: Calculate the correct request length based on page offset and tail size cifs: For SMB2 security informaion query, check for minimum sized security descriptor instead of sizeof FileAllInformation class CIFS: Fix signing for SMB2/3
2 parents bbaa101 + 9d874c3 commit 0c14e43

18 files changed

+261
-138
lines changed

fs/cifs/cifsacl.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,18 @@ struct cifs_ace {
9898
struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
9999
} __attribute__((packed));
100100

101+
/*
102+
* Minimum security identifier can be one for system defined Users
103+
* and Groups such as NULL SID and World or Built-in accounts such
104+
* as Administrator and Guest and consists of
105+
* Revision + Num (Sub)Auths + Authority + Domain (one Subauthority)
106+
*/
107+
#define MIN_SID_LEN (1 + 1 + 6 + 4) /* in bytes */
108+
109+
/*
110+
* Minimum security descriptor can be one without any SACL and DACL and can
111+
* consist of revision, type, and two sids of minimum size for owner and group
112+
*/
113+
#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN))
114+
101115
#endif /* _CIFSACL_H */

fs/cifs/cifsencrypt.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <crypto/aead.h>
3838

3939
int __cifs_calc_signature(struct smb_rqst *rqst,
40+
int start,
4041
struct TCP_Server_Info *server, char *signature,
4142
struct shash_desc *shash)
4243
{
@@ -45,10 +46,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
4546
struct kvec *iov = rqst->rq_iov;
4647
int n_vec = rqst->rq_nvec;
4748

48-
if (n_vec < 2 || iov[0].iov_len != 4)
49-
return -EIO;
50-
51-
for (i = 1; i < n_vec; i++) {
49+
for (i = start; i < n_vec; i++) {
5250
if (iov[i].iov_len == 0)
5351
continue;
5452
if (iov[i].iov_base == NULL) {
@@ -68,11 +66,12 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
6866

6967
/* now hash over the rq_pages array */
7068
for (i = 0; i < rqst->rq_npages; i++) {
71-
void *kaddr = kmap(rqst->rq_pages[i]);
72-
size_t len = rqst->rq_pagesz;
69+
void *kaddr;
70+
unsigned int len, offset;
71+
72+
rqst_page_get_length(rqst, i, &len, &offset);
7373

74-
if (i == rqst->rq_npages - 1)
75-
len = rqst->rq_tailsz;
74+
kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
7675

7776
crypto_shash_update(shash, kaddr, len);
7877

@@ -119,7 +118,7 @@ static int cifs_calc_signature(struct smb_rqst *rqst,
119118
return rc;
120119
}
121120

122-
return __cifs_calc_signature(rqst, server, signature,
121+
return __cifs_calc_signature(rqst, 1, server, signature,
123122
&server->secmech.sdescmd5->shash);
124123
}
125124

fs/cifs/cifsfs.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -698,8 +698,8 @@ static int cifs_set_super(struct super_block *sb, void *data)
698698
}
699699

700700
static struct dentry *
701-
cifs_do_mount(struct file_system_type *fs_type,
702-
int flags, const char *dev_name, void *data)
701+
cifs_smb3_do_mount(struct file_system_type *fs_type,
702+
int flags, const char *dev_name, void *data, bool is_smb3)
703703
{
704704
int rc;
705705
struct super_block *sb;
@@ -710,7 +710,7 @@ cifs_do_mount(struct file_system_type *fs_type,
710710

711711
cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags);
712712

713-
volume_info = cifs_get_volume_info((char *)data, dev_name);
713+
volume_info = cifs_get_volume_info((char *)data, dev_name, is_smb3);
714714
if (IS_ERR(volume_info))
715715
return ERR_CAST(volume_info);
716716

@@ -790,6 +790,20 @@ cifs_do_mount(struct file_system_type *fs_type,
790790
goto out;
791791
}
792792

793+
static struct dentry *
794+
smb3_do_mount(struct file_system_type *fs_type,
795+
int flags, const char *dev_name, void *data)
796+
{
797+
return cifs_smb3_do_mount(fs_type, flags, dev_name, data, true);
798+
}
799+
800+
static struct dentry *
801+
cifs_do_mount(struct file_system_type *fs_type,
802+
int flags, const char *dev_name, void *data)
803+
{
804+
return cifs_smb3_do_mount(fs_type, flags, dev_name, data, false);
805+
}
806+
793807
static ssize_t
794808
cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
795809
{
@@ -925,7 +939,7 @@ MODULE_ALIAS_FS("cifs");
925939
static struct file_system_type smb3_fs_type = {
926940
.owner = THIS_MODULE,
927941
.name = "smb3",
928-
.mount = cifs_do_mount,
942+
.mount = smb3_do_mount,
929943
.kill_sb = cifs_kill_sb,
930944
/* .fs_flags */
931945
};

fs/cifs/cifsglob.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,12 @@ tlink_tcon(struct tcon_link *tlink)
10191019
return tlink->tl_tcon;
10201020
}
10211021

1022+
static inline struct tcon_link *
1023+
cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
1024+
{
1025+
return cifs_sb->master_tlink;
1026+
}
1027+
10221028
extern void cifs_put_tlink(struct tcon_link *tlink);
10231029

10241030
static inline struct tcon_link *

fs/cifs/cifsproto.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
211211
extern int cifs_match_super(struct super_block *, void *);
212212
extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info);
213213
extern struct smb_vol *cifs_get_volume_info(char *mount_data,
214-
const char *devname);
214+
const char *devname, bool is_smb3);
215215
extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
216216
extern void cifs_umount(struct cifs_sb_info *);
217217
extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
@@ -544,7 +544,7 @@ int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
544544
struct cifs_sb_info *cifs_sb,
545545
const unsigned char *path, char *pbuf,
546546
unsigned int *pbytes_written);
547-
int __cifs_calc_signature(struct smb_rqst *rqst,
547+
int __cifs_calc_signature(struct smb_rqst *rqst, int start,
548548
struct TCP_Server_Info *server, char *signature,
549549
struct shash_desc *shash);
550550
enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
@@ -557,4 +557,7 @@ int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
557557
struct sdesc **sdesc);
558558
void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
559559

560+
extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
561+
unsigned int *len, unsigned int *offset);
562+
560563
#endif /* _CIFSPROTO_H */

fs/cifs/connect.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ static int generic_ip_connect(struct TCP_Server_Info *server);
320320
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
321321
static void cifs_prune_tlinks(struct work_struct *work);
322322
static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
323-
const char *devname);
323+
const char *devname, bool is_smb3);
324324

325325
/*
326326
* cifs tcp session reconnection
@@ -1166,7 +1166,7 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
11661166
}
11671167

11681168
static int
1169-
cifs_parse_smb_version(char *value, struct smb_vol *vol)
1169+
cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
11701170
{
11711171
substring_t args[MAX_OPT_ARGS];
11721172

@@ -1176,6 +1176,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
11761176
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
11771177
return 1;
11781178
}
1179+
if (is_smb3) {
1180+
cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
1181+
return 1;
1182+
}
11791183
vol->ops = &smb1_operations;
11801184
vol->vals = &smb1_values;
11811185
break;
@@ -1184,6 +1188,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
11841188
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
11851189
return 1;
11861190
}
1191+
if (is_smb3) {
1192+
cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
1193+
return 1;
1194+
}
11871195
vol->ops = &smb20_operations;
11881196
vol->vals = &smb20_values;
11891197
break;
@@ -1272,7 +1280,7 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol)
12721280

12731281
static int
12741282
cifs_parse_mount_options(const char *mountdata, const char *devname,
1275-
struct smb_vol *vol)
1283+
struct smb_vol *vol, bool is_smb3)
12761284
{
12771285
char *data, *end;
12781286
char *mountdata_copy = NULL, *options;
@@ -1985,7 +1993,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
19851993
if (string == NULL)
19861994
goto out_nomem;
19871995

1988-
if (cifs_parse_smb_version(string, vol) != 0)
1996+
if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
19891997
goto cifs_parse_mount_err;
19901998
got_version = true;
19911999
break;
@@ -3116,12 +3124,6 @@ cifs_put_tlink(struct tcon_link *tlink)
31163124
return;
31173125
}
31183126

3119-
static inline struct tcon_link *
3120-
cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
3121-
{
3122-
return cifs_sb->master_tlink;
3123-
}
3124-
31253127
static int
31263128
compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
31273129
{
@@ -3803,7 +3805,7 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
38033805
} else {
38043806
cleanup_volume_info_contents(volume_info);
38053807
rc = cifs_setup_volume_info(volume_info, mdata,
3806-
fake_devname);
3808+
fake_devname, false);
38073809
}
38083810
kfree(fake_devname);
38093811
kfree(cifs_sb->mountdata);
@@ -3816,11 +3818,11 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
38163818

38173819
static int
38183820
cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
3819-
const char *devname)
3821+
const char *devname, bool is_smb3)
38203822
{
38213823
int rc = 0;
38223824

3823-
if (cifs_parse_mount_options(mount_data, devname, volume_info))
3825+
if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
38243826
return -EINVAL;
38253827

38263828
if (volume_info->nullauth) {
@@ -3854,7 +3856,7 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
38543856
}
38553857

38563858
struct smb_vol *
3857-
cifs_get_volume_info(char *mount_data, const char *devname)
3859+
cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
38583860
{
38593861
int rc;
38603862
struct smb_vol *volume_info;
@@ -3863,7 +3865,7 @@ cifs_get_volume_info(char *mount_data, const char *devname)
38633865
if (!volume_info)
38643866
return ERR_PTR(-ENOMEM);
38653867

3866-
rc = cifs_setup_volume_info(volume_info, mount_data, devname);
3868+
rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
38673869
if (rc) {
38683870
cifs_cleanup_volume_info(volume_info);
38693871
volume_info = ERR_PTR(rc);

fs/cifs/link.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,8 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
421421
return -ENOMEM;
422422
}
423423

424-
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL);
424+
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
425+
NULL);
425426
if (rc)
426427
goto qmf_out_open_fail;
427428

@@ -478,7 +479,8 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
478479
oparms.fid = &fid;
479480
oparms.reconnect = false;
480481

481-
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
482+
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
483+
NULL);
482484
if (rc) {
483485
kfree(utf16_path);
484486
return rc;

fs/cifs/misc.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,3 +905,20 @@ cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
905905
crypto_free_shash(*shash);
906906
*shash = NULL;
907907
}
908+
909+
/**
910+
* rqst_page_get_length - obtain the length and offset for a page in smb_rqst
911+
* Input: rqst - a smb_rqst, page - a page index for rqst
912+
* Output: *len - the length for this page, *offset - the offset for this page
913+
*/
914+
void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
915+
unsigned int *len, unsigned int *offset)
916+
{
917+
*len = rqst->rq_pagesz;
918+
*offset = (page == 0) ? rqst->rq_offset : 0;
919+
920+
if (rqst->rq_npages == 1 || page == rqst->rq_npages-1)
921+
*len = rqst->rq_tailsz;
922+
else if (page == 0)
923+
*len = rqst->rq_pagesz - rqst->rq_offset;
924+
}

fs/cifs/smb2file.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
6464
if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
6565
memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
6666

67-
rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL);
67+
rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL,
68+
NULL);
6869
if (rc)
6970
goto out;
7071

fs/cifs/smb2inode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
7171
oparms.fid = &fid;
7272
oparms.reconnect = false;
7373

74-
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
74+
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
75+
NULL);
7576
if (rc) {
7677
kfree(utf16_path);
7778
return rc;

fs/cifs/smb2misc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,10 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
453453
start_of_path = from + 1;
454454
#ifdef CONFIG_CIFS_SMB311
455455
/* SMB311 POSIX extensions paths do not include leading slash */
456-
else if (cifs_sb_master_tcon(cifs_sb)->posix_extensions)
456+
else if (cifs_sb_master_tlink(cifs_sb) &&
457+
cifs_sb_master_tcon(cifs_sb)->posix_extensions) {
457458
start_of_path = from + 1;
459+
}
458460
#endif /* 311 */
459461
else
460462
start_of_path = from;

0 commit comments

Comments
 (0)