All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: Igor Mammedov <imammedo@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	qemu-devel@nongnu.org, Eduardo Habkost <ehabkost@redhat.com>,
	Richard Henderson <rth@twiddle.net>
Subject: Re: [PATCH v2 20/25] x86: Fix x86_cpu_new() error API violations
Date: Tue, 14 Jul 2020 11:49:50 +0200	[thread overview]
Message-ID: <87mu425su9.fsf@dusky.pond.sub.org> (raw)
In-Reply-To: <20200713175053.2dd20026@redhat.com> (Igor Mammedov's message of "Mon, 13 Jul 2020 17:50:53 +0200")

Igor Mammedov <imammedo@redhat.com> writes:

> On Fri, 26 Jun 2020 14:54:38 +0200
> Markus Armbruster <armbru@redhat.com> wrote:
>
>> Igor Mammedov <imammedo@redhat.com> writes:
>> 
>> > On Wed, 24 Jun 2020 10:37:32 +0200
>> > Markus Armbruster <armbru@redhat.com> wrote:
>> >  
>> >> The Error ** argument must be NULL, &error_abort, &error_fatal, or a
>> >> pointer to a variable containing NULL.  Passing an argument of the
>> >> latter kind twice without clearing it in between is wrong: if the
>> >> first call sets an error, it no longer points to NULL for the second
>> >> call.
>> >> 
>> >> x86_cpu_new() is wrong that way: it passes &local_err to
>> >> object_property_set_uint() without checking it, and then to
>> >> qdev_realize().  Harmless, because the former can't actually fail
>> >> here.
>> >> 
>> >> Fix by checking for failure right away.  While there, replace
>> >> qdev_realize(); object_unref() by qdev_realize_and_unref().
>> >> 
>> >> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> >> Cc: Richard Henderson <rth@twiddle.net>
>> >> Cc: Eduardo Habkost <ehabkost@redhat.com>
>> >> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>> >> ---
>> >>  hw/i386/x86.c | 12 +++---------
>> >>  1 file changed, 3 insertions(+), 9 deletions(-)
>> >> 
>> >> diff --git a/hw/i386/x86.c b/hw/i386/x86.c
>> >> index 34229b45c7..3a7029e6db 100644
>> >> --- a/hw/i386/x86.c
>> >> +++ b/hw/i386/x86.c
>> >> @@ -118,16 +118,10 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
>> >>  
>> >>  void x86_cpu_new(X86MachineState *x86ms, int64_t apic_id, Error **errp)
>> >>  {
>> >> -    Object *cpu = NULL;
>> >> -    Error *local_err = NULL;
>> >> +    Object *cpu = object_new(MACHINE(x86ms)->cpu_type);
>> >>  
>> >> -    cpu = object_new(MACHINE(x86ms)->cpu_type);
>> >> -
>> >> -    object_property_set_uint(cpu, apic_id, "apic-id", &local_err);
>> >> -    qdev_realize(DEVICE(cpu), NULL, &local_err);
>> >> -
>> >> -    object_unref(cpu);
>> >> -    error_propagate(errp, local_err);
>> >> +    object_property_set_uint(cpu, apic_id, "apic-id", &error_abort);  
>> > it may fail here if user specified wrong cpu flags, but there is nothing we can do to fix it.  
>> 
>> Really?
>> 
>> object_property_set_uint() fails when property "apic-id" doesn't exist,
>> has no ->set() method, or its ->set() fails.
>> 
>> Property "apic-id" is defined in x86_cpu_properties[] as
>> 
>>     DEFINE_PROP_UINT32("apic-id", X86CPU, apic_id, UNASSIGNED_APIC_ID),
>> 
>> This means "apic-id" exists, and its ->set() is set_uint32().  That
>> leaves only set_uint32() as possible source of failure.
>> 
>> It fails when
>> 
>> * the device is already realized: programming error
>> 
>> * the value to be stored is not an integer: object_property_set_uint()
>>   makes it one, can't fail
>> 
>> * the value is not representable as uint32_t: @api_id is declared as
>>   int64_t, but:
>> 
>>   - pc_hot_add_cpu() passes x86_cpu_apic_id_from_index(), which is
>>     uint32_t, converted to int64_t.  Can't fail.
>> 
>>   - x86_cpus_init() passes possible_cpus->cpus[i].arch_id, which is
>>     uint64_t.  Is this the "if user specified wrong cpu flags" case?
>
> looking more on it, object_property_set_uint() can't really fail

Correct.

>>   Aside: should the integer types be cleaned up?
>
> apic_id is x86 specific subset of .arch_id.
> The later is used by other targets which may need larger than 32bit integer
> (if I recall correctly virt-arm uses 64bit id). 

I trust this works and makes sense, but the implicit conversions still
give me an uneasy feeling.

>> To assess the bug's impact, we need to know when the other call in this
>> error pileup fails.  If we can make both fail, we have a crash bug.
>> Else, we have a harmless API violation.
>> 
>> Any ideas on how to make the qdev_realize() fail?
> qemu CLI case
>   QEMU -cpu qemu64,enforce,topoext
>
> legacy hotplug case:
>   QEMU -smp 1,maxcpus=2
>   (monitor) cpu-add 1
>   (monitor) cpu-add 1  <= fail

Testing:

    $ qemu-system-x86_64 -nodefaults -display none -S -monitor stdio -smp 1,maxcpus=2
    QEMU 5.0.50 monitor - type 'help' for more information
    (qemu) cpu-add 1
    cpu_add is deprecated, please use device_add instead
    (qemu) cpu-add 1
    cpu_add is deprecated, please use device_add instead
    Error: CPU[1] with APIC ID 1 exists
    (qemu) 

We're good.

    $ qemu-system-x86_64 -cpu qemu64,enforce,topoext
    qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.80000001H:ECX.topoext [bit 22]
    qemu-system-x86_64: TCG doesn't support requested features
    [Exit 1 ]

Are we good?

To finish the job in time for the freeze, I made do with this
non-assessment (commit 18d588fe1e1):

    To assess the bug's impact, we'd need to figure out how to make both
    calls fail.  Too much work for ignorant me, sorry.

Thanks!



  reply	other threads:[~2020-07-14  9:50 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-24  8:37 [PATCH v2 00/25] Error handling fixes & cleanups Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 01/25] net/virtio: Fix failover_replug_primary() return value regression Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 02/25] pci: Delete useless error_propagate() Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 03/25] Clean up some calls to ignore Error objects the right way Markus Armbruster
2020-06-24  9:02   ` Greg Kurz
2020-06-25  6:42     ` Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 04/25] tests: Use &error_abort where appropriate Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 05/25] tests: Use error_free_or_abort() " Markus Armbruster
2020-06-24 14:42   ` Eric Blake
2020-06-24  8:37 ` [PATCH v2 06/25] usb/dev-mtp: Fix Error double free after inotify failure Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 07/25] spapr: Plug minor memory leak in spapr_machine_init() Markus Armbruster
2020-06-24  9:04   ` Greg Kurz
2020-06-25  3:52   ` David Gibson
2020-06-24  8:37 ` [PATCH v2 08/25] qga: Plug unlikely memory leak in guest-set-memory-blocks Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 09/25] sd/milkymist-memcard: Plug minor memory leak in realize Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 10/25] test-util-filemonitor: Plug unlikely memory leak Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 11/25] vnc: Plug minor memory leak in vnc_display_open() Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 12/25] aspeed: Clean up roundabout error propagation Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 13/25] qdev: Drop qbus_set_bus_hotplug_handler() parameter @errp Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 14/25] qdev: Drop qbus_set_hotplug_handler() " Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 15/25] hw: Fix error API violation around object_property_set_link() Markus Armbruster
2020-06-24  8:37   ` Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 16/25] hw/arm: Drop useless object_property_set_link() error handling Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 17/25] riscv/sifive_u: Fix sifive_u_soc_realize() error API violations Markus Armbruster
2020-06-24  8:37   ` Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 18/25] riscv_hart: Fix riscv_harts_realize() " Markus Armbruster
2020-06-24  8:37   ` Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 19/25] mips/cps: Fix mips_cps_realize() " Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 20/25] x86: Fix x86_cpu_new() " Markus Armbruster
2020-06-24 14:17   ` Igor Mammedov
2020-06-24 14:20     ` Paolo Bonzini
2020-06-25  6:44       ` Markus Armbruster
2020-06-25 19:29       ` Igor Mammedov
2020-06-26 12:54     ` Markus Armbruster
2020-07-13 15:50       ` Igor Mammedov
2020-07-14  9:49         ` Markus Armbruster [this message]
2020-06-24  8:37 ` [PATCH v2 21/25] amd_iommu: Fix amdvi_realize() error API violation Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 22/25] arm/stm32f205 arm/stm32f405: Fix realize " Markus Armbruster
2020-06-24 19:17   ` Alistair Francis
2020-06-24  8:37 ` [PATCH v2 23/25] aspeed: " Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 24/25] hw/arm/armsse: Fix armsse_realize() " Markus Armbruster
2020-06-24  8:37 ` [PATCH v2 25/25] arm/{bcm2835, fsl-imx25, fsl-imx6}: Fix realize error API violations Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87mu425su9.fsf@dusky.pond.sub.org \
    --to=armbru@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.