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:
Коммит
555f3d7be9
|
@ -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 {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче