Eduardo Habkost <ehabk...@redhat.com> writes: > Currently it is very easy to crash QEMU by issuing an object-add command > using an abstract class or a class that doesn't support > TYPE_USER_CREATABLE as parameter. > > Example: with the following QMP command: > > (QEMU) object-add qom-type=cpu id=foo > > QEMU aborts at: > > ERROR:qom/object.c:335:object_initialize_with_type: assertion failed: > (type->abstract == false) > > This patch moves the check for TYPE_USER_CREATABLE before object_new(), > and adds a check to prevent the code from trying to instantiate abstract > classes. > > Signed-off-by: Eduardo Habkost <ehabk...@redhat.com>
Related device_add fixes: 061e84f qdev-monitor: Avoid device_add crashing on non-device driver name 2fa4e56 qdev-monitor: Fix crash when device_add is called with abstract driver 7ea5e78 qdev: Do not let the user try to device_add when it cannot work > --- > qmp.c | 21 ++++++++++++++------- > 1 file changed, 14 insertions(+), 7 deletions(-) > > diff --git a/qmp.c b/qmp.c > index 87a28f7..e7ecbb7 100644 > --- a/qmp.c > +++ b/qmp.c > @@ -540,14 +540,27 @@ void object_add(const char *type, const char *id, const > QDict *qdict, > Visitor *v, Error **errp) > { > Object *obj; > + ObjectClass *klass; > const QDictEntry *e; > Error *local_err = NULL; > > - if (!object_class_by_name(type)) { > + klass = object_class_by_name(type); > + if (!klass) { > error_setg(errp, "invalid class name"); > return; > } > > + if (object_class_is_abstract(klass)) { > + error_setg(errp, "object type '%s' is abstract", type); > + return; > + } > + > + if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { > + error_setg(errp, "object type '%s' isn't supported by object-add", > + type); > + return; > + } > + > obj = object_new(type); > if (qdict) { > for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { For comparison, this is qdev_device_add(): oc = object_class_by_name(driver); if (!oc) { const char *typename = find_typename_by_alias(driver); if (typename) { driver = typename; oc = object_class_by_name(driver); } } if (!object_class_dynamic_cast(oc, TYPE_DEVICE)) { qerror_report(ERROR_CLASS_GENERIC_ERROR, "'%s' is not a valid device model name", driver); return NULL; } if (object_class_is_abstract(oc)) { qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "non-abstract device type"); return NULL; } dc = DEVICE_CLASS(oc); if (dc->cannot_instantiate_with_device_add_yet) { qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "pluggable device type"); return NULL; } Got the "subtype of" and the "not abstract" check in the opposite order, and the additional cannot_instantiate_with_device_add_yet check. Does the different order matter? > @@ -558,12 +571,6 @@ void object_add(const char *type, const char *id, const > QDict *qdict, > } > } > > - if (!object_dynamic_cast(obj, TYPE_USER_CREATABLE)) { > - error_setg(&local_err, "object type '%s' isn't supported by > object-add", > - type); > - goto out; > - } > - > user_creatable_complete(obj, &local_err); > if (local_err) { > goto out;