]> git.itanic.dy.fi Git - linux-stable/commitdiff
ksmbd: fix global-out-of-bounds in smb2_find_context_vals
authorChih-Yen Chang <cc85nod@gmail.com>
Sun, 14 May 2023 03:05:05 +0000 (12:05 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 May 2023 16:30:21 +0000 (17:30 +0100)
commit 02f76c401d17e409ed45bf7887148fcc22c93c85 upstream.

Add tag_len argument in smb2_find_context_vals() to avoid out-of-bound
read when create_context's name_len is larger than tag length.

[    7.995411] ==================================================================
[    7.995866] BUG: KASAN: global-out-of-bounds in memcmp+0x83/0xa0
[    7.996248] Read of size 8 at addr ffffffff8258d940 by task kworker/0:0/7
...
[    7.998191] Call Trace:
[    7.998358]  <TASK>
[    7.998503]  dump_stack_lvl+0x33/0x50
[    7.998743]  print_report+0xcc/0x620
[    7.999458]  kasan_report+0xae/0xe0
[    7.999895]  kasan_check_range+0x35/0x1b0
[    8.000152]  memcmp+0x83/0xa0
[    8.000347]  smb2_find_context_vals+0xf7/0x1e0
[    8.000635]  smb2_open+0x1df2/0x43a0
[    8.006398]  handle_ksmbd_work+0x274/0x810
[    8.006666]  process_one_work+0x419/0x760
[    8.006922]  worker_thread+0x2a2/0x6f0
[    8.007429]  kthread+0x160/0x190
[    8.007946]  ret_from_fork+0x1f/0x30
[    8.008181]  </TASK>

Cc: stable@vger.kernel.org
Signed-off-by: Chih-Yen Chang <cc85nod@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/ksmbd/oplock.c
fs/ksmbd/oplock.h
fs/ksmbd/smb2pdu.c

index 2e54ded4d92c21f254659326fc54f2d20dcedd3d..6d1ccb99989398f56d859a8088341f5adb122d52 100644 (file)
@@ -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
  * @open_req:  buffer containing smb2 file open(create) request
  * @tag:       context name to search for
+ * @tag_len:   the length of tag
  *
  * Return:     pointer to requested context, NULL if @str context not found
  *             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;
        unsigned int next = 0;
@@ -1492,7 +1493,7 @@ struct create_context *smb2_find_context_vals(void *open_req, const char *tag)
                        return ERR_PTR(-EINVAL);
 
                name = (char *)cc + name_off;
-               if (memcmp(name, tag, name_len) == 0)
+               if (name_len == tag_len && !memcmp(name, tag, name_len))
                        return cc;
 
                remain_len -= next;
index 09753448f7798de7ff5af0bc1aa38096861d05b5..4b0fe6da76940f54a915cb4bd20d3ce67539bd3e 100644 (file)
@@ -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_disk_id_rsp_buf(char *cc, __u64 file_id, __u64 vol_id);
 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,
                                          char *lease_key);
 int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
index c652cea7f48041a25ae4d331042c052588f2a864..cca593e340967eff626b9d42b53300a40fb85475 100644 (file)
@@ -2491,7 +2491,7 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work,
                return -ENOENT;
 
        /* 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)
                return -ENOENT;
        else if (IS_ERR(context))
@@ -2693,7 +2693,7 @@ int smb2_open(struct ksmbd_work *work)
 
        if (req->CreateContextsOffset) {
                /* 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)) {
                        rc = PTR_ERR(context);
                        goto err_out1;
@@ -2713,7 +2713,7 @@ int smb2_open(struct ksmbd_work *work)
                }
 
                context = smb2_find_context_vals(req,
-                                                SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST);
+                                                SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4);
                if (IS_ERR(context)) {
                        rc = PTR_ERR(context);
                        goto err_out1;
@@ -2724,7 +2724,7 @@ int smb2_open(struct ksmbd_work *work)
                }
 
                context = smb2_find_context_vals(req,
-                                                SMB2_CREATE_TIMEWARP_REQUEST);
+                                                SMB2_CREATE_TIMEWARP_REQUEST, 4);
                if (IS_ERR(context)) {
                        rc = PTR_ERR(context);
                        goto err_out1;
@@ -2736,7 +2736,7 @@ int smb2_open(struct ksmbd_work *work)
 
                if (tcon->posix_extensions) {
                        context = smb2_find_context_vals(req,
-                                                        SMB2_CREATE_TAG_POSIX);
+                                                        SMB2_CREATE_TAG_POSIX, 16);
                        if (IS_ERR(context)) {
                                rc = PTR_ERR(context);
                                goto err_out1;
@@ -3135,7 +3135,7 @@ int smb2_open(struct ksmbd_work *work)
                struct create_alloc_size_req *az_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)) {
                        rc = PTR_ERR(az_req);
                        goto err_out;
@@ -3162,7 +3162,7 @@ int smb2_open(struct ksmbd_work *work)
                                            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)) {
                        rc = PTR_ERR(context);
                        goto err_out;