Skip to content

Commit 555f3d7

Browse files
committed
Merge tag '5.17-rc3-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull ksmbd server fixes from Steve French: - NTLMSSP authentication improvement - RDMA (smbdirect) fix allowing broader set of NICs to be supported - improved buffer validation - additional small fixes, including a posix extensions fix for stable * tag '5.17-rc3-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: add support for key exchange ksmbd: reduce smb direct max read/write size ksmbd: don't align last entry offset in smb2 query directory ksmbd: fix same UniqueId for dot and dotdot entries ksmbd: smbd: validate buffer descriptor structures ksmbd: fix SMB 3.11 posix extension mount failure
2 parents 2ade8ee + f9929ef commit 555f3d7

File tree

6 files changed

+70
-14
lines changed

6 files changed

+70
-14
lines changed

fs/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,8 @@ source "fs/ksmbd/Kconfig"
369369

370370
config SMBFS_COMMON
371371
tristate
372-
default y if CIFS=y
373-
default m if CIFS=m
372+
default y if CIFS=y || SMB_SERVER=y
373+
default m if CIFS=m || SMB_SERVER=m
374374

375375
source "fs/coda/Kconfig"
376376
source "fs/afs/Kconfig"

fs/ksmbd/auth.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "mgmt/user_config.h"
3030
#include "crypto_ctx.h"
3131
#include "transport_ipc.h"
32+
#include "../smbfs_common/arc4.h"
3233

3334
/*
3435
* Fixed format data defining GSS header and fixed string
@@ -336,6 +337,29 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
336337
nt_len - CIFS_ENCPWD_SIZE,
337338
domain_name, conn->ntlmssp.cryptkey);
338339
kfree(domain_name);
340+
341+
/* The recovered secondary session key */
342+
if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) {
343+
struct arc4_ctx *ctx_arc4;
344+
unsigned int sess_key_off, sess_key_len;
345+
346+
sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset);
347+
sess_key_len = le16_to_cpu(authblob->SessionKey.Length);
348+
349+
if (blob_len < (u64)sess_key_off + sess_key_len)
350+
return -EINVAL;
351+
352+
ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
353+
if (!ctx_arc4)
354+
return -ENOMEM;
355+
356+
cifs_arc4_setkey(ctx_arc4, sess->sess_key,
357+
SMB2_NTLMV2_SESSKEY_SIZE);
358+
cifs_arc4_crypt(ctx_arc4, sess->sess_key,
359+
(char *)authblob + sess_key_off, sess_key_len);
360+
kfree_sensitive(ctx_arc4);
361+
}
362+
339363
return ret;
340364
}
341365

@@ -408,6 +432,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
408432
(cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
409433
flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
410434

435+
if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH)
436+
flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
437+
411438
chgblob->NegotiateFlags = cpu_to_le32(flags);
412439
len = strlen(ksmbd_netbios_name());
413440
name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);

fs/ksmbd/smb2pdu.c

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2688,7 +2688,7 @@ int smb2_open(struct ksmbd_work *work)
26882688
(struct create_posix *)context;
26892689
if (le16_to_cpu(context->DataOffset) +
26902690
le32_to_cpu(context->DataLength) <
2691-
sizeof(struct create_posix)) {
2691+
sizeof(struct create_posix) - 4) {
26922692
rc = -EINVAL;
26932693
goto err_out1;
26942694
}
@@ -3422,9 +3422,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
34223422
goto free_conv_name;
34233423
}
34243424

3425-
struct_sz = readdir_info_level_struct_sz(info_level);
3426-
next_entry_offset = ALIGN(struct_sz - 1 + conv_len,
3427-
KSMBD_DIR_INFO_ALIGNMENT);
3425+
struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len;
3426+
next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT);
3427+
d_info->last_entry_off_align = next_entry_offset - struct_sz;
34283428

34293429
if (next_entry_offset > d_info->out_buf_len) {
34303430
d_info->out_buf_len = 0;
@@ -3976,6 +3976,7 @@ int smb2_query_dir(struct ksmbd_work *work)
39763976
((struct file_directory_info *)
39773977
((char *)rsp->Buffer + d_info.last_entry_offset))
39783978
->NextEntryOffset = 0;
3979+
d_info.data_count -= d_info.last_entry_off_align;
39793980

39803981
rsp->StructureSize = cpu_to_le16(9);
39813982
rsp->OutputBufferOffset = cpu_to_le16(72);
@@ -6126,13 +6127,26 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
61266127
__le16 ChannelInfoOffset,
61276128
__le16 ChannelInfoLength)
61286129
{
6130+
unsigned int i, ch_count;
6131+
61296132
if (work->conn->dialect == SMB30_PROT_ID &&
61306133
Channel != SMB2_CHANNEL_RDMA_V1)
61316134
return -EINVAL;
61326135

6133-
if (ChannelInfoOffset == 0 ||
6134-
le16_to_cpu(ChannelInfoLength) < sizeof(*desc))
6136+
ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc);
6137+
if (ksmbd_debug_types & KSMBD_DEBUG_RDMA) {
6138+
for (i = 0; i < ch_count; i++) {
6139+
pr_info("RDMA r/w request %#x: token %#x, length %#x\n",
6140+
i,
6141+
le32_to_cpu(desc[i].token),
6142+
le32_to_cpu(desc[i].length));
6143+
}
6144+
}
6145+
if (ch_count != 1) {
6146+
ksmbd_debug(RDMA, "RDMA multiple buffer descriptors %d are not supported yet\n",
6147+
ch_count);
61356148
return -EINVAL;
6149+
}
61366150

61376151
work->need_invalidate_rkey =
61386152
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
@@ -6185,9 +6199,15 @@ int smb2_read(struct ksmbd_work *work)
61856199

61866200
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
61876201
req->Channel == SMB2_CHANNEL_RDMA_V1) {
6202+
unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
6203+
6204+
if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
6205+
err = -EINVAL;
6206+
goto out;
6207+
}
61886208
err = smb2_set_remote_key_for_rdma(work,
61896209
(struct smb2_buffer_desc_v1 *)
6190-
&req->Buffer[0],
6210+
((char *)req + ch_offset),
61916211
req->Channel,
61926212
req->ReadChannelInfoOffset,
61936213
req->ReadChannelInfoLength);
@@ -6428,11 +6448,16 @@ int smb2_write(struct ksmbd_work *work)
64286448

64296449
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
64306450
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
6431-
if (req->Length != 0 || req->DataOffset != 0)
6432-
return -EINVAL;
6451+
unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
6452+
6453+
if (req->Length != 0 || req->DataOffset != 0 ||
6454+
ch_offset < offsetof(struct smb2_write_req, Buffer)) {
6455+
err = -EINVAL;
6456+
goto out;
6457+
}
64336458
err = smb2_set_remote_key_for_rdma(work,
64346459
(struct smb2_buffer_desc_v1 *)
6435-
&req->Buffer[0],
6460+
((char *)req + ch_offset),
64366461
req->Channel,
64376462
req->WriteChannelInfoOffset,
64386463
req->WriteChannelInfoLength);

fs/ksmbd/smb_common.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,14 +308,17 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
308308
for (i = 0; i < 2; i++) {
309309
struct kstat kstat;
310310
struct ksmbd_kstat ksmbd_kstat;
311+
struct dentry *dentry;
311312

312313
if (!dir->dot_dotdot[i]) { /* fill dot entry info */
313314
if (i == 0) {
314315
d_info->name = ".";
315316
d_info->name_len = 1;
317+
dentry = dir->filp->f_path.dentry;
316318
} else {
317319
d_info->name = "..";
318320
d_info->name_len = 2;
321+
dentry = dir->filp->f_path.dentry->d_parent;
319322
}
320323

321324
if (!match_pattern(d_info->name, d_info->name_len,
@@ -327,7 +330,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
327330
ksmbd_kstat.kstat = &kstat;
328331
ksmbd_vfs_fill_dentry_attrs(work,
329332
user_ns,
330-
dir->filp->f_path.dentry->d_parent,
333+
dentry,
331334
&ksmbd_kstat);
332335
rc = fn(conn, info_level, d_info, &ksmbd_kstat);
333336
if (rc)

fs/ksmbd/transport_rdma.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
8080
/* The maximum single-message size which can be received */
8181
static int smb_direct_max_receive_size = 8192;
8282

83-
static int smb_direct_max_read_write_size = 1048512;
83+
static int smb_direct_max_read_write_size = 524224;
8484

8585
static int smb_direct_max_outstanding_rw_ops = 8;
8686

fs/ksmbd/vfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct ksmbd_dir_info {
4747
int last_entry_offset;
4848
bool hide_dot_file;
4949
int flags;
50+
int last_entry_off_align;
5051
};
5152

5253
struct ksmbd_readdir_data {

0 commit comments

Comments
 (0)