[libvirt] [PATCH v2] qemu: fix msg could be a wild pointer in qemuMonitorIOProcess()
zhuweilun
zhuweilun at huawei.com
Wed Jun 20 08:46:08 UTC 2018
Hi Peter,
Thanks a lot for your review! I'm so sorry for the delay, please see my reply below.
在 2018/6/8 16:05, Peter Krempa 写道:
> On Thu, Jun 07, 2018 at 15:09:58 +0800, Weilun Zhu wrote:
>> As qemuMonitorJSONIOProcess() will unlock the qemu monitor, there is
>> some extreme situation, eg qemu send message to monitor twice in a short
>> time, where the local viriable 'msg' of qemuMonitorIOProcess() could be
>
> I'd write this as:
>
> As qemuMonitorJSONIOProcess will call qemuMonitorJSONIOProcessEvent
> which unlocks the monitor mutex
>
All right, it's much better.
>> a wild point:
>>
>> 1. qemuMonitorSend() assign mon->msg to parameter 'msg', which is alse a
>> local variable of its caller qemuMonitorJSONCommandWithFd(), cause
>> eventloop to send message to monitor, then wait condition.
>> 2. qemu send message to monitor for the first time immediately.
>> 3. qemuMonitorIOProcess() is called, then wake up the qemuMonitorSend()
>> thread, but the qemuMonitorSend() thread stuck for a while as cpu pressure
>> or some other reasons,, which means the qemu monitor is still unlocked.
>> 4. qemu send event message to monitor for the second time,
>> such as RTC_CHANGE event
>> 5. qemuMonitorIOProcess() is called, the local viriable 'msg' is
>> assigned to mon->msg.
>> 6. qemuMonitorIOProcess() call qemuMonitorJSONIOProcess() to deal with
>> the qemu event.
>> 7. qemuMonitorJSONIOProcess() unlock the qemu monitor in the macro
>> 'QEMU_MONITOR_CALLBACK', then qemuMonitorSend() thread get the mutex
>> and free the mon->msg, assign mon->msg to NULL.
>
> This is okay
>
>>
>> so the local viriable 'msg' of qemuMonitorIOProcess() is a wild pointer
>> now.
>>
>> AFAIK, it is not harmful to call again virCondBroadcast() while msg is a
>> wild pointer, but just in case, we fix it in this patch.
>
> These two paragraphs can be dropped.
>
>
> Also we now require that the authors of patches agree to the
> 'Developer's certificate of origin' ( https://developercertificate.org/
> ). You express your agreement by adding a 'Signed-off-by' line. Without
> that, your patch can't be pushed.
>
>
OK, I did not notice that, I will add it.
>> ---
>> src/qemu/qemu_monitor.c | 8 ++++++++
>> 1 file changed, 8 insertions(+)
>>
>> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
>> index 215135aa3e..a4b8572e24 100644
>> --- a/src/qemu/qemu_monitor.c
>> +++ b/src/qemu/qemu_monitor.c
>> @@ -463,6 +463,14 @@ qemuMonitorIOProcess(qemuMonitorPtr mon)
>> #if DEBUG_IO
>> VIR_DEBUG("Process done %d used %d", (int)mon->bufferOffset, len);
>> #endif
>> +
>> + /* As the monitor mutex was unlocked in qemuMonitorJSONIOProcess()
>> + * while dealing with qemu event, mon->msg could be changed,
>> + * thus we re-acquire the msg here */
>> + msg = NULL;
>
> This part is okay (except for the last line if you apply what I suggest
> bellow)
>
>> + if (mon->msg && mon->msg->txOffset == mon->msg->txLength) {
>> + msg = mon->msg;
>
> But this condition can be merged with the one below.
>
>> +
>> if (msg && msg->finished)
>
> It should look like:
> if (mon->msg && mon->msg->finished)
> virCondBroadcast(&mon->notify);
>
> The part with the txOffset is not necessary any more, since
> msg->finished will be set only when that was true. The main reasoning is
> that we don't really need to extract msg at this point any more.
>
>
OK, your suggest is better, and I will change the comment like following:
"
- if (msg && msg->finished)
+
+ /* As the monitor mutex was unlocked in qemuMonitorJSONIOProcess()
+ * while dealing with qemu event, mon->msg could be changed which
+ * means the above 'msg' may be invalid, thus we use 'mon->msg' here */
+ if (mon->msg && mon->msg->finished)
"
>> virCondBroadcast(&mon->notify);
>> return len;
>> --
>> 2.18.0.rc1
>>
>> --
>> libvir-list mailing list
>> libvir-list at redhat.com
>> https://www.redhat.com/mailman/listinfo/libvir-list
More information about the libvir-list
mailing list