Commit e25ca045 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.15-rc3-ksmbd-fixes' of git://git.samba.org/ksmbd

Pull ksmbd server fixes from Steve French:
 "Eleven fixes for the ksmbd kernel server, mostly security related:

   - an important fix for disabling weak NTLMv1 authentication

   - seven security (improved buffer overflow checks) fixes

   - fix for wrong infolevel struct used in some getattr/setattr paths

   - two small documentation fixes"

* tag '5.15-rc3-ksmbd-fixes' of git://git.samba.org/ksmbd:
  ksmbd: missing check for NULL in convert_to_nt_pathname()
  ksmbd: fix transform header validation
  ksmbd: add buffer validation for SMB2_CREATE_CONTEXT
  ksmbd: add validation in smb2 negotiate
  ksmbd: add request buffer validation in smb2_set_info
  ksmbd: use correct basic info level in set_file_basic_info()
  ksmbd: remove NTLMv1 authentication
  ksmbd: fix documentation for 2 functions
  MAINTAINERS: rename cifs_common to smbfs_common in cifs and ksmbd entry
  ksmbd: fix invalid request buffer access in compound
  ksmbd: remove RFC1002 check in smb2 request
parents 9904468f 87ffb310
...@@ -4657,7 +4657,7 @@ W: http://linux-cifs.samba.org/ ...@@ -4657,7 +4657,7 @@ W: http://linux-cifs.samba.org/
T: git git://git.samba.org/sfrench/cifs-2.6.git T: git git://git.samba.org/sfrench/cifs-2.6.git
F: Documentation/admin-guide/cifs/ F: Documentation/admin-guide/cifs/
F: fs/cifs/ F: fs/cifs/
F: fs/cifs_common/ F: fs/smbfs_common/
COMPACTPCI HOTPLUG CORE COMPACTPCI HOTPLUG CORE
M: Scott Murray <scott@spiteful.org> M: Scott Murray <scott@spiteful.org>
...@@ -10195,8 +10195,8 @@ M: Hyunchul Lee <hyc.lee@gmail.com> ...@@ -10195,8 +10195,8 @@ M: Hyunchul Lee <hyc.lee@gmail.com>
L: linux-cifs@vger.kernel.org L: linux-cifs@vger.kernel.org
S: Maintained S: Maintained
T: git git://git.samba.org/ksmbd.git T: git git://git.samba.org/ksmbd.git
F: fs/cifs_common/
F: fs/ksmbd/ F: fs/ksmbd/
F: fs/smbfs_common/
KERNEL UNIT TESTING FRAMEWORK (KUnit) KERNEL UNIT TESTING FRAMEWORK (KUnit)
M: Brendan Higgins <brendanhiggins@google.com> M: Brendan Higgins <brendanhiggins@google.com>
......
...@@ -68,125 +68,6 @@ void ksmbd_copy_gss_neg_header(void *buf) ...@@ -68,125 +68,6 @@ void ksmbd_copy_gss_neg_header(void *buf)
memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH); memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH);
} }
static void
str_to_key(unsigned char *str, unsigned char *key)
{
int i;
key[0] = str[0] >> 1;
key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
key[7] = str[6] & 0x7F;
for (i = 0; i < 8; i++)
key[i] = (key[i] << 1);
}
static int
smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
{
unsigned char key2[8];
struct des_ctx ctx;
if (fips_enabled) {
ksmbd_debug(AUTH, "FIPS compliance enabled: DES not permitted\n");
return -ENOENT;
}
str_to_key(key, key2);
des_expand_key(&ctx, key2, DES_KEY_SIZE);
des_encrypt(&ctx, out, in);
memzero_explicit(&ctx, sizeof(ctx));
return 0;
}
static int ksmbd_enc_p24(unsigned char *p21, const unsigned char *c8, unsigned char *p24)
{
int rc;
rc = smbhash(p24, c8, p21);
if (rc)
return rc;
rc = smbhash(p24 + 8, c8, p21 + 7);
if (rc)
return rc;
return smbhash(p24 + 16, c8, p21 + 14);
}
/* produce a md4 message digest from data of length n bytes */
static int ksmbd_enc_md4(unsigned char *md4_hash, unsigned char *link_str,
int link_len)
{
int rc;
struct ksmbd_crypto_ctx *ctx;
ctx = ksmbd_crypto_ctx_find_md4();
if (!ctx) {
ksmbd_debug(AUTH, "Crypto md4 allocation error\n");
return -ENOMEM;
}
rc = crypto_shash_init(CRYPTO_MD4(ctx));
if (rc) {
ksmbd_debug(AUTH, "Could not init md4 shash\n");
goto out;
}
rc = crypto_shash_update(CRYPTO_MD4(ctx), link_str, link_len);
if (rc) {
ksmbd_debug(AUTH, "Could not update with link_str\n");
goto out;
}
rc = crypto_shash_final(CRYPTO_MD4(ctx), md4_hash);
if (rc)
ksmbd_debug(AUTH, "Could not generate md4 hash\n");
out:
ksmbd_release_crypto_ctx(ctx);
return rc;
}
static int ksmbd_enc_update_sess_key(unsigned char *md5_hash, char *nonce,
char *server_challenge, int len)
{
int rc;
struct ksmbd_crypto_ctx *ctx;
ctx = ksmbd_crypto_ctx_find_md5();
if (!ctx) {
ksmbd_debug(AUTH, "Crypto md5 allocation error\n");
return -ENOMEM;
}
rc = crypto_shash_init(CRYPTO_MD5(ctx));
if (rc) {
ksmbd_debug(AUTH, "Could not init md5 shash\n");
goto out;
}
rc = crypto_shash_update(CRYPTO_MD5(ctx), server_challenge, len);
if (rc) {
ksmbd_debug(AUTH, "Could not update with challenge\n");
goto out;
}
rc = crypto_shash_update(CRYPTO_MD5(ctx), nonce, len);
if (rc) {
ksmbd_debug(AUTH, "Could not update with nonce\n");
goto out;
}
rc = crypto_shash_final(CRYPTO_MD5(ctx), md5_hash);
if (rc)
ksmbd_debug(AUTH, "Could not generate md5 hash\n");
out:
ksmbd_release_crypto_ctx(ctx);
return rc;
}
/** /**
* ksmbd_gen_sess_key() - function to generate session key * ksmbd_gen_sess_key() - function to generate session key
* @sess: session of connection * @sess: session of connection
...@@ -324,43 +205,6 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash, ...@@ -324,43 +205,6 @@ static int calc_ntlmv2_hash(struct ksmbd_session *sess, char *ntlmv2_hash,
return ret; return ret;
} }
/**
* ksmbd_auth_ntlm() - NTLM authentication handler
* @sess: session of connection
* @pw_buf: NTLM challenge response
* @passkey: user password
*
* Return: 0 on success, error number on error
*/
int ksmbd_auth_ntlm(struct ksmbd_session *sess, char *pw_buf)
{
int rc;
unsigned char p21[21];
char key[CIFS_AUTH_RESP_SIZE];
memset(p21, '\0', 21);
memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE);
rc = ksmbd_enc_p24(p21, sess->ntlmssp.cryptkey, key);
if (rc) {
pr_err("password processing failed\n");
return rc;
}
ksmbd_enc_md4(sess->sess_key, user_passkey(sess->user),
CIFS_SMB1_SESSKEY_SIZE);
memcpy(sess->sess_key + CIFS_SMB1_SESSKEY_SIZE, key,
CIFS_AUTH_RESP_SIZE);
sess->sequence_number = 1;
if (strncmp(pw_buf, key, CIFS_AUTH_RESP_SIZE) != 0) {
ksmbd_debug(AUTH, "ntlmv1 authentication failed\n");
return -EINVAL;
}
ksmbd_debug(AUTH, "ntlmv1 authentication pass\n");
return 0;
}
/** /**
* ksmbd_auth_ntlmv2() - NTLMv2 authentication handler * ksmbd_auth_ntlmv2() - NTLMv2 authentication handler
* @sess: session of connection * @sess: session of connection
...@@ -441,44 +285,6 @@ int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2, ...@@ -441,44 +285,6 @@ int ksmbd_auth_ntlmv2(struct ksmbd_session *sess, struct ntlmv2_resp *ntlmv2,
return rc; return rc;
} }
/**
* __ksmbd_auth_ntlmv2() - NTLM2(extended security) authentication handler
* @sess: session of connection
* @client_nonce: client nonce from LM response.
* @ntlm_resp: ntlm response data from client.
*
* Return: 0 on success, error number on error
*/
static int __ksmbd_auth_ntlmv2(struct ksmbd_session *sess, char *client_nonce,
char *ntlm_resp)
{
char sess_key[CIFS_SMB1_SESSKEY_SIZE] = {0};
int rc;
unsigned char p21[21];
char key[CIFS_AUTH_RESP_SIZE];
rc = ksmbd_enc_update_sess_key(sess_key,
client_nonce,
(char *)sess->ntlmssp.cryptkey, 8);
if (rc) {
pr_err("password processing failed\n");
goto out;
}
memset(p21, '\0', 21);
memcpy(p21, user_passkey(sess->user), CIFS_NTHASH_SIZE);
rc = ksmbd_enc_p24(p21, sess_key, key);
if (rc) {
pr_err("password processing failed\n");
goto out;
}
if (memcmp(ntlm_resp, key, CIFS_AUTH_RESP_SIZE) != 0)
rc = -EINVAL;
out:
return rc;
}
/** /**
* ksmbd_decode_ntlmssp_auth_blob() - helper function to construct * ksmbd_decode_ntlmssp_auth_blob() - helper function to construct
* authenticate blob * authenticate blob
...@@ -512,17 +318,6 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, ...@@ -512,17 +318,6 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset); nt_off = le32_to_cpu(authblob->NtChallengeResponse.BufferOffset);
nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length); nt_len = le16_to_cpu(authblob->NtChallengeResponse.Length);
/* process NTLM authentication */
if (nt_len == CIFS_AUTH_RESP_SIZE) {
if (le32_to_cpu(authblob->NegotiateFlags) &
NTLMSSP_NEGOTIATE_EXTENDED_SEC)
return __ksmbd_auth_ntlmv2(sess, (char *)authblob +
lm_off, (char *)authblob + nt_off);
else
return ksmbd_auth_ntlm(sess, (char *)authblob +
nt_off);
}
/* TODO : use domain name that imported from configuration file */ /* TODO : use domain name that imported from configuration file */
domain_name = smb_strndup_from_utf16((const char *)authblob + domain_name = smb_strndup_from_utf16((const char *)authblob +
le32_to_cpu(authblob->DomainName.BufferOffset), le32_to_cpu(authblob->DomainName.BufferOffset),
......
...@@ -81,12 +81,6 @@ static struct shash_desc *alloc_shash_desc(int id) ...@@ -81,12 +81,6 @@ static struct shash_desc *alloc_shash_desc(int id)
case CRYPTO_SHASH_SHA512: case CRYPTO_SHASH_SHA512:
tfm = crypto_alloc_shash("sha512", 0, 0); tfm = crypto_alloc_shash("sha512", 0, 0);
break; break;
case CRYPTO_SHASH_MD4:
tfm = crypto_alloc_shash("md4", 0, 0);
break;
case CRYPTO_SHASH_MD5:
tfm = crypto_alloc_shash("md5", 0, 0);
break;
default: default:
return NULL; return NULL;
} }
...@@ -214,16 +208,6 @@ struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void) ...@@ -214,16 +208,6 @@ struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void)
return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512); return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512);
} }
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void)
{
return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD4);
}
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void)
{
return ____crypto_shash_ctx_find(CRYPTO_SHASH_MD5);
}
static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id) static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
{ {
struct ksmbd_crypto_ctx *ctx; struct ksmbd_crypto_ctx *ctx;
......
...@@ -15,8 +15,6 @@ enum { ...@@ -15,8 +15,6 @@ enum {
CRYPTO_SHASH_CMACAES, CRYPTO_SHASH_CMACAES,
CRYPTO_SHASH_SHA256, CRYPTO_SHASH_SHA256,
CRYPTO_SHASH_SHA512, CRYPTO_SHASH_SHA512,
CRYPTO_SHASH_MD4,
CRYPTO_SHASH_MD5,
CRYPTO_SHASH_MAX, CRYPTO_SHASH_MAX,
}; };
...@@ -43,8 +41,6 @@ struct ksmbd_crypto_ctx { ...@@ -43,8 +41,6 @@ struct ksmbd_crypto_ctx {
#define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES]) #define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES])
#define CRYPTO_SHA256(c) ((c)->desc[CRYPTO_SHASH_SHA256]) #define CRYPTO_SHA256(c) ((c)->desc[CRYPTO_SHASH_SHA256])
#define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512]) #define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512])
#define CRYPTO_MD4(c) ((c)->desc[CRYPTO_SHASH_MD4])
#define CRYPTO_MD5(c) ((c)->desc[CRYPTO_SHASH_MD5])
#define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm) #define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm)
#define CRYPTO_HMACSHA256_TFM(c)\ #define CRYPTO_HMACSHA256_TFM(c)\
...@@ -52,8 +48,6 @@ struct ksmbd_crypto_ctx { ...@@ -52,8 +48,6 @@ struct ksmbd_crypto_ctx {
#define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm) #define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm)
#define CRYPTO_SHA256_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA256]->tfm) #define CRYPTO_SHA256_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA256]->tfm)
#define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm) #define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm)
#define CRYPTO_MD4_TFM(c) ((c)->desc[CRYPTO_SHASH_MD4]->tfm)
#define CRYPTO_MD5_TFM(c) ((c)->desc[CRYPTO_SHASH_MD5]->tfm)
#define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM]) #define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])
#define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM]) #define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM])
...@@ -64,8 +58,6 @@ struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void); ...@@ -64,8 +58,6 @@ struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void); struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void); struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void); struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha256(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md4(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_md5(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void); struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void); struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
void ksmbd_crypto_destroy(void); void ksmbd_crypto_destroy(void);
......
...@@ -162,17 +162,14 @@ char *convert_to_nt_pathname(char *filename) ...@@ -162,17 +162,14 @@ char *convert_to_nt_pathname(char *filename)
{ {
char *ab_pathname; char *ab_pathname;
if (strlen(filename) == 0) { if (strlen(filename) == 0)
ab_pathname = kmalloc(2, GFP_KERNEL); filename = "\\";
ab_pathname[0] = '\\';
ab_pathname[1] = '\0';
} else {
ab_pathname = kstrdup(filename, GFP_KERNEL);
if (!ab_pathname)
return NULL;
ksmbd_conv_path_to_windows(ab_pathname); ab_pathname = kstrdup(filename, GFP_KERNEL);
} if (!ab_pathname)
return NULL;
ksmbd_conv_path_to_windows(ab_pathname);
return ab_pathname; return ab_pathname;
} }
......
...@@ -1451,26 +1451,47 @@ struct lease_ctx_info *parse_lease_state(void *open_req) ...@@ -1451,26 +1451,47 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
*/ */
struct create_context *smb2_find_context_vals(void *open_req, const char *tag) struct create_context *smb2_find_context_vals(void *open_req, const char *tag)
{ {
char *data_offset;
struct create_context *cc; struct create_context *cc;
unsigned int next = 0; unsigned int next = 0;
char *name; char *name;
struct smb2_create_req *req = (struct smb2_create_req *)open_req; struct smb2_create_req *req = (struct smb2_create_req *)open_req;
unsigned int remain_len, name_off, name_len, value_off, value_len,
cc_len;
data_offset = (char *)req + 4 + le32_to_cpu(req->CreateContextsOffset); /*
cc = (struct create_context *)data_offset; * CreateContextsOffset and CreateContextsLength are guaranteed to
* be valid because of ksmbd_smb2_check_message().
*/
cc = (struct create_context *)((char *)req + 4 +
le32_to_cpu(req->CreateContextsOffset));
remain_len = le32_to_cpu(req->CreateContextsLength);
do { do {
int val;
cc = (struct create_context *)((char *)cc + next); cc = (struct create_context *)((char *)cc + next);
name = le16_to_cpu(cc->NameOffset) + (char *)cc; if (remain_len < offsetof(struct create_context, Buffer))
val = le16_to_cpu(cc->NameLength);
if (val < 4)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (memcmp(name, tag, val) == 0)
return cc;
next = le32_to_cpu(cc->Next); next = le32_to_cpu(cc->Next);
name_off = le16_to_cpu(cc->NameOffset);
name_len = le16_to_cpu(cc->NameLength);
value_off = le16_to_cpu(cc->DataOffset);
value_len = le32_to_cpu(cc->DataLength);
cc_len = next ? next : remain_len;
if ((next & 0x7) != 0 ||
next > remain_len ||
name_off != offsetof(struct create_context, Buffer) ||
name_len < 4 ||
name_off + name_len > cc_len ||
(value_off & 0x7) != 0 ||
(value_off && (value_off < name_off + name_len)) ||
((u64)value_off + value_len > cc_len))
return ERR_PTR(-EINVAL);
name = (char *)cc + name_off;
if (memcmp(name, tag, name_len) == 0)
return cc;
remain_len -= next;
} while (next != 0); } while (next != 0);
return NULL; return NULL;
......
This diff is collapsed.
...@@ -1464,6 +1464,15 @@ struct smb2_file_all_info { /* data block encoding of response to level 18 */ ...@@ -1464,6 +1464,15 @@ struct smb2_file_all_info { /* data block encoding of response to level 18 */
char FileName[1]; char FileName[1];
} __packed; /* level 18 Query */ } __packed; /* level 18 Query */
struct smb2_file_basic_info { /* data block encoding of response to level 18 */
__le64 CreationTime; /* Beginning of FILE_BASIC_INFO equivalent */
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le32 Attributes;
__u32 Pad1; /* End of FILE_BASIC_INFO_INFO equivalent */
} __packed;
struct smb2_file_alt_name_info { struct smb2_file_alt_name_info {
__le32 FileNameLength; __le32 FileNameLength;
char FileName[0]; char FileName[0];
......
...@@ -155,20 +155,7 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work) ...@@ -155,20 +155,7 @@ int ksmbd_verify_smb_message(struct ksmbd_work *work)
*/ */
bool ksmbd_smb_request(struct ksmbd_conn *conn) bool ksmbd_smb_request(struct ksmbd_conn *conn)
{ {
int type = *(char *)conn->request_buf; return conn->request_buf[0] == 0;
switch (type) {
case RFC1002_SESSION_MESSAGE:
/* Regular SMB request */
return true;
case RFC1002_SESSION_KEEP_ALIVE:
ksmbd_debug(SMB, "RFC 1002 session keep alive\n");
break;
default:
ksmbd_debug(SMB, "RFC 1002 unknown request type 0x%x\n", type);
}
return false;
} }
static bool supported_protocol(int idx) static bool supported_protocol(int idx)
...@@ -182,10 +169,12 @@ static bool supported_protocol(int idx) ...@@ -182,10 +169,12 @@ static bool supported_protocol(int idx)
idx <= server_conf.max_protocol); idx <= server_conf.max_protocol);
} }
static char *next_dialect(char *dialect, int *next_off) static char *next_dialect(char *dialect, int *next_off, int bcount)
{ {
dialect = dialect + *next_off; dialect = dialect + *next_off;
*next_off = strlen(dialect); *next_off = strnlen(dialect, bcount);
if (dialect[*next_off] != '\0')
return NULL;
return dialect; return dialect;
} }
...@@ -200,7 +189,9 @@ static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count) ...@@ -200,7 +189,9 @@ static int ksmbd_lookup_dialect_by_name(char *cli_dialects, __le16 byte_count)
dialect = cli_dialects; dialect = cli_dialects;
bcount = le16_to_cpu(byte_count); bcount = le16_to_cpu(byte_count);
do { do {
dialect = next_dialect(dialect, &next); dialect = next_dialect(dialect, &next, bcount);
if (!dialect)
break;
ksmbd_debug(SMB, "client requested dialect %s\n", ksmbd_debug(SMB, "client requested dialect %s\n",
dialect); dialect);
if (!strcmp(dialect, smb1_protos[i].name)) { if (!strcmp(dialect, smb1_protos[i].name)) {
...@@ -248,13 +239,22 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count) ...@@ -248,13 +239,22 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
static int ksmbd_negotiate_smb_dialect(void *buf) static int ksmbd_negotiate_smb_dialect(void *buf)
{ {
__le32 proto; int smb_buf_length = get_rfc1002_len(buf);
__le32 proto = ((struct smb2_hdr *)buf)->ProtocolId;
proto = ((struct smb2_hdr *)buf)->ProtocolId;
if (proto == SMB2_PROTO_NUMBER) { if (proto == SMB2_PROTO_NUMBER) {
struct smb2_negotiate_req *req; struct smb2_negotiate_req *req;
int smb2_neg_size =
offsetof(struct smb2_negotiate_req, Dialects) - 4;
req = (struct smb2_negotiate_req *)buf; req = (struct smb2_negotiate_req *)buf;
if (smb2_neg_size > smb_buf_length)
goto err_out;
if (smb2_neg_size + le16_to_cpu(req->DialectCount) * sizeof(__le16) >
smb_buf_length)
goto err_out;
return ksmbd_lookup_dialect_by_id(req->Dialects, return ksmbd_lookup_dialect_by_id(req->Dialects,
req->DialectCount); req->DialectCount);
} }
...@@ -264,10 +264,19 @@ static int ksmbd_negotiate_smb_dialect(void *buf) ...@@ -264,10 +264,19 @@ static int ksmbd_negotiate_smb_dialect(void *buf)
struct smb_negotiate_req *req; struct smb_negotiate_req *req;
req = (struct smb_negotiate_req *)buf; req = (struct smb_negotiate_req *)buf;
if (le16_to_cpu(req->ByteCount) < 2)
goto err_out;
if (offsetof(struct smb_negotiate_req, DialectsArray) - 4 +
le16_to_cpu(req->ByteCount) > smb_buf_length) {
goto err_out;
}
return ksmbd_lookup_dialect_by_name(req->DialectsArray, return ksmbd_lookup_dialect_by_name(req->DialectsArray,
req->ByteCount); req->ByteCount);
} }
err_out:
return BAD_PROT_ID; return BAD_PROT_ID;
} }
......
...@@ -48,14 +48,6 @@ ...@@ -48,14 +48,6 @@
#define CIFS_DEFAULT_IOSIZE (64 * 1024) #define CIFS_DEFAULT_IOSIZE (64 * 1024)
#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */ #define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
/* RFC 1002 session packet types */
#define RFC1002_SESSION_MESSAGE 0x00
#define RFC1002_SESSION_REQUEST 0x81
#define RFC1002_POSITIVE_SESSION_RESPONSE 0x82
#define RFC1002_NEGATIVE_SESSION_RESPONSE 0x83
#define RFC1002_RETARGET_SESSION_RESPONSE 0x84
#define RFC1002_SESSION_KEEP_ALIVE 0x85
/* Responses when opening a file. */ /* Responses when opening a file. */
#define F_SUPERSEDED 0 #define F_SUPERSEDED 0
#define F_OPENED 1 #define F_OPENED 1
......
...@@ -380,7 +380,7 @@ static void parse_dacl(struct user_namespace *user_ns, ...@@ -380,7 +380,7 @@ static void parse_dacl(struct user_namespace *user_ns,
{ {
int i, ret; int i, ret;
int num_aces = 0; int num_aces = 0;
int acl_size; unsigned int acl_size;
char *acl_base; char *acl_base;
struct smb_ace **ppace; struct smb_ace **ppace;
struct posix_acl_entry *cf_pace, *cf_pdace; struct posix_acl_entry *cf_pace, *cf_pdace;
...@@ -392,7 +392,7 @@ static void parse_dacl(struct user_namespace *user_ns, ...@@ -392,7 +392,7 @@ static void parse_dacl(struct user_namespace *user_ns,
return; return;
/* validate that we do not go past end of acl */ /* validate that we do not go past end of acl */
if (end_of_acl <= (char *)pdacl || if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) ||
end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
pr_err("ACL too small to parse DACL\n"); pr_err("ACL too small to parse DACL\n");
return; return;
...@@ -431,8 +431,22 @@ static void parse_dacl(struct user_namespace *user_ns, ...@@ -431,8 +431,22 @@ static void parse_dacl(struct user_namespace *user_ns,
* user/group/other have no permissions * user/group/other have no permissions
*/ */
for (i = 0; i < num_aces; ++i) { for (i = 0; i < num_aces; ++i) {
if (end_of_acl - acl_base < acl_size)
break;
ppace[i] = (struct smb_ace *)(acl_base + acl_size); ppace[i] = (struct smb_ace *)(acl_base + acl_size);
acl_base = (char *)ppace[i]; acl_base = (char *)ppace[i];
acl_size = offsetof(struct smb_ace, sid) +
offsetof(struct smb_sid, sub_auth);
if (end_of_acl - acl_base < acl_size ||
ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
(end_of_acl - acl_base <
acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
(le16_to_cpu(ppace[i]->size) <
acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth))
break;
acl_size = le16_to_cpu(ppace[i]->size); acl_size = le16_to_cpu(ppace[i]->size);
ppace[i]->access_req = ppace[i]->access_req =
smb_map_generic_desired_access(ppace[i]->access_req); smb_map_generic_desired_access(ppace[i]->access_req);
...@@ -807,6 +821,9 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, ...@@ -807,6 +821,9 @@ int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
if (!pntsd) if (!pntsd)
return -EIO; return -EIO;
if (acl_len < sizeof(struct smb_ntsd))
return -EINVAL;
owner_sid_ptr = (struct smb_sid *)((char *)pntsd + owner_sid_ptr = (struct smb_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset)); le32_to_cpu(pntsd->osidoffset));
group_sid_ptr = (struct smb_sid *)((char *)pntsd + group_sid_ptr = (struct smb_sid *)((char *)pntsd +
......
...@@ -215,7 +215,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk) ...@@ -215,7 +215,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk)
* ksmbd_kthread_fn() - listen to new SMB connections and callback server * ksmbd_kthread_fn() - listen to new SMB connections and callback server
* @p: arguments to forker thread * @p: arguments to forker thread
* *
* Return: Returns a task_struct or ERR_PTR * Return: 0 on success, error number otherwise
*/ */
static int ksmbd_kthread_fn(void *p) static int ksmbd_kthread_fn(void *p)
{ {
...@@ -387,7 +387,7 @@ static void tcp_destroy_socket(struct socket *ksmbd_socket) ...@@ -387,7 +387,7 @@ static void tcp_destroy_socket(struct socket *ksmbd_socket)
/** /**
* create_socket - create socket for ksmbd/0 * create_socket - create socket for ksmbd/0
* *
* Return: Returns a task_struct or ERR_PTR * Return: 0 on success, error number otherwise
*/ */
static int create_socket(struct interface *iface) static int create_socket(struct interface *iface)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment