Commit e2065b8c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '6.4-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd

Pull ksmbd server fixes from Steve French:

 - two fixes for incorrect SMB3 message validation (one for client which
   uses 8 byte padding, and one for empty bcc)

 - two fixes for out of bounds bugs: one for username offset checks (in
   session setup) and the other for create context name length checks in
   open requests

* tag '6.4-rc2-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: smb2: Allow messages padded to 8byte boundary
  ksmbd: allocate one more byte for implied bcc[0]
  ksmbd: fix wrong UserName check in session_user
  ksmbd: fix global-out-of-bounds in smb2_find_context_vals
parents 0c9dcf12 e7b8b8ed
...@@ -351,7 +351,8 @@ int ksmbd_conn_handler_loop(void *p) ...@@ -351,7 +351,8 @@ int ksmbd_conn_handler_loop(void *p)
break; break;
/* 4 for rfc1002 length field */ /* 4 for rfc1002 length field */
size = pdu_size + 4; /* 1 for implied bcc[0] */
size = pdu_size + 4 + 1;
conn->request_buf = kvmalloc(size, GFP_KERNEL); conn->request_buf = kvmalloc(size, GFP_KERNEL);
if (!conn->request_buf) if (!conn->request_buf)
break; break;
......
...@@ -1449,11 +1449,12 @@ struct lease_ctx_info *parse_lease_state(void *open_req) ...@@ -1449,11 +1449,12 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
* smb2_find_context_vals() - find a particular context info in open request * smb2_find_context_vals() - find a particular context info in open request
* @open_req: buffer containing smb2 file open(create) request * @open_req: buffer containing smb2 file open(create) request
* @tag: context name to search for * @tag: context name to search for
* @tag_len: the length of tag
* *
* Return: pointer to requested context, NULL if @str context not found * Return: pointer to requested context, NULL if @str context not found
* or error pointer if name length is invalid. * or error pointer if name length is invalid.
*/ */
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, int tag_len)
{ {
struct create_context *cc; struct create_context *cc;
unsigned int next = 0; unsigned int next = 0;
...@@ -1492,7 +1493,7 @@ struct create_context *smb2_find_context_vals(void *open_req, const char *tag) ...@@ -1492,7 +1493,7 @@ struct create_context *smb2_find_context_vals(void *open_req, const char *tag)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
name = (char *)cc + name_off; name = (char *)cc + name_off;
if (memcmp(name, tag, name_len) == 0) if (name_len == tag_len && !memcmp(name, tag, name_len))
return cc; return cc;
remain_len -= next; remain_len -= next;
......
...@@ -118,7 +118,7 @@ void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp); ...@@ -118,7 +118,7 @@ void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp);
void create_mxac_rsp_buf(char *cc, int maximal_access); void create_mxac_rsp_buf(char *cc, int maximal_access);
void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id); void create_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id);
void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp); void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp);
struct create_context *smb2_find_context_vals(void *open_req, const char *str); struct create_context *smb2_find_context_vals(void *open_req, const char *tag, int tag_len);
struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn, struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn,
char *lease_key); char *lease_key);
int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
......
...@@ -416,8 +416,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) ...@@ -416,8 +416,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
/* /*
* Allow a message that padded to 8byte boundary. * Allow a message that padded to 8byte boundary.
* Linux 4.19.217 with smb 3.0.2 are sometimes
* sending messages where the cls_len is exactly
* 8 bytes less than len.
*/ */
if (clc_len < len && (len - clc_len) < 8) if (clc_len < len && (len - clc_len) <= 8)
goto validate_credit; goto validate_credit;
pr_err_ratelimited( pr_err_ratelimited(
......
...@@ -1356,7 +1356,7 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn, ...@@ -1356,7 +1356,7 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
struct authenticate_message *authblob; struct authenticate_message *authblob;
struct ksmbd_user *user; struct ksmbd_user *user;
char *name; char *name;
unsigned int auth_msg_len, name_off, name_len, secbuf_len; unsigned int name_off, name_len, secbuf_len;
secbuf_len = le16_to_cpu(req->SecurityBufferLength); secbuf_len = le16_to_cpu(req->SecurityBufferLength);
if (secbuf_len < sizeof(struct authenticate_message)) { if (secbuf_len < sizeof(struct authenticate_message)) {
...@@ -1366,9 +1366,8 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn, ...@@ -1366,9 +1366,8 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
authblob = user_authblob(conn, req); authblob = user_authblob(conn, req);
name_off = le32_to_cpu(authblob->UserName.BufferOffset); name_off = le32_to_cpu(authblob->UserName.BufferOffset);
name_len = le16_to_cpu(authblob->UserName.Length); name_len = le16_to_cpu(authblob->UserName.Length);
auth_msg_len = le16_to_cpu(req->SecurityBufferOffset) + secbuf_len;
if (auth_msg_len < (u64)name_off + name_len) if (secbuf_len < (u64)name_off + name_len)
return NULL; return NULL;
name = smb_strndup_from_utf16((const char *)authblob + name_off, name = smb_strndup_from_utf16((const char *)authblob + name_off,
...@@ -2464,7 +2463,7 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work, ...@@ -2464,7 +2463,7 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work,
return -ENOENT; return -ENOENT;
/* Parse SD BUFFER create contexts */ /* Parse SD BUFFER create contexts */
context = smb2_find_context_vals(req, SMB2_CREATE_SD_BUFFER); context = smb2_find_context_vals(req, SMB2_CREATE_SD_BUFFER, 4);
if (!context) if (!context)
return -ENOENT; return -ENOENT;
else if (IS_ERR(context)) else if (IS_ERR(context))
...@@ -2666,7 +2665,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2666,7 +2665,7 @@ int smb2_open(struct ksmbd_work *work)
if (req->CreateContextsOffset) { if (req->CreateContextsOffset) {
/* Parse non-durable handle create contexts */ /* Parse non-durable handle create contexts */
context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER); context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4);
if (IS_ERR(context)) { if (IS_ERR(context)) {
rc = PTR_ERR(context); rc = PTR_ERR(context);
goto err_out1; goto err_out1;
...@@ -2686,7 +2685,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2686,7 +2685,7 @@ int smb2_open(struct ksmbd_work *work)
} }
context = smb2_find_context_vals(req, context = smb2_find_context_vals(req,
SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST); SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4);
if (IS_ERR(context)) { if (IS_ERR(context)) {
rc = PTR_ERR(context); rc = PTR_ERR(context);
goto err_out1; goto err_out1;
...@@ -2697,7 +2696,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2697,7 +2696,7 @@ int smb2_open(struct ksmbd_work *work)
} }
context = smb2_find_context_vals(req, context = smb2_find_context_vals(req,
SMB2_CREATE_TIMEWARP_REQUEST); SMB2_CREATE_TIMEWARP_REQUEST, 4);
if (IS_ERR(context)) { if (IS_ERR(context)) {
rc = PTR_ERR(context); rc = PTR_ERR(context);
goto err_out1; goto err_out1;
...@@ -2709,7 +2708,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2709,7 +2708,7 @@ int smb2_open(struct ksmbd_work *work)
if (tcon->posix_extensions) { if (tcon->posix_extensions) {
context = smb2_find_context_vals(req, context = smb2_find_context_vals(req,
SMB2_CREATE_TAG_POSIX); SMB2_CREATE_TAG_POSIX, 16);
if (IS_ERR(context)) { if (IS_ERR(context)) {
rc = PTR_ERR(context); rc = PTR_ERR(context);
goto err_out1; goto err_out1;
...@@ -3107,7 +3106,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -3107,7 +3106,7 @@ int smb2_open(struct ksmbd_work *work)
struct create_alloc_size_req *az_req; struct create_alloc_size_req *az_req;
az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req, az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req,
SMB2_CREATE_ALLOCATION_SIZE); SMB2_CREATE_ALLOCATION_SIZE, 4);
if (IS_ERR(az_req)) { if (IS_ERR(az_req)) {
rc = PTR_ERR(az_req); rc = PTR_ERR(az_req);
goto err_out; goto err_out;
...@@ -3134,7 +3133,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -3134,7 +3133,7 @@ int smb2_open(struct ksmbd_work *work)
err); err);
} }
context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID); context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4);
if (IS_ERR(context)) { if (IS_ERR(context)) {
rc = PTR_ERR(context); rc = PTR_ERR(context);
goto err_out; goto err_out;
......
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