diff mbox series

[v3,2/3] util/main-loop: Avoid adding the same HANDLE twice

Message ID 20220824085231.1630804-2-bmeng.cn@gmail.com (mailing list archive)
State New, archived
Headers show
Series [v3,1/3] util/main-loop: Fix maximum number of wait objects for win32 | expand

Commit Message

Bin Meng Aug. 24, 2022, 8:52 a.m. UTC
From: Bin Meng <bin.meng@windriver.com>

Fix the logic in qemu_add_wait_object() to avoid adding the same
HANDLE twice, as the behavior is undefined when passing an array
that contains same HANDLEs to WaitForMultipleObjects() API.

Signed-off-by: Bin Meng <bin.meng@windriver.com>
---

Changes in v3:
- new patch: avoid adding the same HANDLE twice

 include/qemu/main-loop.h |  2 ++
 util/main-loop.c         | 10 ++++++++++
 2 files changed, 12 insertions(+)

Comments

Philippe Mathieu-Daudé Aug. 30, 2022, 12:22 p.m. UTC | #1
On 24/8/22 10:52, Bin Meng wrote:
> From: Bin Meng <bin.meng@windriver.com>
> 
> Fix the logic in qemu_add_wait_object() to avoid adding the same
> HANDLE twice, as the behavior is undefined when passing an array
> that contains same HANDLEs to WaitForMultipleObjects() API.
> 
> Signed-off-by: Bin Meng <bin.meng@windriver.com>
> ---
> 
> Changes in v3:
> - new patch: avoid adding the same HANDLE twice
> 
>   include/qemu/main-loop.h |  2 ++
>   util/main-loop.c         | 10 ++++++++++
>   2 files changed, 12 insertions(+)

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Daniel P. Berrangé Oct. 19, 2022, 8:32 a.m. UTC | #2
On Wed, Aug 24, 2022 at 04:52:30PM +0800, Bin Meng wrote:
> From: Bin Meng <bin.meng@windriver.com>
> 
> Fix the logic in qemu_add_wait_object() to avoid adding the same
> HANDLE twice, as the behavior is undefined when passing an array
> that contains same HANDLEs to WaitForMultipleObjects() API.

Have you encountered this problem in the real world, or is this
just a flaw you spotted through code inspection ?

Essentially I'm wondering if there's any known caller that is
making this mistake of adding it twice ?

> 
> Signed-off-by: Bin Meng <bin.meng@windriver.com>
> ---
> 
> Changes in v3:
> - new patch: avoid adding the same HANDLE twice
> 
>  include/qemu/main-loop.h |  2 ++
>  util/main-loop.c         | 10 ++++++++++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
> index c50d1b7e3a..db8d380550 100644
> --- a/include/qemu/main-loop.h
> +++ b/include/qemu/main-loop.h
> @@ -157,6 +157,8 @@ typedef void WaitObjectFunc(void *opaque);
>   * in the main loop's calls to WaitForMultipleObjects.  When the handle
>   * is in a signaled state, QEMU will call @func.
>   *
> + * If the same HANDLE is added twice, this function returns -1.
> + *
>   * @handle: The Windows handle to be observed.
>   * @func: A function to be called when @handle is in a signaled state.
>   * @opaque: A pointer-size value that is passed to @func.
> diff --git a/util/main-loop.c b/util/main-loop.c
> index cb018dc33c..dae33a8daf 100644
> --- a/util/main-loop.c
> +++ b/util/main-loop.c
> @@ -373,10 +373,20 @@ static WaitObjects wait_objects = {0};
>  
>  int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
>  {
> +    int i;
>      WaitObjects *w = &wait_objects;
> +
>      if (w->num >= MAXIMUM_WAIT_OBJECTS) {
>          return -1;
>      }
> +
> +    for (i = 0; i < w->num; i++) {
> +        /* check if the same handle is added twice */
> +        if (w->events[i] == handle) {
> +            return -1;
> +        }
> +    }
> +
>      w->events[w->num] = handle;
>      w->func[w->num] = func;
>      w->opaque[w->num] = opaque;
> -- 
> 2.34.1
> 
> 

With regards,
Daniel
Bin Meng Oct. 19, 2022, 9:07 a.m. UTC | #3
Hi Daniel,

On Wed, Oct 19, 2022 at 4:32 PM Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> On Wed, Aug 24, 2022 at 04:52:30PM +0800, Bin Meng wrote:
> > From: Bin Meng <bin.meng@windriver.com>
> >
> > Fix the logic in qemu_add_wait_object() to avoid adding the same
> > HANDLE twice, as the behavior is undefined when passing an array
> > that contains same HANDLEs to WaitForMultipleObjects() API.
>
> Have you encountered this problem in the real world, or is this
> just a flaw you spotted through code inspection ?

No. This was noticed as part of debugging [1] and code inspection was
done for all possible suspicious places.

[1] https://lore.kernel.org/qemu-devel/20221006151927.2079583-17-bmeng.cn@gmail.com/

>
> Essentially I'm wondering if there's any known caller that is
> making this mistake of adding it twice ?

No known caller at this call chain. But there is another in the QIO
socket channel APIs that may add the same handle twice, fortunately
that scenario is handled properly in the GLib internally.

>
> >
> > Signed-off-by: Bin Meng <bin.meng@windriver.com>
> > ---
> >
> > Changes in v3:
> > - new patch: avoid adding the same HANDLE twice
> >
> >  include/qemu/main-loop.h |  2 ++
> >  util/main-loop.c         | 10 ++++++++++
> >  2 files changed, 12 insertions(+)
> >

Regards,
Bin
diff mbox series

Patch

diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h
index c50d1b7e3a..db8d380550 100644
--- a/include/qemu/main-loop.h
+++ b/include/qemu/main-loop.h
@@ -157,6 +157,8 @@  typedef void WaitObjectFunc(void *opaque);
  * in the main loop's calls to WaitForMultipleObjects.  When the handle
  * is in a signaled state, QEMU will call @func.
  *
+ * If the same HANDLE is added twice, this function returns -1.
+ *
  * @handle: The Windows handle to be observed.
  * @func: A function to be called when @handle is in a signaled state.
  * @opaque: A pointer-size value that is passed to @func.
diff --git a/util/main-loop.c b/util/main-loop.c
index cb018dc33c..dae33a8daf 100644
--- a/util/main-loop.c
+++ b/util/main-loop.c
@@ -373,10 +373,20 @@  static WaitObjects wait_objects = {0};
 
 int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
 {
+    int i;
     WaitObjects *w = &wait_objects;
+
     if (w->num >= MAXIMUM_WAIT_OBJECTS) {
         return -1;
     }
+
+    for (i = 0; i < w->num; i++) {
+        /* check if the same handle is added twice */
+        if (w->events[i] == handle) {
+            return -1;
+        }
+    }
+
     w->events[w->num] = handle;
     w->func[w->num] = func;
     w->opaque[w->num] = opaque;