mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
cifsd: add the check to prevent potential overflow with smb_strtoUTF16() and UNICODE_LEN()
Add the check to prevent potential overflow with smb_strtoUTF16() and UNICODE_LEN(). Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
7047805976
commit
a2d0b5034a
@ -246,7 +246,7 @@ out:
|
|||||||
static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
|
static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
|
||||||
char *dname)
|
char *dname)
|
||||||
{
|
{
|
||||||
int ret, len;
|
int ret, len, conv_len;
|
||||||
wchar_t *domain = NULL;
|
wchar_t *domain = NULL;
|
||||||
__le16 *uniname = NULL;
|
__le16 *uniname = NULL;
|
||||||
struct ksmbd_crypto_ctx *ctx;
|
struct ksmbd_crypto_ctx *ctx;
|
||||||
@ -279,15 +279,17 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len) {
|
conv_len = smb_strtoUTF16(uniname, user_name(sess->user), len,
|
||||||
len = smb_strtoUTF16(uniname, user_name(sess->user), len,
|
|
||||||
sess->conn->local_nls);
|
sess->conn->local_nls);
|
||||||
UniStrupr(uniname);
|
if (conv_len < 0 || conv_len > len) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
UniStrupr(uniname);
|
||||||
|
|
||||||
ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
|
ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
|
||||||
(char *)uniname,
|
(char *)uniname,
|
||||||
UNICODE_LEN(len));
|
UNICODE_LEN(conv_len));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ksmbd_debug(AUTH, "Could not update with user\n");
|
ksmbd_debug(AUTH, "Could not update with user\n");
|
||||||
goto out;
|
goto out;
|
||||||
@ -301,12 +303,16 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = smb_strtoUTF16((__le16 *)domain, dname, len,
|
conv_len = smb_strtoUTF16((__le16 *)domain, dname, len,
|
||||||
sess->conn->local_nls);
|
sess->conn->local_nls);
|
||||||
|
if (conv_len < 0 || conv_len > len) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
|
ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
|
||||||
(char *)domain,
|
(char *)domain,
|
||||||
UNICODE_LEN(len));
|
UNICODE_LEN(conv_len));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ksmbd_debug(AUTH, "Could not update with domain\n");
|
ksmbd_debug(AUTH, "Could not update with domain\n");
|
||||||
goto out;
|
goto out;
|
||||||
@ -584,6 +590,7 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
|
|||||||
wchar_t *name;
|
wchar_t *name;
|
||||||
__u8 *target_name;
|
__u8 *target_name;
|
||||||
unsigned int len, flags, blob_off, blob_len, type, target_info_len = 0;
|
unsigned int len, flags, blob_off, blob_len, type, target_info_len = 0;
|
||||||
|
unsigned int uni_len, conv_len;
|
||||||
int cflags = sess->ntlmssp.client_flags;
|
int cflags = sess->ntlmssp.client_flags;
|
||||||
|
|
||||||
memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8);
|
memcpy(chgblob->Signature, NTLMSSP_SIGNATURE, 8);
|
||||||
@ -611,19 +618,24 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
|
|||||||
|
|
||||||
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 + (len * 2), GFP_KERNEL);
|
name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
|
||||||
if (!name)
|
if (!name)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
|
conv_len = smb_strtoUTF16((__le16 *)name, ksmbd_netbios_name(), len,
|
||||||
sess->conn->local_nls);
|
sess->conn->local_nls);
|
||||||
len = UNICODE_LEN(len);
|
if (conv_len < 0 || conv_len > len) {
|
||||||
|
kfree(name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uni_len = UNICODE_LEN(conv_len);
|
||||||
|
|
||||||
blob_off = sizeof(struct challenge_message);
|
blob_off = sizeof(struct challenge_message);
|
||||||
blob_len = blob_off + len;
|
blob_len = blob_off + uni_len;
|
||||||
|
|
||||||
chgblob->TargetName.Length = cpu_to_le16(len);
|
chgblob->TargetName.Length = cpu_to_le16(uni_len);
|
||||||
chgblob->TargetName.MaximumLength = cpu_to_le16(len);
|
chgblob->TargetName.MaximumLength = cpu_to_le16(uni_len);
|
||||||
chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
|
chgblob->TargetName.BufferOffset = cpu_to_le32(blob_off);
|
||||||
|
|
||||||
/* Initialize random conn challenge */
|
/* Initialize random conn challenge */
|
||||||
@ -635,18 +647,18 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
|
|||||||
chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len);
|
chgblob->TargetInfoArray.BufferOffset = cpu_to_le32(blob_len);
|
||||||
|
|
||||||
target_name = (__u8 *)chgblob + blob_off;
|
target_name = (__u8 *)chgblob + blob_off;
|
||||||
memcpy(target_name, name, len);
|
memcpy(target_name, name, uni_len);
|
||||||
tinfo = (struct target_info *)(target_name + len);
|
tinfo = (struct target_info *)(target_name + uni_len);
|
||||||
|
|
||||||
chgblob->TargetInfoArray.Length = 0;
|
chgblob->TargetInfoArray.Length = 0;
|
||||||
/* Add target info list for NetBIOS/DNS settings */
|
/* Add target info list for NetBIOS/DNS settings */
|
||||||
for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
|
for (type = NTLMSSP_AV_NB_COMPUTER_NAME;
|
||||||
type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
|
type <= NTLMSSP_AV_DNS_DOMAIN_NAME; type++) {
|
||||||
tinfo->Type = cpu_to_le16(type);
|
tinfo->Type = cpu_to_le16(type);
|
||||||
tinfo->Length = cpu_to_le16(len);
|
tinfo->Length = cpu_to_le16(uni_len);
|
||||||
memcpy(tinfo->Content, name, len);
|
memcpy(tinfo->Content, name, uni_len);
|
||||||
tinfo = (struct target_info *)((char *)tinfo + 4 + len);
|
tinfo = (struct target_info *)((char *)tinfo + 4 + uni_len);
|
||||||
target_info_len += 4 + len;
|
target_info_len += 4 + uni_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add terminator subblock */
|
/* Add terminator subblock */
|
||||||
|
Loading…
Reference in New Issue
Block a user