Skip to content

Commit c75de84

Browse files
committed
Merge tag '5.15-rc4-ksmbd-fixes' of git://git.samba.org/ksmbd
Pull ksmbd fixes from Steve French: "Six fixes for the ksmbd kernel server, including two additional overflow checks, a fix for oops, and some cleanup (e.g. remove dead code for less secure dialects that has been removed)" * tag '5.15-rc4-ksmbd-fixes' of git://git.samba.org/ksmbd: ksmbd: fix oops from fuse driver ksmbd: fix version mismatch with out of tree ksmbd: use buf_data_size instead of recalculation in smb3_decrypt_req() ksmbd: remove the leftover of smb2.0 dialect support ksmbd: check strictly data area in ksmbd_smb2_check_message() ksmbd: add the check to vaildate if stream protocol length exceeds maximum value
2 parents 717478d + 64e7875 commit c75de84

File tree

8 files changed

+77
-114
lines changed

8 files changed

+77
-114
lines changed

fs/ksmbd/connection.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,12 @@ int ksmbd_conn_handler_loop(void *p)
296296
pdu_size = get_rfc1002_len(hdr_buf);
297297
ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);
298298

299-
/* make sure we have enough to get to SMB header end */
300-
if (!ksmbd_pdu_size_has_room(pdu_size)) {
301-
ksmbd_debug(CONN, "SMB request too short (%u bytes)\n",
302-
pdu_size);
299+
/*
300+
* Check if pdu size is valid (min : smb header size,
301+
* max : 0x00FFFFFF).
302+
*/
303+
if (pdu_size < __SMB2_HEADER_STRUCTURE_SIZE ||
304+
pdu_size > MAX_STREAM_PROT_LEN) {
303305
continue;
304306
}
305307

fs/ksmbd/glob.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include "unicode.h"
1313
#include "vfs_cache.h"
1414

15-
#define KSMBD_VERSION "3.1.9"
15+
#define KSMBD_VERSION "3.4.2"
1616

1717
extern int ksmbd_debug_types;
1818

fs/ksmbd/smb2misc.c

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,21 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
8080
};
8181

8282
/*
83-
* Returns the pointer to the beginning of the data area. Length of the data
84-
* area and the offset to it (from the beginning of the smb are also returned.
83+
* Set length of the data area and the offset to arguments.
84+
* if they are invalid, return error.
8585
*/
86-
static char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
86+
static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
87+
struct smb2_hdr *hdr)
8788
{
89+
int ret = 0;
90+
8891
*off = 0;
8992
*len = 0;
9093

9194
/* error reqeusts do not have data area */
9295
if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
9396
(((struct smb2_err_rsp *)hdr)->StructureSize) == SMB2_ERROR_STRUCTURE_SIZE2_LE)
94-
return NULL;
97+
return ret;
9598

9699
/*
97100
* Following commands have data areas so we have to get the location
@@ -165,69 +168,60 @@ static char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
165168
case SMB2_IOCTL:
166169
*off = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset);
167170
*len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount);
168-
169171
break;
170172
default:
171173
ksmbd_debug(SMB, "no length check for command\n");
172174
break;
173175
}
174176

175-
/*
176-
* Invalid length or offset probably means data area is invalid, but
177-
* we have little choice but to ignore the data area in this case.
178-
*/
179177
if (*off > 4096) {
180-
ksmbd_debug(SMB, "offset %d too large, data area ignored\n",
181-
*off);
182-
*len = 0;
183-
*off = 0;
184-
} else if (*off < 0) {
185-
ksmbd_debug(SMB,
186-
"negative offset %d to data invalid ignore data area\n",
187-
*off);
188-
*off = 0;
189-
*len = 0;
190-
} else if (*len < 0) {
191-
ksmbd_debug(SMB,
192-
"negative data length %d invalid, data area ignored\n",
193-
*len);
194-
*len = 0;
195-
} else if (*len > 128 * 1024) {
196-
ksmbd_debug(SMB, "data area larger than 128K: %d\n", *len);
197-
*len = 0;
178+
ksmbd_debug(SMB, "offset %d too large\n", *off);
179+
ret = -EINVAL;
180+
} else if ((u64)*off + *len > MAX_STREAM_PROT_LEN) {
181+
ksmbd_debug(SMB, "Request is larger than maximum stream protocol length(%u): %llu\n",
182+
MAX_STREAM_PROT_LEN, (u64)*off + *len);
183+
ret = -EINVAL;
198184
}
199185

200-
/* return pointer to beginning of data area, ie offset from SMB start */
201-
if ((*off != 0) && (*len != 0))
202-
return (char *)hdr + *off;
203-
else
204-
return NULL;
186+
return ret;
205187
}
206188

207189
/*
208190
* Calculate the size of the SMB message based on the fixed header
209191
* portion, the number of word parameters and the data portion of the message.
210192
*/
211-
static unsigned int smb2_calc_size(void *buf)
193+
static int smb2_calc_size(void *buf, unsigned int *len)
212194
{
213195
struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
214196
struct smb2_hdr *hdr = &pdu->hdr;
215-
int offset; /* the offset from the beginning of SMB to data area */
216-
int data_length; /* the length of the variable length data area */
197+
unsigned int offset; /* the offset from the beginning of SMB to data area */
198+
unsigned int data_length; /* the length of the variable length data area */
199+
int ret;
200+
217201
/* Structure Size has already been checked to make sure it is 64 */
218-
int len = le16_to_cpu(hdr->StructureSize);
202+
*len = le16_to_cpu(hdr->StructureSize);
219203

220204
/*
221205
* StructureSize2, ie length of fixed parameter area has already
222206
* been checked to make sure it is the correct length.
223207
*/
224-
len += le16_to_cpu(pdu->StructureSize2);
208+
*len += le16_to_cpu(pdu->StructureSize2);
209+
/*
210+
* StructureSize2 of smb2_lock pdu is set to 48, indicating
211+
* the size of smb2 lock request with single smb2_lock_element
212+
* regardless of number of locks. Subtract single
213+
* smb2_lock_element for correct buffer size check.
214+
*/
215+
if (hdr->Command == SMB2_LOCK)
216+
*len -= sizeof(struct smb2_lock_element);
225217

226218
if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false)
227219
goto calc_size_exit;
228220

229-
smb2_get_data_area_len(&offset, &data_length, hdr);
230-
ksmbd_debug(SMB, "SMB2 data length %d offset %d\n", data_length,
221+
ret = smb2_get_data_area_len(&offset, &data_length, hdr);
222+
if (ret)
223+
return ret;
224+
ksmbd_debug(SMB, "SMB2 data length %u offset %u\n", data_length,
231225
offset);
232226

233227
if (data_length > 0) {
@@ -237,16 +231,19 @@ static unsigned int smb2_calc_size(void *buf)
237231
* for some commands, typically those with odd StructureSize,
238232
* so we must add one to the calculation.
239233
*/
240-
if (offset + 1 < len)
234+
if (offset + 1 < *len) {
241235
ksmbd_debug(SMB,
242-
"data area offset %d overlaps SMB2 header %d\n",
243-
offset + 1, len);
244-
else
245-
len = offset + data_length;
236+
"data area offset %d overlaps SMB2 header %u\n",
237+
offset + 1, *len);
238+
return -EINVAL;
239+
}
240+
241+
*len = offset + data_length;
246242
}
243+
247244
calc_size_exit:
248-
ksmbd_debug(SMB, "SMB2 len %d\n", len);
249-
return len;
245+
ksmbd_debug(SMB, "SMB2 len %u\n", *len);
246+
return 0;
250247
}
251248

252249
static inline int smb2_query_info_req_len(struct smb2_query_info_req *h)
@@ -391,9 +388,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
391388
return 1;
392389
}
393390

394-
clc_len = smb2_calc_size(hdr);
391+
if (smb2_calc_size(hdr, &clc_len))
392+
return 1;
393+
395394
if (len != clc_len) {
396-
/* server can return one byte more due to implied bcc[0] */
395+
/* client can return one byte more due to implied bcc[0] */
397396
if (clc_len == len + 1)
398397
return 0;
399398

@@ -418,9 +417,6 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
418417
return 0;
419418
}
420419

421-
if (command == SMB2_LOCK_HE && len == 88)
422-
return 0;
423-
424420
ksmbd_debug(SMB,
425421
"cli req too short, len %d not %d. cmd:%d mid:%llu\n",
426422
len, clc_len, command,

fs/ksmbd/smb2ops.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,6 @@ static struct smb_version_cmds smb2_0_server_cmds[NUMBER_OF_SMB2_COMMANDS] = {
187187
[SMB2_CHANGE_NOTIFY_HE] = { .proc = smb2_notify},
188188
};
189189

190-
int init_smb2_0_server(struct ksmbd_conn *conn)
191-
{
192-
return -EOPNOTSUPP;
193-
}
194-
195190
/**
196191
* init_smb2_1_server() - initialize a smb server connection with smb2.1
197192
* command dispatcher

fs/ksmbd/smb2pdu.c

Lines changed: 18 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,6 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
236236

237237
if (conn->need_neg == false)
238238
return -EINVAL;
239-
if (!(conn->dialect >= SMB20_PROT_ID &&
240-
conn->dialect <= SMB311_PROT_ID))
241-
return -EINVAL;
242239

243240
rsp_hdr = work->response_buf;
244241

@@ -1166,13 +1163,6 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
11661163
case SMB21_PROT_ID:
11671164
init_smb2_1_server(conn);
11681165
break;
1169-
case SMB20_PROT_ID:
1170-
rc = init_smb2_0_server(conn);
1171-
if (rc) {
1172-
rsp->hdr.Status = STATUS_NOT_SUPPORTED;
1173-
goto err_out;
1174-
}
1175-
break;
11761166
case SMB2X_PROT_ID:
11771167
case BAD_PROT_ID:
11781168
default:
@@ -1191,11 +1181,9 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
11911181
rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size);
11921182
rsp->MaxWriteSize = cpu_to_le32(conn->vals->max_write_size);
11931183

1194-
if (conn->dialect > SMB20_PROT_ID) {
1195-
memcpy(conn->ClientGUID, req->ClientGUID,
1196-
SMB2_CLIENT_GUID_SIZE);
1197-
conn->cli_sec_mode = le16_to_cpu(req->SecurityMode);
1198-
}
1184+
memcpy(conn->ClientGUID, req->ClientGUID,
1185+
SMB2_CLIENT_GUID_SIZE);
1186+
conn->cli_sec_mode = le16_to_cpu(req->SecurityMode);
11991187

12001188
rsp->StructureSize = cpu_to_le16(65);
12011189
rsp->DialectRevision = cpu_to_le16(conn->dialect);
@@ -1537,11 +1525,9 @@ static int ntlm_authenticate(struct ksmbd_work *work)
15371525
}
15381526
}
15391527

1540-
if (conn->dialect > SMB20_PROT_ID) {
1541-
if (!ksmbd_conn_lookup_dialect(conn)) {
1542-
pr_err("fail to verify the dialect\n");
1543-
return -ENOENT;
1544-
}
1528+
if (!ksmbd_conn_lookup_dialect(conn)) {
1529+
pr_err("fail to verify the dialect\n");
1530+
return -ENOENT;
15451531
}
15461532
return 0;
15471533
}
@@ -1623,11 +1609,9 @@ static int krb5_authenticate(struct ksmbd_work *work)
16231609
}
16241610
}
16251611

1626-
if (conn->dialect > SMB20_PROT_ID) {
1627-
if (!ksmbd_conn_lookup_dialect(conn)) {
1628-
pr_err("fail to verify the dialect\n");
1629-
return -ENOENT;
1630-
}
1612+
if (!ksmbd_conn_lookup_dialect(conn)) {
1613+
pr_err("fail to verify the dialect\n");
1614+
return -ENOENT;
16311615
}
16321616
return 0;
16331617
}
@@ -5499,7 +5483,6 @@ static int set_file_basic_info(struct ksmbd_file *fp,
54995483
struct ksmbd_share_config *share)
55005484
{
55015485
struct iattr attrs;
5502-
struct timespec64 ctime;
55035486
struct file *filp;
55045487
struct inode *inode;
55055488
struct user_namespace *user_ns;
@@ -5521,13 +5504,11 @@ static int set_file_basic_info(struct ksmbd_file *fp,
55215504
attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
55225505
}
55235506

5524-
if (file_info->ChangeTime) {
5507+
attrs.ia_valid |= ATTR_CTIME;
5508+
if (file_info->ChangeTime)
55255509
attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
5526-
ctime = attrs.ia_ctime;
5527-
attrs.ia_valid |= ATTR_CTIME;
5528-
} else {
5529-
ctime = inode->i_ctime;
5530-
}
5510+
else
5511+
attrs.ia_ctime = inode->i_ctime;
55315512

55325513
if (file_info->LastWriteTime) {
55335514
attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
@@ -5573,11 +5554,9 @@ static int set_file_basic_info(struct ksmbd_file *fp,
55735554
return -EACCES;
55745555

55755556
inode_lock(inode);
5557+
inode->i_ctime = attrs.ia_ctime;
5558+
attrs.ia_valid &= ~ATTR_CTIME;
55765559
rc = notify_change(user_ns, dentry, &attrs, NULL);
5577-
if (!rc) {
5578-
inode->i_ctime = ctime;
5579-
mark_inode_dirty(inode);
5580-
}
55815560
inode_unlock(inode);
55825561
}
55835562
return rc;
@@ -8411,20 +8390,18 @@ int smb3_decrypt_req(struct ksmbd_work *work)
84118390
struct smb2_hdr *hdr;
84128391
unsigned int pdu_length = get_rfc1002_len(buf);
84138392
struct kvec iov[2];
8414-
unsigned int buf_data_size = pdu_length + 4 -
8393+
int buf_data_size = pdu_length + 4 -
84158394
sizeof(struct smb2_transform_hdr);
84168395
struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
84178396
int rc = 0;
84188397

8419-
if (pdu_length + 4 <
8420-
sizeof(struct smb2_transform_hdr) + sizeof(struct smb2_hdr)) {
8398+
if (buf_data_size < sizeof(struct smb2_hdr)) {
84218399
pr_err("Transform message is too small (%u)\n",
84228400
pdu_length);
84238401
return -ECONNABORTED;
84248402
}
84258403

8426-
if (pdu_length + 4 <
8427-
le32_to_cpu(tr_hdr->OriginalMessageSize) + sizeof(struct smb2_transform_hdr)) {
8404+
if (buf_data_size < le32_to_cpu(tr_hdr->OriginalMessageSize)) {
84288405
pr_err("Transform message is broken\n");
84298406
return -ECONNABORTED;
84308407
}

fs/ksmbd/smb2pdu.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1637,7 +1637,6 @@ struct smb2_posix_info {
16371637
} __packed;
16381638

16391639
/* functions */
1640-
int init_smb2_0_server(struct ksmbd_conn *conn);
16411640
void init_smb2_1_server(struct ksmbd_conn *conn);
16421641
void init_smb3_0_server(struct ksmbd_conn *conn);
16431642
void init_smb3_02_server(struct ksmbd_conn *conn);

fs/ksmbd/smb_common.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ static const char basechars[43] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
2121
#define MAGIC_CHAR '~'
2222
#define PERIOD '.'
2323
#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
24-
#define KSMBD_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr))
2524

2625
struct smb_protocol {
2726
int index;
@@ -89,7 +88,7 @@ unsigned int ksmbd_server_side_copy_max_total_size(void)
8988

9089
inline int ksmbd_min_protocol(void)
9190
{
92-
return SMB2_PROT;
91+
return SMB21_PROT;
9392
}
9493

9594
inline int ksmbd_max_protocol(void)
@@ -294,11 +293,6 @@ int ksmbd_init_smb_server(struct ksmbd_work *work)
294293
return 0;
295294
}
296295

297-
bool ksmbd_pdu_size_has_room(unsigned int pdu)
298-
{
299-
return (pdu >= KSMBD_MIN_SUPPORTED_HEADER_SIZE - 4);
300-
}
301-
302296
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
303297
struct ksmbd_file *dir,
304298
struct ksmbd_dir_info *d_info,
@@ -433,7 +427,7 @@ int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
433427

434428
static int __smb2_negotiate(struct ksmbd_conn *conn)
435429
{
436-
return (conn->dialect >= SMB20_PROT_ID &&
430+
return (conn->dialect >= SMB21_PROT_ID &&
437431
conn->dialect <= SMB311_PROT_ID);
438432
}
439433

@@ -463,7 +457,7 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
463457
}
464458
}
465459

466-
if (command == SMB2_NEGOTIATE_HE) {
460+
if (command == SMB2_NEGOTIATE_HE && __smb2_negotiate(conn)) {
467461
ret = smb2_handle_negotiate(work);
468462
init_smb2_neg_rsp(work);
469463
return ret;

0 commit comments

Comments
 (0)