Skip to content

Commit 09c9b0e

Browse files
committed
Merge tag '4.17-rc1SMB3-Fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "SMB3 fixes, a few for stable, and some important cleanup work from Ronnie of the smb3 transport code" * tag '4.17-rc1SMB3-Fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: change validate_buf to validate_iov cifs: remove rfc1002 hardcoded constants from cifs_discard_remaining_data() cifs: Change SMB2_open to return an iov for the error parameter cifs: add resp_buf_size to the mid_q_entry structure smb3.11: replace a 4 with server->vals->header_preamble_size cifs: replace a 4 with server->vals->header_preamble_size cifs: add pdu_size to the TCP_Server_Info structure SMB311: Improve checking of negotiate security contexts SMB3: Fix length checking of SMB3.11 negotiate request CIFS: add ONCE flag for cifs_dbg type cifs: Use ULL suffix for 64-bit constant SMB3: Log at least once if tree connect fails during reconnect cifs: smb2pdu: Fix potential NULL pointer dereference
2 parents f0d98d8 + c1596ff commit 09c9b0e

File tree

13 files changed

+240
-71
lines changed

13 files changed

+240
-71
lines changed

fs/cifs/cifs_debug.c

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,6 @@ cifs_dump_mem(char *label, void *data, int length)
4242
data, length, true);
4343
}
4444

45-
#ifdef CONFIG_CIFS_DEBUG
46-
void cifs_vfs_err(const char *fmt, ...)
47-
{
48-
struct va_format vaf;
49-
va_list args;
50-
51-
va_start(args, fmt);
52-
53-
vaf.fmt = fmt;
54-
vaf.va = &args;
55-
56-
pr_err_ratelimited("CIFS VFS: %pV", &vaf);
57-
58-
va_end(args);
59-
}
60-
#endif
61-
6245
void cifs_dump_detail(void *buf)
6346
{
6447
#ifdef CONFIG_CIFS_DEBUG2

fs/cifs/cifs_debug.h

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,36 @@ extern int cifsFYI;
3939
#else
4040
#define NOISY 0
4141
#endif
42+
#define ONCE 8
4243

4344
/*
4445
* debug ON
4546
* --------
4647
*/
4748
#ifdef CONFIG_CIFS_DEBUG
4849

49-
__printf(1, 2) void cifs_vfs_err(const char *fmt, ...);
50-
5150
/* information message: e.g., configuration, major event */
52-
#define cifs_dbg(type, fmt, ...) \
53-
do { \
54-
if (type == FYI && cifsFYI & CIFS_INFO) { \
55-
pr_debug_ratelimited("%s: " \
56-
fmt, __FILE__, ##__VA_ARGS__); \
57-
} else if (type == VFS) { \
58-
cifs_vfs_err(fmt, ##__VA_ARGS__); \
59-
} else if (type == NOISY && type != 0) { \
60-
pr_debug_ratelimited(fmt, ##__VA_ARGS__); \
61-
} \
51+
#define cifs_dbg_func(ratefunc, type, fmt, ...) \
52+
do { \
53+
if ((type) & FYI && cifsFYI & CIFS_INFO) { \
54+
pr_debug_ ## ratefunc("%s: " \
55+
fmt, __FILE__, ##__VA_ARGS__); \
56+
} else if ((type) & VFS) { \
57+
pr_err_ ## ratefunc("CuIFS VFS: " \
58+
fmt, ##__VA_ARGS__); \
59+
} else if ((type) & NOISY && (NOISY != 0)) { \
60+
pr_debug_ ## ratefunc(fmt, ##__VA_ARGS__); \
61+
} \
62+
} while (0)
63+
64+
#define cifs_dbg(type, fmt, ...) \
65+
do { \
66+
if ((type) & ONCE) \
67+
cifs_dbg_func(once, \
68+
type, fmt, ##__VA_ARGS__); \
69+
else \
70+
cifs_dbg_func(ratelimited, \
71+
type, fmt, ##__VA_ARGS__); \
6272
} while (0)
6373

6474
/*

fs/cifs/cifsglob.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@ struct TCP_Server_Info {
665665
struct delayed_work echo; /* echo ping workqueue job */
666666
char *smallbuf; /* pointer to current "small" buffer */
667667
char *bigbuf; /* pointer to current "big" buffer */
668+
/* Total size of this PDU. Only valid from cifs_demultiplex_thread */
669+
unsigned int pdu_size;
668670
unsigned int total_read; /* total amount of data read in this pass */
669671
#ifdef CONFIG_CIFS_FSCACHE
670672
struct fscache_cookie *fscache; /* client index cache cookie */
@@ -676,6 +678,7 @@ struct TCP_Server_Info {
676678
unsigned int max_read;
677679
unsigned int max_write;
678680
#ifdef CONFIG_CIFS_SMB311
681+
__le16 cipher_type;
679682
/* save initital negprot hash */
680683
__u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
681684
#endif /* 3.1.1 */
@@ -1373,6 +1376,7 @@ struct mid_q_entry {
13731376
mid_handle_t *handle; /* call handle mid callback */
13741377
void *callback_data; /* general purpose pointer for callback */
13751378
void *resp_buf; /* pointer to received SMB header */
1379+
unsigned int resp_buf_size;
13761380
int mid_state; /* wish this were enum but can not pass to wait_event */
13771381
unsigned int mid_flags;
13781382
__le16 command; /* smb command code */

fs/cifs/cifssmb.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,10 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
206206
mutex_unlock(&ses->session_mutex);
207207
cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
208208

209-
if (rc)
209+
if (rc) {
210+
printk_once(KERN_WARNING "reconnect tcon failed rc = %d\n", rc);
210211
goto out;
212+
}
211213

212214
atomic_inc(&tconInfoReconnectCount);
213215

@@ -1416,8 +1418,9 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
14161418
int
14171419
cifs_discard_remaining_data(struct TCP_Server_Info *server)
14181420
{
1419-
unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1420-
int remaining = rfclen + 4 - server->total_read;
1421+
unsigned int rfclen = server->pdu_size;
1422+
int remaining = rfclen + server->vals->header_preamble_size -
1423+
server->total_read;
14211424

14221425
while (remaining > 0) {
14231426
int length;
@@ -1454,7 +1457,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
14541457
unsigned int data_offset, data_len;
14551458
struct cifs_readdata *rdata = mid->callback_data;
14561459
char *buf = server->smallbuf;
1457-
unsigned int buflen = get_rfc1002_length(buf) +
1460+
unsigned int buflen = server->pdu_size +
14581461
server->vals->header_preamble_size;
14591462
bool use_rdma_mr = false;
14601463

fs/cifs/connect.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
772772
{
773773
int length;
774774
char *buf = server->smallbuf;
775-
unsigned int pdu_length = get_rfc1002_length(buf);
775+
unsigned int pdu_length = server->pdu_size;
776776

777777
/* make sure this will fit in a large buffer */
778778
if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
@@ -881,6 +881,7 @@ cifs_demultiplex_thread(void *p)
881881
* so we can now interpret the length field.
882882
*/
883883
pdu_length = get_rfc1002_length(buf);
884+
server->pdu_size = pdu_length;
884885

885886
cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
886887
if (!is_smb_response(server, buf[0]))
@@ -927,6 +928,7 @@ cifs_demultiplex_thread(void *p)
927928

928929
server->lstrp = jiffies;
929930
if (mid_entry != NULL) {
931+
mid_entry->resp_buf_size = server->pdu_size;
930932
if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
931933
mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
932934
server->ops->handle_cancelled_mid)

fs/cifs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ cifs_get_file_info(struct file *filp)
710710
/* Simple function to return a 64 bit hash of string. Rarely called */
711711
static __u64 simple_hashstr(const char *str)
712712
{
713-
const __u64 hash_mult = 1125899906842597L; /* a big enough prime */
713+
const __u64 hash_mult = 1125899906842597ULL; /* a big enough prime */
714714
__u64 hash = 0;
715715

716716
while (*str)

fs/cifs/smb2misc.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,43 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
9393
/* SMB2_OPLOCK_BREAK */ cpu_to_le16(24)
9494
};
9595

96+
#ifdef CONFIG_CIFS_SMB311
97+
static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen,
98+
size_t hdr_preamble_size)
99+
{
100+
__u16 neg_count;
101+
__u32 nc_offset, size_of_pad_before_neg_ctxts;
102+
struct smb2_negotiate_rsp *pneg_rsp = (struct smb2_negotiate_rsp *)hdr;
103+
104+
/* Negotiate contexts are only valid for latest dialect SMB3.11 */
105+
neg_count = le16_to_cpu(pneg_rsp->NegotiateContextCount);
106+
if ((neg_count == 0) ||
107+
(pneg_rsp->DialectRevision != cpu_to_le16(SMB311_PROT_ID)))
108+
return 0;
109+
110+
/* Make sure that negotiate contexts start after gss security blob */
111+
nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset);
112+
if (nc_offset < non_ctxlen - hdr_preamble_size /* RFC1001 len */) {
113+
printk_once(KERN_WARNING "invalid negotiate context offset\n");
114+
return 0;
115+
}
116+
size_of_pad_before_neg_ctxts = nc_offset -
117+
(non_ctxlen - hdr_preamble_size);
118+
119+
/* Verify that at least minimal negotiate contexts fit within frame */
120+
if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) {
121+
printk_once(KERN_WARNING "negotiate context goes beyond end\n");
122+
return 0;
123+
}
124+
125+
cifs_dbg(FYI, "length of negcontexts %d pad %d\n",
126+
len - nc_offset, size_of_pad_before_neg_ctxts);
127+
128+
/* length of negcontexts including pad from end of sec blob to them */
129+
return (len - nc_offset) + size_of_pad_before_neg_ctxts;
130+
}
131+
#endif /* CIFS_SMB311 */
132+
96133
int
97134
smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
98135
{
@@ -198,6 +235,11 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
198235

199236
clc_len = smb2_calc_size(hdr);
200237

238+
#ifdef CONFIG_CIFS_SMB311
239+
if (shdr->Command == SMB2_NEGOTIATE)
240+
clc_len += get_neg_ctxt_len(hdr, len, clc_len,
241+
srvr->vals->header_preamble_size);
242+
#endif /* SMB311 */
201243
if (srvr->vals->header_preamble_size + len != clc_len) {
202244
cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n",
203245
clc_len, srvr->vals->header_preamble_size + len, mid);

fs/cifs/smb2ops.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
14511451
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
14521452
struct cifs_open_parms oparms;
14531453
struct cifs_fid fid;
1454+
struct kvec err_iov = {NULL, 0};
14541455
struct smb2_err_rsp *err_buf = NULL;
14551456
struct smb2_symlink_err_rsp *symlink;
14561457
unsigned int sub_len;
@@ -1473,15 +1474,16 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
14731474
oparms.fid = &fid;
14741475
oparms.reconnect = false;
14751476

1476-
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf);
1477+
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
14771478

14781479
if (!rc || !err_buf) {
14791480
kfree(utf16_path);
14801481
return -ENOENT;
14811482
}
14821483

1484+
err_buf = err_iov.iov_base;
14831485
if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
1484-
get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
1486+
err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
14851487
kfree(utf16_path);
14861488
return -ENOENT;
14871489
}
@@ -1494,13 +1496,13 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
14941496
print_len = le16_to_cpu(symlink->PrintNameLength);
14951497
print_offset = le16_to_cpu(symlink->PrintNameOffset);
14961498

1497-
if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
1499+
if (err_iov.iov_len + server->vals->header_preamble_size <
14981500
SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
14991501
kfree(utf16_path);
15001502
return -ENOENT;
15011503
}
15021504

1503-
if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
1505+
if (err_iov.iov_len + server->vals->header_preamble_size <
15041506
SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
15051507
kfree(utf16_path);
15061508
return -ENOENT;
@@ -2550,7 +2552,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
25502552
unsigned int npages;
25512553
struct page **pages;
25522554
unsigned int len;
2553-
unsigned int buflen = get_rfc1002_length(buf) + server->vals->header_preamble_size;
2555+
unsigned int buflen = server->pdu_size + server->vals->header_preamble_size;
25542556
int rc;
25552557
int i = 0;
25562558

@@ -2624,7 +2626,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
26242626
{
26252627
int length;
26262628
char *buf = server->smallbuf;
2627-
unsigned int pdu_length = get_rfc1002_length(buf);
2629+
unsigned int pdu_length = server->pdu_size;
26282630
unsigned int buf_size;
26292631
struct mid_q_entry *mid_entry;
26302632

@@ -2668,7 +2670,7 @@ static int
26682670
smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
26692671
{
26702672
char *buf = server->smallbuf;
2671-
unsigned int pdu_length = get_rfc1002_length(buf);
2673+
unsigned int pdu_length = server->pdu_size;
26722674
struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
26732675
unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
26742676

@@ -2699,7 +2701,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
26992701
{
27002702
char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
27012703

2702-
return handle_read_data(server, mid, buf, get_rfc1002_length(buf) +
2704+
return handle_read_data(server, mid, buf, server->pdu_size +
27032705
server->vals->header_preamble_size,
27042706
NULL, 0, 0);
27052707
}

0 commit comments

Comments
 (0)