6 smb3 server fixes, including one for RDMA, one for improving NTLMSSP auth, one for improved buffer validation, one for stable

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmH/ARYACgkQiiy9cAdy
 T1GRYAwAp6iS2iyjvB5OXesiqj9b6ejn66dyA51Jaee8CvUx7YCNQVbnoCH3hVZX
 wHIMfvcGEej7QR8jtAipOdTeMbWlnNAxCC//TZjRgOnpRGe/uVqPEh7c5e1YFbhM
 UlNuN1zvWfn9n5jZIeeV8z2LuAj9mJCOAD4qjHJtPCh/vgyHzXfSFkC+7Ryc+41I
 fUvp43rz3xs73+uz4cZOhFGwv0CQxCSvddoUPCioF9JQlx6pkfiJjnoUPrUGtNJN
 RGjcZ5Er4GNMSeHhETLq83Sua5pagZRJL8F3Z7mpO+6iU97k3nfpZh29WaRDA4dN
 rtEVcm/juB2hFBgPU9m6QyXCfSnKjEVU59QJrVxHT89FluRW43p1CHCpTaLbPKHA
 +5emfpkHCreR3qLc17eIX4SmYfoChEeT7f00et5okmhyyyHPFu3adKVV8e4SRsUA
 sIJDI8oaPkhJgvj5ZZo20avKQ0wPR3m7zA+JjBKgiy8UmhV5Vl3hkdiVKU3r5Q4v
 TsKqukpl
 =CJKx
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2022-02-07 15:25:50 -08:00
Родитель 2ade8eef99 f9929ef6a2
Коммит 555f3d7be9
6 изменённых файлов: 70 добавлений и 14 удалений

Просмотреть файл

@ -369,8 +369,8 @@ source "fs/ksmbd/Kconfig"
config SMBFS_COMMON config SMBFS_COMMON
tristate tristate
default y if CIFS=y default y if CIFS=y || SMB_SERVER=y
default m if CIFS=m default m if CIFS=m || SMB_SERVER=m
source "fs/coda/Kconfig" source "fs/coda/Kconfig"
source "fs/afs/Kconfig" source "fs/afs/Kconfig"

Просмотреть файл

@ -29,6 +29,7 @@
#include "mgmt/user_config.h" #include "mgmt/user_config.h"
#include "crypto_ctx.h" #include "crypto_ctx.h"
#include "transport_ipc.h" #include "transport_ipc.h"
#include "../smbfs_common/arc4.h"
/* /*
* Fixed format data defining GSS header and fixed string * Fixed format data defining GSS header and fixed string
@ -336,6 +337,29 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
nt_len - CIFS_ENCPWD_SIZE, nt_len - CIFS_ENCPWD_SIZE,
domain_name, conn->ntlmssp.cryptkey); domain_name, conn->ntlmssp.cryptkey);
kfree(domain_name); kfree(domain_name);
/* The recovered secondary session key */
if (conn->ntlmssp.client_flags & NTLMSSP_NEGOTIATE_KEY_XCH) {
struct arc4_ctx *ctx_arc4;
unsigned int sess_key_off, sess_key_len;
sess_key_off = le32_to_cpu(authblob->SessionKey.BufferOffset);
sess_key_len = le16_to_cpu(authblob->SessionKey.Length);
if (blob_len < (u64)sess_key_off + sess_key_len)
return -EINVAL;
ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
if (!ctx_arc4)
return -ENOMEM;
cifs_arc4_setkey(ctx_arc4, sess->sess_key,
SMB2_NTLMV2_SESSKEY_SIZE);
cifs_arc4_crypt(ctx_arc4, sess->sess_key,
(char *)authblob + sess_key_off, sess_key_len);
kfree_sensitive(ctx_arc4);
}
return ret; return ret;
} }
@ -408,6 +432,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
(cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC)) (cflags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC; flags |= NTLMSSP_NEGOTIATE_EXTENDED_SEC;
if (cflags & NTLMSSP_NEGOTIATE_KEY_XCH)
flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
chgblob->NegotiateFlags = cpu_to_le32(flags); chgblob->NegotiateFlags = cpu_to_le32(flags);
len = strlen(ksmbd_netbios_name()); len = strlen(ksmbd_netbios_name());
name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL); name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);

Просмотреть файл

@ -2688,7 +2688,7 @@ int smb2_open(struct ksmbd_work *work)
(struct create_posix *)context; (struct create_posix *)context;
if (le16_to_cpu(context->DataOffset) + if (le16_to_cpu(context->DataOffset) +
le32_to_cpu(context->DataLength) < le32_to_cpu(context->DataLength) <
sizeof(struct create_posix)) { sizeof(struct create_posix) - 4) {
rc = -EINVAL; rc = -EINVAL;
goto err_out1; goto err_out1;
} }
@ -3422,9 +3422,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
goto free_conv_name; goto free_conv_name;
} }
struct_sz = readdir_info_level_struct_sz(info_level); struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len;
next_entry_offset = ALIGN(struct_sz - 1 + conv_len, next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT);
KSMBD_DIR_INFO_ALIGNMENT); d_info->last_entry_off_align = next_entry_offset - struct_sz;
if (next_entry_offset > d_info->out_buf_len) { if (next_entry_offset > d_info->out_buf_len) {
d_info->out_buf_len = 0; d_info->out_buf_len = 0;
@ -3976,6 +3976,7 @@ int smb2_query_dir(struct ksmbd_work *work)
((struct file_directory_info *) ((struct file_directory_info *)
((char *)rsp->Buffer + d_info.last_entry_offset)) ((char *)rsp->Buffer + d_info.last_entry_offset))
->NextEntryOffset = 0; ->NextEntryOffset = 0;
d_info.data_count -= d_info.last_entry_off_align;
rsp->StructureSize = cpu_to_le16(9); rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72); rsp->OutputBufferOffset = cpu_to_le16(72);
@ -6126,13 +6127,26 @@ static int smb2_set_remote_key_for_rdma(struct ksmbd_work *work,
__le16 ChannelInfoOffset, __le16 ChannelInfoOffset,
__le16 ChannelInfoLength) __le16 ChannelInfoLength)
{ {
unsigned int i, ch_count;
if (work->conn->dialect == SMB30_PROT_ID && if (work->conn->dialect == SMB30_PROT_ID &&
Channel != SMB2_CHANNEL_RDMA_V1) Channel != SMB2_CHANNEL_RDMA_V1)
return -EINVAL; return -EINVAL;
if (ChannelInfoOffset == 0 || ch_count = le16_to_cpu(ChannelInfoLength) / sizeof(*desc);
le16_to_cpu(ChannelInfoLength) < sizeof(*desc)) if (ksmbd_debug_types & KSMBD_DEBUG_RDMA) {
for (i = 0; i < ch_count; i++) {
pr_info("RDMA r/w request %#x: token %#x, length %#x\n",
i,
le32_to_cpu(desc[i].token),
le32_to_cpu(desc[i].length));
}
}
if (ch_count != 1) {
ksmbd_debug(RDMA, "RDMA multiple buffer descriptors %d are not supported yet\n",
ch_count);
return -EINVAL; return -EINVAL;
}
work->need_invalidate_rkey = work->need_invalidate_rkey =
(Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE); (Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE);
@ -6185,9 +6199,15 @@ int smb2_read(struct ksmbd_work *work)
if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE || if (req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE ||
req->Channel == SMB2_CHANNEL_RDMA_V1) { req->Channel == SMB2_CHANNEL_RDMA_V1) {
unsigned int ch_offset = le16_to_cpu(req->ReadChannelInfoOffset);
if (ch_offset < offsetof(struct smb2_read_req, Buffer)) {
err = -EINVAL;
goto out;
}
err = smb2_set_remote_key_for_rdma(work, err = smb2_set_remote_key_for_rdma(work,
(struct smb2_buffer_desc_v1 *) (struct smb2_buffer_desc_v1 *)
&req->Buffer[0], ((char *)req + ch_offset),
req->Channel, req->Channel,
req->ReadChannelInfoOffset, req->ReadChannelInfoOffset,
req->ReadChannelInfoLength); req->ReadChannelInfoLength);
@ -6428,11 +6448,16 @@ int smb2_write(struct ksmbd_work *work)
if (req->Channel == SMB2_CHANNEL_RDMA_V1 || if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) { req->Channel == SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
if (req->Length != 0 || req->DataOffset != 0) unsigned int ch_offset = le16_to_cpu(req->WriteChannelInfoOffset);
return -EINVAL;
if (req->Length != 0 || req->DataOffset != 0 ||
ch_offset < offsetof(struct smb2_write_req, Buffer)) {
err = -EINVAL;
goto out;
}
err = smb2_set_remote_key_for_rdma(work, err = smb2_set_remote_key_for_rdma(work,
(struct smb2_buffer_desc_v1 *) (struct smb2_buffer_desc_v1 *)
&req->Buffer[0], ((char *)req + ch_offset),
req->Channel, req->Channel,
req->WriteChannelInfoOffset, req->WriteChannelInfoOffset,
req->WriteChannelInfoLength); req->WriteChannelInfoLength);

Просмотреть файл

@ -308,14 +308,17 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
struct kstat kstat; struct kstat kstat;
struct ksmbd_kstat ksmbd_kstat; struct ksmbd_kstat ksmbd_kstat;
struct dentry *dentry;
if (!dir->dot_dotdot[i]) { /* fill dot entry info */ if (!dir->dot_dotdot[i]) { /* fill dot entry info */
if (i == 0) { if (i == 0) {
d_info->name = "."; d_info->name = ".";
d_info->name_len = 1; d_info->name_len = 1;
dentry = dir->filp->f_path.dentry;
} else { } else {
d_info->name = ".."; d_info->name = "..";
d_info->name_len = 2; d_info->name_len = 2;
dentry = dir->filp->f_path.dentry->d_parent;
} }
if (!match_pattern(d_info->name, d_info->name_len, 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,
ksmbd_kstat.kstat = &kstat; ksmbd_kstat.kstat = &kstat;
ksmbd_vfs_fill_dentry_attrs(work, ksmbd_vfs_fill_dentry_attrs(work,
user_ns, user_ns,
dir->filp->f_path.dentry->d_parent, dentry,
&ksmbd_kstat); &ksmbd_kstat);
rc = fn(conn, info_level, d_info, &ksmbd_kstat); rc = fn(conn, info_level, d_info, &ksmbd_kstat);
if (rc) if (rc)

Просмотреть файл

@ -80,7 +80,7 @@ static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
/* The maximum single-message size which can be received */ /* The maximum single-message size which can be received */
static int smb_direct_max_receive_size = 8192; static int smb_direct_max_receive_size = 8192;
static int smb_direct_max_read_write_size = 1048512; static int smb_direct_max_read_write_size = 524224;
static int smb_direct_max_outstanding_rw_ops = 8; static int smb_direct_max_outstanding_rw_ops = 8;

Просмотреть файл

@ -47,6 +47,7 @@ struct ksmbd_dir_info {
int last_entry_offset; int last_entry_offset;
bool hide_dot_file; bool hide_dot_file;
int flags; int flags;
int last_entry_off_align;
}; };
struct ksmbd_readdir_data { struct ksmbd_readdir_data {