[PATCH v3 02/13] tcg: Fix error reporting on mprotect() failure in tcg_region_init()

Markus Armbruster posted 13 patches 5 days, 7 hours ago
Maintainers: Jonathan Cameron <jonathan.cameron@huawei.com>, Fan Ni <fan.ni@samsung.com>, "Alex Bennée" <alex.bennee@linaro.org>, Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>, Dmitry Osipenko <dmitry.osipenko@collabora.com>, "Michael S. Tsirkin" <mst@redhat.com>, Gustavo Romero <gustavo.romero@linaro.org>, Jason Wang <jasowang@redhat.com>, Elena Ufimtseva <elena.ufimtseva@oracle.com>, Jagannathan Raman <jag.raman@oracle.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Markus Armbruster <armbru@redhat.com>, Michael Roth <michael.roth@amd.com>, Stefan Weil <sw@weilnetz.de>, "Daniel P. Berrangé" <berrange@redhat.com>, Steve Sistare <steven.sistare@oracle.com>, Peter Xu <peterx@redhat.com>, Fabiano Rosas <farosas@suse.de>, "Dr. David Alan Gilbert" <dave@treblig.org>, Samuel Thibault <samuel.thibault@ens-lyon.org>, Richard Henderson <richard.henderson@linaro.org>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, Stefan Hajnoczi <stefanha@redhat.com>, Fam Zheng <fam@euphon.net>
[PATCH v3 02/13] tcg: Fix error reporting on mprotect() failure in tcg_region_init()
Posted by Markus Armbruster 5 days, 7 hours ago
tcg_region_init() calls one of qemu_mprotect_rwx(),
qemu_mprotect_rw(), and mprotect(), then reports failure with
error_setg_errno(&error_fatal, errno, ...).

The use of &error_fatal is undesirable.  qapi/error.h advises:

 * Please don't error_setg(&error_fatal, ...), use error_report() and
 * exit(), because that's more obvious.

The use of errno is wrong.  qemu_mprotect_rwx() and qemu_mprotect_rw()
wrap around qemu_mprotect__osdep().  qemu_mprotect__osdep() calls
mprotect() on POSIX, VirtualProtect() on Windows, and reports failure
with error_report().  VirtualProtect() doesn't set errno.  mprotect()
does, but error_report() may clobber it.

Fix tcg_region_init() to report errors only when it calls mprotect(),
and rely on qemu_mprotect_rwx()'s and qemu_mprotect_rw()'s error
reporting otherwise.  Use error_report(), not error_setg().

Fixes: 22c6a9938f75 (tcg: Merge buffer protection and guard page protection)
Fixes: 6bc144237a85 (tcg: Use Error with alloc_code_gen_buffer)
Cc: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/region.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/tcg/region.c b/tcg/region.c
index 7ea0b37a84..2181267e48 100644
--- a/tcg/region.c
+++ b/tcg/region.c
@@ -832,13 +832,16 @@ void tcg_region_init(size_t tb_size, int splitwx, unsigned max_threads)
             } else {
 #ifdef CONFIG_POSIX
                 rc = mprotect(start, end - start, need_prot);
+                if (rc) {
+                    error_report("mprotect of jit buffer: %s",
+                                 strerror(errno));
+                }
 #else
                 g_assert_not_reached();
 #endif
             }
             if (rc) {
-                error_setg_errno(&error_fatal, errno,
-                                 "mprotect of jit buffer");
+                exit(1);
             }
         }
         if (have_prot != 0) {
-- 
2.49.0


Re: [PATCH v3 02/13] tcg: Fix error reporting on mprotect() failure in tcg_region_init()
Posted by Philippe Mathieu-Daudé 5 days, 6 hours ago
On 23/9/25 11:09, Markus Armbruster wrote:
> tcg_region_init() calls one of qemu_mprotect_rwx(),
> qemu_mprotect_rw(), and mprotect(), then reports failure with
> error_setg_errno(&error_fatal, errno, ...).
> 
> The use of &error_fatal is undesirable.  qapi/error.h advises:
> 
>   * Please don't error_setg(&error_fatal, ...), use error_report() and
>   * exit(), because that's more obvious.
> 
> The use of errno is wrong.  qemu_mprotect_rwx() and qemu_mprotect_rw()
> wrap around qemu_mprotect__osdep().  qemu_mprotect__osdep() calls
> mprotect() on POSIX, VirtualProtect() on Windows, and reports failure
> with error_report().  VirtualProtect() doesn't set errno.  mprotect()
> does, but error_report() may clobber it.
> 
> Fix tcg_region_init() to report errors only when it calls mprotect(),
> and rely on qemu_mprotect_rwx()'s and qemu_mprotect_rw()'s error
> reporting otherwise.  Use error_report(), not error_setg().
> 
> Fixes: 22c6a9938f75 (tcg: Merge buffer protection and guard page protection)
> Fixes: 6bc144237a85 (tcg: Use Error with alloc_code_gen_buffer)
> Cc: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Markus Armbruster <armbru@redhat.com>
> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   tcg/region.c | 7 +++++--
>   1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/tcg/region.c b/tcg/region.c
> index 7ea0b37a84..2181267e48 100644
> --- a/tcg/region.c
> +++ b/tcg/region.c
> @@ -832,13 +832,16 @@ void tcg_region_init(size_t tb_size, int splitwx, unsigned max_threads)
>               } else {
>   #ifdef CONFIG_POSIX
>                   rc = mprotect(start, end - start, need_prot);
> +                if (rc) {
> +                    error_report("mprotect of jit buffer: %s",
> +                                 strerror(errno));

I'm not keen on handling errors differently in the same function.

qemu_mprotect_rwx() and qemu_mprotect_rw() already print the error.

Why not add qemu_mprotect() as a simple qemu_mprotect__osdep() alias,
then call it here, also covering the non-POSIX case?
(Question for Richard, after looking at commits 22c6a9938f7 and more
  importantly 97a83753c9 -- wondering about WoA).

> +                }
>   #else
>                   g_assert_not_reached();
>   #endif
>               }
>               if (rc) {
> -                error_setg_errno(&error_fatal, errno,
> -                                 "mprotect of jit buffer");
> +                exit(1);
>               }>           }
>           if (have_prot != 0) {


Re: [PATCH v3 02/13] tcg: Fix error reporting on mprotect() failure in tcg_region_init()
Posted by Markus Armbruster 5 days, 5 hours ago
Philippe Mathieu-Daudé <philmd@linaro.org> writes:

> On 23/9/25 11:09, Markus Armbruster wrote:
>> tcg_region_init() calls one of qemu_mprotect_rwx(),
>> qemu_mprotect_rw(), and mprotect(), then reports failure with
>> error_setg_errno(&error_fatal, errno, ...).
>>
>> The use of &error_fatal is undesirable.  qapi/error.h advises:
>>
>>   * Please don't error_setg(&error_fatal, ...), use error_report() and
>>   * exit(), because that's more obvious.
>>
>> The use of errno is wrong.  qemu_mprotect_rwx() and qemu_mprotect_rw()
>> wrap around qemu_mprotect__osdep().  qemu_mprotect__osdep() calls
>> mprotect() on POSIX, VirtualProtect() on Windows, and reports failure
>> with error_report().  VirtualProtect() doesn't set errno.  mprotect()
>> does, but error_report() may clobber it.
>>
>> Fix tcg_region_init() to report errors only when it calls mprotect(),
>> and rely on qemu_mprotect_rwx()'s and qemu_mprotect_rw()'s error
>> reporting otherwise.  Use error_report(), not error_setg().
>>
>> Fixes: 22c6a9938f75 (tcg: Merge buffer protection and guard page protection)
>> Fixes: 6bc144237a85 (tcg: Use Error with alloc_code_gen_buffer)
>> Cc: Richard Henderson <richard.henderson@linaro.org>
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   tcg/region.c | 7 +++++--
>>   1 file changed, 5 insertions(+), 2 deletions(-)
>> diff --git a/tcg/region.c b/tcg/region.c
>> index 7ea0b37a84..2181267e48 100644
>> --- a/tcg/region.c
>> +++ b/tcg/region.c
>> @@ -832,13 +832,16 @@ void tcg_region_init(size_t tb_size, int splitwx, unsigned max_threads)
>>              } else {
>>  #ifdef CONFIG_POSIX
>>                  rc = mprotect(start, end - start, need_prot);
>> +                if (rc) {
>> +                    error_report("mprotect of jit buffer: %s",
>> +                                 strerror(errno));
>
> I'm not keen on handling errors differently in the same function.
>
> qemu_mprotect_rwx() and qemu_mprotect_rw() already print the error.

Yes: they call qemu_mprotect__osdep(), which uses error_report().

> Why not add qemu_mprotect() as a simple qemu_mprotect__osdep() alias,
> then call it here, also covering the non-POSIX case?
> (Question for Richard, after looking at commits 22c6a9938f7 and more
>  importantly 97a83753c9 -- wondering about WoA).

There is no commit 97a83753c9.  Do you mean a97a83753c9?

I'd like to merge this commit as is.  It's a minimal fix, and it's been
reviewed.  We can always improve on top.

>> +                }
>>  #else
>>                  g_assert_not_reached();
>>  #endif
>>              }
>>              if (rc) {
>> -                error_setg_errno(&error_fatal, errno,
>> -                                 "mprotect of jit buffer");
>> +                exit(1);
>>              }
>>           }
>>           if (have_prot != 0) {
Re: [PATCH v3 02/13] tcg: Fix error reporting on mprotect() failure in tcg_region_init()
Posted by Philippe Mathieu-Daudé 5 days, 3 hours ago
On 23/9/25 13:16, Markus Armbruster wrote:
> Philippe Mathieu-Daudé <philmd@linaro.org> writes:
> 
>> On 23/9/25 11:09, Markus Armbruster wrote:
>>> tcg_region_init() calls one of qemu_mprotect_rwx(),
>>> qemu_mprotect_rw(), and mprotect(), then reports failure with
>>> error_setg_errno(&error_fatal, errno, ...).
>>>
>>> The use of &error_fatal is undesirable.  qapi/error.h advises:
>>>
>>>    * Please don't error_setg(&error_fatal, ...), use error_report() and
>>>    * exit(), because that's more obvious.
>>>
>>> The use of errno is wrong.  qemu_mprotect_rwx() and qemu_mprotect_rw()
>>> wrap around qemu_mprotect__osdep().  qemu_mprotect__osdep() calls
>>> mprotect() on POSIX, VirtualProtect() on Windows, and reports failure
>>> with error_report().  VirtualProtect() doesn't set errno.  mprotect()
>>> does, but error_report() may clobber it.
>>>
>>> Fix tcg_region_init() to report errors only when it calls mprotect(),
>>> and rely on qemu_mprotect_rwx()'s and qemu_mprotect_rw()'s error
>>> reporting otherwise.  Use error_report(), not error_setg().
>>>
>>> Fixes: 22c6a9938f75 (tcg: Merge buffer protection and guard page protection)
>>> Fixes: 6bc144237a85 (tcg: Use Error with alloc_code_gen_buffer)
>>> Cc: Richard Henderson <richard.henderson@linaro.org>
>>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>>> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
>>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>>> ---
>>>    tcg/region.c | 7 +++++--
>>>    1 file changed, 5 insertions(+), 2 deletions(-)
>>> diff --git a/tcg/region.c b/tcg/region.c
>>> index 7ea0b37a84..2181267e48 100644
>>> --- a/tcg/region.c
>>> +++ b/tcg/region.c
>>> @@ -832,13 +832,16 @@ void tcg_region_init(size_t tb_size, int splitwx, unsigned max_threads)
>>>               } else {
>>>   #ifdef CONFIG_POSIX
>>>                   rc = mprotect(start, end - start, need_prot);
>>> +                if (rc) {
>>> +                    error_report("mprotect of jit buffer: %s",
>>> +                                 strerror(errno));
>>
>> I'm not keen on handling errors differently in the same function.
>>
>> qemu_mprotect_rwx() and qemu_mprotect_rw() already print the error.
> 
> Yes: they call qemu_mprotect__osdep(), which uses error_report().
> 
>> Why not add qemu_mprotect() as a simple qemu_mprotect__osdep() alias,
>> then call it here, also covering the non-POSIX case?
>> (Question for Richard, after looking at commits 22c6a9938f7 and more
>>   importantly 97a83753c9 -- wondering about WoA).
> 
> There is no commit 97a83753c9.  Do you mean a97a83753c9?

Yes.

> I'd like to merge this commit as is.  It's a minimal fix, and it's been
> reviewed.  We can always improve on top.

Right (we'd need to map non-POSIX protection bits anyway).

No objection!