eight smb3 server fixes (also for stable)
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmQd2yMACgkQiiy9cAdy T1Hn0gwAnXY+Rl59ESZxvpjxFtK3rPzr8jchwo04gQn2NUQZSBr3eaU7AgUu91ib vAnN/NwUjUg3rGX5t/oBBW1BrbpMEM++I9glElStB+lcA8XubfkBXnWzSo/1d7cM dgk2Q0eblIcbwZeVNbJ31wO112T6JRmyJFMmNP1DhJS3HUy8veUV0ZNlK6r08y1t dlVGYRFo0hivlAgeCfSqJwcwcbB4vMACb1SDKQYZWaR2CQ7PyN02osGoLWpbMe1Q uQQBsMtvo4nY40aObI91TEMAUn4vIceuRw84P/4J6DINY+01fSSCFEJd9Ez1cvhP CX3zaR0qG07gALeHQL7zgo3VOPIIoKyBG5ctioMoRmo9Ian+ZnxJDRHPhXir51y/ XbZhdkWfvy4xdVDoAAHAOWPL+/MJGNNvmxdsELanS4fuKHY4o5bclnTsCrfqqV9z XIx6R8nUJkRSDqqcZxi44RQn0NBAZX0MFP13DP1r7ZiGJIusVmklOqmXx8IeTIMs 2csnpA8m =rX3t -----END PGP SIGNATURE----- Merge tag '6.3-rc3-ksmbd-smb3-server-fixes' of git://git.samba.org/ksmbd Pull ksmbd server fixes from Steve French: - return less confusing messages on unsupported dialects (STATUS_NOT_SUPPORTED instead of I/O error) - fix for overly frequent inactive session termination - fix refcount leak - fix bounds check problems found by static checkers - fix to advertise named stream support correctly - Fix AES256 signing bug when connected to from MacOS * tag '6.3-rc3-ksmbd-smb3-server-fixes' of git://git.samba.org/ksmbd: ksmbd: return unsupported error on smb1 mount ksmbd: return STATUS_NOT_SUPPORTED on unsupported smb2.0 dialect ksmbd: don't terminate inactive sessions after a few seconds ksmbd: fix possible refcount leak in smb2_open() ksmbd: add low bound validation to FSCTL_QUERY_ALLOCATED_RANGES ksmbd: add low bound validation to FSCTL_SET_ZERO_DATA ksmbd: set FILE_NAMED_STREAMS attribute in FS_ATTRIBUTE_INFORMATION ksmbd: fix wrong signingkey creation when encryption is AES256
This commit is contained in:
commit
90c8ce31db
@ -727,8 +727,9 @@ static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
|
|||||||
goto smb3signkey_ret;
|
goto smb3signkey_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
|
if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
|
||||||
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)
|
(conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
|
||||||
|
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
|
||||||
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
|
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
|
||||||
else
|
else
|
||||||
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
|
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
|
||||||
|
@ -298,7 +298,7 @@ int ksmbd_conn_handler_loop(void *p)
|
|||||||
kvfree(conn->request_buf);
|
kvfree(conn->request_buf);
|
||||||
conn->request_buf = NULL;
|
conn->request_buf = NULL;
|
||||||
|
|
||||||
size = t->ops->read(t, hdr_buf, sizeof(hdr_buf));
|
size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
|
||||||
if (size != sizeof(hdr_buf))
|
if (size != sizeof(hdr_buf))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -319,13 +319,10 @@ int ksmbd_conn_handler_loop(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if pdu size is valid (min : smb header size,
|
* Check maximum pdu size(0x00FFFFFF).
|
||||||
* max : 0x00FFFFFF).
|
|
||||||
*/
|
*/
|
||||||
if (pdu_size < __SMB2_HEADER_STRUCTURE_SIZE ||
|
if (pdu_size > MAX_STREAM_PROT_LEN)
|
||||||
pdu_size > MAX_STREAM_PROT_LEN) {
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* 4 for rfc1002 length field */
|
/* 4 for rfc1002 length field */
|
||||||
size = pdu_size + 4;
|
size = pdu_size + 4;
|
||||||
@ -344,7 +341,7 @@ int ksmbd_conn_handler_loop(void *p)
|
|||||||
* We already read 4 bytes to find out PDU size, now
|
* We already read 4 bytes to find out PDU size, now
|
||||||
* read in PDU
|
* read in PDU
|
||||||
*/
|
*/
|
||||||
size = t->ops->read(t, conn->request_buf + 4, pdu_size);
|
size = t->ops->read(t, conn->request_buf + 4, pdu_size, 2);
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
pr_err("sock_read failed: %d\n", size);
|
pr_err("sock_read failed: %d\n", size);
|
||||||
break;
|
break;
|
||||||
|
@ -114,7 +114,8 @@ struct ksmbd_transport_ops {
|
|||||||
int (*prepare)(struct ksmbd_transport *t);
|
int (*prepare)(struct ksmbd_transport *t);
|
||||||
void (*disconnect)(struct ksmbd_transport *t);
|
void (*disconnect)(struct ksmbd_transport *t);
|
||||||
void (*shutdown)(struct ksmbd_transport *t);
|
void (*shutdown)(struct ksmbd_transport *t);
|
||||||
int (*read)(struct ksmbd_transport *t, char *buf, unsigned int size);
|
int (*read)(struct ksmbd_transport *t, char *buf,
|
||||||
|
unsigned int size, int max_retries);
|
||||||
int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
|
int (*writev)(struct ksmbd_transport *t, struct kvec *iovs, int niov,
|
||||||
int size, bool need_invalidate_rkey,
|
int size, bool need_invalidate_rkey,
|
||||||
unsigned int remote_key);
|
unsigned int remote_key);
|
||||||
|
@ -2977,8 +2977,11 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
sizeof(struct smb_acl) +
|
sizeof(struct smb_acl) +
|
||||||
sizeof(struct smb_ace) * ace_num * 2,
|
sizeof(struct smb_ace) * ace_num * 2,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!pntsd)
|
if (!pntsd) {
|
||||||
|
posix_acl_release(fattr.cf_acls);
|
||||||
|
posix_acl_release(fattr.cf_dacls);
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
rc = build_sec_desc(idmap,
|
rc = build_sec_desc(idmap,
|
||||||
pntsd, NULL, 0,
|
pntsd, NULL, 0,
|
||||||
@ -4934,6 +4937,10 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
|
|||||||
|
|
||||||
info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
|
info->Attributes |= cpu_to_le32(server_conf.share_fake_fscaps);
|
||||||
|
|
||||||
|
if (test_share_config_flag(work->tcon->share_conf,
|
||||||
|
KSMBD_SHARE_FLAG_STREAMS))
|
||||||
|
info->Attributes |= cpu_to_le32(FILE_NAMED_STREAMS);
|
||||||
|
|
||||||
info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen);
|
info->MaxPathNameComponentLength = cpu_to_le32(stfs.f_namelen);
|
||||||
len = smbConvertToUTF16((__le16 *)info->FileSystemName,
|
len = smbConvertToUTF16((__le16 *)info->FileSystemName,
|
||||||
"NTFS", PATH_MAX, conn->local_nls, 0);
|
"NTFS", PATH_MAX, conn->local_nls, 0);
|
||||||
@ -7444,13 +7451,16 @@ static int fsctl_query_allocated_ranges(struct ksmbd_work *work, u64 id,
|
|||||||
if (in_count == 0)
|
if (in_count == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
start = le64_to_cpu(qar_req->file_offset);
|
||||||
|
length = le64_to_cpu(qar_req->length);
|
||||||
|
|
||||||
|
if (start < 0 || length < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
fp = ksmbd_lookup_fd_fast(work, id);
|
fp = ksmbd_lookup_fd_fast(work, id);
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
start = le64_to_cpu(qar_req->file_offset);
|
|
||||||
length = le64_to_cpu(qar_req->length);
|
|
||||||
|
|
||||||
ret = ksmbd_vfs_fqar_lseek(fp, start, length,
|
ret = ksmbd_vfs_fqar_lseek(fp, start, length,
|
||||||
qar_rsp, in_count, out_count);
|
qar_rsp, in_count, out_count);
|
||||||
if (ret && ret != -E2BIG)
|
if (ret && ret != -E2BIG)
|
||||||
@ -7751,7 +7761,7 @@ int smb2_ioctl(struct ksmbd_work *work)
|
|||||||
|
|
||||||
off = le64_to_cpu(zero_data->FileOffset);
|
off = le64_to_cpu(zero_data->FileOffset);
|
||||||
bfz = le64_to_cpu(zero_data->BeyondFinalZero);
|
bfz = le64_to_cpu(zero_data->BeyondFinalZero);
|
||||||
if (off > bfz) {
|
if (off < 0 || bfz < 0 || off > bfz) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ int ksmbd_extract_shortname(struct ksmbd_conn *conn, const char *longname,
|
|||||||
|
|
||||||
static int __smb2_negotiate(struct ksmbd_conn *conn)
|
static int __smb2_negotiate(struct ksmbd_conn *conn)
|
||||||
{
|
{
|
||||||
return (conn->dialect >= SMB21_PROT_ID &&
|
return (conn->dialect >= SMB20_PROT_ID &&
|
||||||
conn->dialect <= SMB311_PROT_ID);
|
conn->dialect <= SMB311_PROT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,9 +442,26 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
|
|||||||
{
|
{
|
||||||
struct smb_negotiate_rsp *neg_rsp = work->response_buf;
|
struct smb_negotiate_rsp *neg_rsp = work->response_buf;
|
||||||
|
|
||||||
ksmbd_debug(SMB, "Unsupported SMB protocol\n");
|
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
|
||||||
neg_rsp->hdr.Status.CifsError = STATUS_INVALID_LOGON_TYPE;
|
|
||||||
return -EINVAL;
|
/*
|
||||||
|
* Remove 4 byte direct TCP header, add 2 byte bcc and
|
||||||
|
* 2 byte DialectIndex.
|
||||||
|
*/
|
||||||
|
*(__be32 *)work->response_buf =
|
||||||
|
cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2 + 2);
|
||||||
|
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
neg_rsp->hdr.Command = SMB_COM_NEGOTIATE;
|
||||||
|
*(__le32 *)neg_rsp->hdr.Protocol = SMB1_PROTO_NUMBER;
|
||||||
|
neg_rsp->hdr.Flags = SMBFLG_RESPONSE;
|
||||||
|
neg_rsp->hdr.Flags2 = SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS |
|
||||||
|
SMBFLG2_EXT_SEC | SMBFLG2_IS_LONG_NAME;
|
||||||
|
|
||||||
|
neg_rsp->hdr.WordCount = 1;
|
||||||
|
neg_rsp->DialectIndex = cpu_to_le16(work->conn->dialect);
|
||||||
|
neg_rsp->ByteCount = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
|
int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
|
||||||
@ -465,7 +482,7 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command == SMB2_NEGOTIATE_HE && __smb2_negotiate(conn)) {
|
if (command == SMB2_NEGOTIATE_HE) {
|
||||||
ret = smb2_handle_negotiate(work);
|
ret = smb2_handle_negotiate(work);
|
||||||
init_smb2_neg_rsp(work);
|
init_smb2_neg_rsp(work);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -158,8 +158,15 @@
|
|||||||
|
|
||||||
#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
|
#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
|
||||||
#define SMB_COM_NEGOTIATE 0x72
|
#define SMB_COM_NEGOTIATE 0x72
|
||||||
|
|
||||||
#define SMB1_CLIENT_GUID_SIZE (16)
|
#define SMB1_CLIENT_GUID_SIZE (16)
|
||||||
|
|
||||||
|
#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
|
||||||
|
|
||||||
|
#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
|
||||||
|
#define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
|
||||||
|
#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
|
||||||
|
#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
|
||||||
|
|
||||||
struct smb_hdr {
|
struct smb_hdr {
|
||||||
__be32 smb_buf_length;
|
__be32 smb_buf_length;
|
||||||
__u8 Protocol[4];
|
__u8 Protocol[4];
|
||||||
@ -199,28 +206,7 @@ struct smb_negotiate_req {
|
|||||||
struct smb_negotiate_rsp {
|
struct smb_negotiate_rsp {
|
||||||
struct smb_hdr hdr; /* wct = 17 */
|
struct smb_hdr hdr; /* wct = 17 */
|
||||||
__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
|
__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
|
||||||
__u8 SecurityMode;
|
|
||||||
__le16 MaxMpxCount;
|
|
||||||
__le16 MaxNumberVcs;
|
|
||||||
__le32 MaxBufferSize;
|
|
||||||
__le32 MaxRawSize;
|
|
||||||
__le32 SessionKey;
|
|
||||||
__le32 Capabilities; /* see below */
|
|
||||||
__le32 SystemTimeLow;
|
|
||||||
__le32 SystemTimeHigh;
|
|
||||||
__le16 ServerTimeZone;
|
|
||||||
__u8 EncryptionKeyLength;
|
|
||||||
__le16 ByteCount;
|
__le16 ByteCount;
|
||||||
union {
|
|
||||||
unsigned char EncryptionKey[8]; /* cap extended security off */
|
|
||||||
/* followed by Domain name - if extended security is off */
|
|
||||||
/* followed by 16 bytes of server GUID */
|
|
||||||
/* then security blob if cap_extended_security negotiated */
|
|
||||||
struct {
|
|
||||||
unsigned char GUID[SMB1_CLIENT_GUID_SIZE];
|
|
||||||
unsigned char SecurityBlob[1];
|
|
||||||
} __packed extended_response;
|
|
||||||
} __packed u;
|
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
struct filesystem_attribute_info {
|
struct filesystem_attribute_info {
|
||||||
|
@ -670,7 +670,7 @@ static int smb_direct_post_recv(struct smb_direct_transport *t,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int smb_direct_read(struct ksmbd_transport *t, char *buf,
|
static int smb_direct_read(struct ksmbd_transport *t, char *buf,
|
||||||
unsigned int size)
|
unsigned int size, int unused)
|
||||||
{
|
{
|
||||||
struct smb_direct_recvmsg *recvmsg;
|
struct smb_direct_recvmsg *recvmsg;
|
||||||
struct smb_direct_data_transfer *data_transfer;
|
struct smb_direct_data_transfer *data_transfer;
|
||||||
|
@ -291,16 +291,18 @@ static int ksmbd_tcp_run_kthread(struct interface *iface)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ksmbd_tcp_readv() - read data from socket in given iovec
|
* ksmbd_tcp_readv() - read data from socket in given iovec
|
||||||
* @t: TCP transport instance
|
* @t: TCP transport instance
|
||||||
* @iov_orig: base IO vector
|
* @iov_orig: base IO vector
|
||||||
* @nr_segs: number of segments in base iov
|
* @nr_segs: number of segments in base iov
|
||||||
* @to_read: number of bytes to read from socket
|
* @to_read: number of bytes to read from socket
|
||||||
|
* @max_retries: maximum retry count
|
||||||
*
|
*
|
||||||
* Return: on success return number of bytes read from socket,
|
* Return: on success return number of bytes read from socket,
|
||||||
* otherwise return error number
|
* otherwise return error number
|
||||||
*/
|
*/
|
||||||
static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
|
static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
|
||||||
unsigned int nr_segs, unsigned int to_read)
|
unsigned int nr_segs, unsigned int to_read,
|
||||||
|
int max_retries)
|
||||||
{
|
{
|
||||||
int length = 0;
|
int length = 0;
|
||||||
int total_read;
|
int total_read;
|
||||||
@ -308,7 +310,6 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
|
|||||||
struct msghdr ksmbd_msg;
|
struct msghdr ksmbd_msg;
|
||||||
struct kvec *iov;
|
struct kvec *iov;
|
||||||
struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
|
struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn;
|
||||||
int max_retry = 2;
|
|
||||||
|
|
||||||
iov = get_conn_iovec(t, nr_segs);
|
iov = get_conn_iovec(t, nr_segs);
|
||||||
if (!iov)
|
if (!iov)
|
||||||
@ -335,14 +336,23 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
|
|||||||
} else if (conn->status == KSMBD_SESS_NEED_RECONNECT) {
|
} else if (conn->status == KSMBD_SESS_NEED_RECONNECT) {
|
||||||
total_read = -EAGAIN;
|
total_read = -EAGAIN;
|
||||||
break;
|
break;
|
||||||
} else if ((length == -ERESTARTSYS || length == -EAGAIN) &&
|
} else if (length == -ERESTARTSYS || length == -EAGAIN) {
|
||||||
max_retry) {
|
/*
|
||||||
|
* If max_retries is negative, Allow unlimited
|
||||||
|
* retries to keep connection with inactive sessions.
|
||||||
|
*/
|
||||||
|
if (max_retries == 0) {
|
||||||
|
total_read = length;
|
||||||
|
break;
|
||||||
|
} else if (max_retries > 0) {
|
||||||
|
max_retries--;
|
||||||
|
}
|
||||||
|
|
||||||
usleep_range(1000, 2000);
|
usleep_range(1000, 2000);
|
||||||
length = 0;
|
length = 0;
|
||||||
max_retry--;
|
|
||||||
continue;
|
continue;
|
||||||
} else if (length <= 0) {
|
} else if (length <= 0) {
|
||||||
total_read = -EAGAIN;
|
total_read = length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -358,14 +368,15 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig,
|
|||||||
* Return: on success return number of bytes read from socket,
|
* Return: on success return number of bytes read from socket,
|
||||||
* otherwise return error number
|
* otherwise return error number
|
||||||
*/
|
*/
|
||||||
static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf, unsigned int to_read)
|
static int ksmbd_tcp_read(struct ksmbd_transport *t, char *buf,
|
||||||
|
unsigned int to_read, int max_retries)
|
||||||
{
|
{
|
||||||
struct kvec iov;
|
struct kvec iov;
|
||||||
|
|
||||||
iov.iov_base = buf;
|
iov.iov_base = buf;
|
||||||
iov.iov_len = to_read;
|
iov.iov_len = to_read;
|
||||||
|
|
||||||
return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read);
|
return ksmbd_tcp_readv(TCP_TRANS(t), &iov, 1, to_read, max_retries);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
|
static int ksmbd_tcp_writev(struct ksmbd_transport *t, struct kvec *iov,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user