Re: [PATCH v5 1/3] qom: Introduce object_property_try_add_child()

2020-07-01 Thread Auger Eric
Hi Greg,

On 6/30/20 3:41 PM, Greg Kurz wrote:
> On Mon, 29 Jun 2020 21:34:22 +0200
> Eric Auger  wrote:
> 
>> object_property_add() does not allow object_property_try_add()
>> to gracefully fail as _abort is passed as an error handle.
>>
>> However such failure can easily be triggered from the QMP shell when,
>> for instance, one attempts to create an object with an id that already
>> exists. This is achieved from the following call path:
>>
>> qmp_object_add -> user_creatable_add_dict -> user_creatable_add_type ->
>> object_property_add_child -> object_property_add
>>
>> For instance, from the qmp-shell, call twice:
>> object-add qom-type=memory-backend-ram id=mem1 props.size=1073741824
>> and QEMU aborts.
>>
>> This behavior is undesired as a user/management application mistake
>> in reusing a property ID shouldn't result in loss of the VM and live
>> data within.
>>
>> This patch introduces a new function, object_property_try_add_child()
>> which takes an error handle and turn object_property_try_add() into
>> a non-static one.
>>
>> Now the call path becomes:
>>
>> user_creatable_add_type -> object_property_try_add_child ->
>> object_property_try_add
>>
>> and the error is returned gracefully to the QMP client.
>>
>> (QEMU) object-add qom-type=memory-backend-ram id=mem2  props.size=4294967296
>> {"return": {}}
>> (QEMU) object-add qom-type=memory-backend-ram id=mem2  props.size=4294967296
>> {"error": {"class": "GenericError", "desc": "attempt to add duplicate 
>> property
>> 'mem2' to object (type 'container')"}}
>>
>> Signed-off-by: Eric Auger 
>> Fixes: d2623129a7de ("qom: Drop parameter @errp of object_property_add() & 
>> friends")
>> Reviewed-by: Markus Armbruster 
>>
> 
> FWIW
> 
> Reviewed-by: Greg Kurz 
> 
> and
> 
> Tested-by: Greg Kurz 
Thanks!

Eric
> 
>> ---
>>
>> v3 -> v4:
>> - Took into account Markus' style related comments
>>
>> v2 -> v3:
>> - don't take the object reference on failure in
>>   object_property_try_add_child
>> ---
>>  include/qom/object.h| 26 --
>>  qom/object.c| 21 -
>>  qom/object_interfaces.c |  7 +--
>>  3 files changed, 45 insertions(+), 9 deletions(-)
>>
>> diff --git a/include/qom/object.h b/include/qom/object.h
>> index 94a61ccc3f..1c5cdcd0e3 100644
>> --- a/include/qom/object.h
>> +++ b/include/qom/object.h
>> @@ -1039,7 +1039,7 @@ Object *object_ref(Object *obj);
>>  void object_unref(Object *obj);
>>  
>>  /**
>> - * object_property_add:
>> + * object_property_try_add:
>>   * @obj: the object to add a property to
>>   * @name: the name of the property.  This can contain any character except 
>> for
>>   *  a forward slash.  In general, you should use hyphens '-' instead of
>> @@ -1056,10 +1056,23 @@ void object_unref(Object *obj);
>>   *   meant to allow a property to free its opaque upon object
>>   *   destruction.  This may be NULL.
>>   * @opaque: an opaque pointer to pass to the callbacks for the property
>> + * @errp: pointer to error object
>>   *
>>   * Returns: The #ObjectProperty; this can be used to set the @resolve
>>   * callback for child and link properties.
>>   */
>> +ObjectProperty *object_property_try_add(Object *obj, const char *name,
>> +const char *type,
>> +ObjectPropertyAccessor *get,
>> +ObjectPropertyAccessor *set,
>> +ObjectPropertyRelease *release,
>> +void *opaque, Error **errp);
>> +
>> +/**
>> + * object_property_add:
>> + * Same as object_property_try_add() with @errp hardcoded to
>> + * _abort.
>> + */
>>  ObjectProperty *object_property_add(Object *obj, const char *name,
>>  const char *type,
>>  ObjectPropertyAccessor *get,
>> @@ -1495,10 +1508,11 @@ Object *object_resolve_path_type(const char *path, 
>> const char *typename,
>>  Object *object_resolve_path_component(Object *parent, const char *part);
>>  
>>  /**
>> - * object_property_add_child:
>> + * object_property_try_add_child:
>>   * @obj: the object to add a property to
>>   * @name: the name of the property
>>   * @child: the child object
>> + * @errp: pointer to error object
>>   *
>>   * Child properties form the composition tree.  All objects need to be a 
>> child
>>   * of another object.  Objects can only be a child of one object.
>> @@ -1512,6 +1526,14 @@ Object *object_resolve_path_component(Object *parent, 
>> const char *part);
>>   *
>>   * Returns: The newly added property on success, or %NULL on failure.
>>   */
>> +ObjectProperty *object_property_try_add_child(Object *obj, const char *name,
>> +  Object *child, Error **errp);
>> +
>> +/**
>> + * object_property_add_child:
>> + * Same as object_property_try_add_child() with @errp hardcoded to
>> + * _abort
>> + */
>>  

Re: [PATCH v5 1/3] qom: Introduce object_property_try_add_child()

2020-06-30 Thread Greg Kurz
On Mon, 29 Jun 2020 21:34:22 +0200
Eric Auger  wrote:

> object_property_add() does not allow object_property_try_add()
> to gracefully fail as _abort is passed as an error handle.
> 
> However such failure can easily be triggered from the QMP shell when,
> for instance, one attempts to create an object with an id that already
> exists. This is achieved from the following call path:
> 
> qmp_object_add -> user_creatable_add_dict -> user_creatable_add_type ->
> object_property_add_child -> object_property_add
> 
> For instance, from the qmp-shell, call twice:
> object-add qom-type=memory-backend-ram id=mem1 props.size=1073741824
> and QEMU aborts.
> 
> This behavior is undesired as a user/management application mistake
> in reusing a property ID shouldn't result in loss of the VM and live
> data within.
> 
> This patch introduces a new function, object_property_try_add_child()
> which takes an error handle and turn object_property_try_add() into
> a non-static one.
> 
> Now the call path becomes:
> 
> user_creatable_add_type -> object_property_try_add_child ->
> object_property_try_add
> 
> and the error is returned gracefully to the QMP client.
> 
> (QEMU) object-add qom-type=memory-backend-ram id=mem2  props.size=4294967296
> {"return": {}}
> (QEMU) object-add qom-type=memory-backend-ram id=mem2  props.size=4294967296
> {"error": {"class": "GenericError", "desc": "attempt to add duplicate property
> 'mem2' to object (type 'container')"}}
> 
> Signed-off-by: Eric Auger 
> Fixes: d2623129a7de ("qom: Drop parameter @errp of object_property_add() & 
> friends")
> Reviewed-by: Markus Armbruster 
> 

FWIW

Reviewed-by: Greg Kurz 

and

Tested-by: Greg Kurz 

> ---
> 
> v3 -> v4:
> - Took into account Markus' style related comments
> 
> v2 -> v3:
> - don't take the object reference on failure in
>   object_property_try_add_child
> ---
>  include/qom/object.h| 26 --
>  qom/object.c| 21 -
>  qom/object_interfaces.c |  7 +--
>  3 files changed, 45 insertions(+), 9 deletions(-)
> 
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 94a61ccc3f..1c5cdcd0e3 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -1039,7 +1039,7 @@ Object *object_ref(Object *obj);
>  void object_unref(Object *obj);
>  
>  /**
> - * object_property_add:
> + * object_property_try_add:
>   * @obj: the object to add a property to
>   * @name: the name of the property.  This can contain any character except 
> for
>   *  a forward slash.  In general, you should use hyphens '-' instead of
> @@ -1056,10 +1056,23 @@ void object_unref(Object *obj);
>   *   meant to allow a property to free its opaque upon object
>   *   destruction.  This may be NULL.
>   * @opaque: an opaque pointer to pass to the callbacks for the property
> + * @errp: pointer to error object
>   *
>   * Returns: The #ObjectProperty; this can be used to set the @resolve
>   * callback for child and link properties.
>   */
> +ObjectProperty *object_property_try_add(Object *obj, const char *name,
> +const char *type,
> +ObjectPropertyAccessor *get,
> +ObjectPropertyAccessor *set,
> +ObjectPropertyRelease *release,
> +void *opaque, Error **errp);
> +
> +/**
> + * object_property_add:
> + * Same as object_property_try_add() with @errp hardcoded to
> + * _abort.
> + */
>  ObjectProperty *object_property_add(Object *obj, const char *name,
>  const char *type,
>  ObjectPropertyAccessor *get,
> @@ -1495,10 +1508,11 @@ Object *object_resolve_path_type(const char *path, 
> const char *typename,
>  Object *object_resolve_path_component(Object *parent, const char *part);
>  
>  /**
> - * object_property_add_child:
> + * object_property_try_add_child:
>   * @obj: the object to add a property to
>   * @name: the name of the property
>   * @child: the child object
> + * @errp: pointer to error object
>   *
>   * Child properties form the composition tree.  All objects need to be a 
> child
>   * of another object.  Objects can only be a child of one object.
> @@ -1512,6 +1526,14 @@ Object *object_resolve_path_component(Object *parent, 
> const char *part);
>   *
>   * Returns: The newly added property on success, or %NULL on failure.
>   */
> +ObjectProperty *object_property_try_add_child(Object *obj, const char *name,
> +  Object *child, Error **errp);
> +
> +/**
> + * object_property_add_child:
> + * Same as object_property_try_add_child() with @errp hardcoded to
> + * _abort
> + */
>  ObjectProperty *object_property_add_child(Object *obj, const char *name,
>Object *child);
>  
> diff --git a/qom/object.c b/qom/object.c
> index 

[PATCH v5 1/3] qom: Introduce object_property_try_add_child()

2020-06-29 Thread Eric Auger
object_property_add() does not allow object_property_try_add()
to gracefully fail as _abort is passed as an error handle.

However such failure can easily be triggered from the QMP shell when,
for instance, one attempts to create an object with an id that already
exists. This is achieved from the following call path:

qmp_object_add -> user_creatable_add_dict -> user_creatable_add_type ->
object_property_add_child -> object_property_add

For instance, from the qmp-shell, call twice:
object-add qom-type=memory-backend-ram id=mem1 props.size=1073741824
and QEMU aborts.

This behavior is undesired as a user/management application mistake
in reusing a property ID shouldn't result in loss of the VM and live
data within.

This patch introduces a new function, object_property_try_add_child()
which takes an error handle and turn object_property_try_add() into
a non-static one.

Now the call path becomes:

user_creatable_add_type -> object_property_try_add_child ->
object_property_try_add

and the error is returned gracefully to the QMP client.

(QEMU) object-add qom-type=memory-backend-ram id=mem2  props.size=4294967296
{"return": {}}
(QEMU) object-add qom-type=memory-backend-ram id=mem2  props.size=4294967296
{"error": {"class": "GenericError", "desc": "attempt to add duplicate property
'mem2' to object (type 'container')"}}

Signed-off-by: Eric Auger 
Fixes: d2623129a7de ("qom: Drop parameter @errp of object_property_add() & 
friends")
Reviewed-by: Markus Armbruster 

---

v3 -> v4:
- Took into account Markus' style related comments

v2 -> v3:
- don't take the object reference on failure in
  object_property_try_add_child
---
 include/qom/object.h| 26 --
 qom/object.c| 21 -
 qom/object_interfaces.c |  7 +--
 3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/include/qom/object.h b/include/qom/object.h
index 94a61ccc3f..1c5cdcd0e3 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1039,7 +1039,7 @@ Object *object_ref(Object *obj);
 void object_unref(Object *obj);
 
 /**
- * object_property_add:
+ * object_property_try_add:
  * @obj: the object to add a property to
  * @name: the name of the property.  This can contain any character except for
  *  a forward slash.  In general, you should use hyphens '-' instead of
@@ -1056,10 +1056,23 @@ void object_unref(Object *obj);
  *   meant to allow a property to free its opaque upon object
  *   destruction.  This may be NULL.
  * @opaque: an opaque pointer to pass to the callbacks for the property
+ * @errp: pointer to error object
  *
  * Returns: The #ObjectProperty; this can be used to set the @resolve
  * callback for child and link properties.
  */
+ObjectProperty *object_property_try_add(Object *obj, const char *name,
+const char *type,
+ObjectPropertyAccessor *get,
+ObjectPropertyAccessor *set,
+ObjectPropertyRelease *release,
+void *opaque, Error **errp);
+
+/**
+ * object_property_add:
+ * Same as object_property_try_add() with @errp hardcoded to
+ * _abort.
+ */
 ObjectProperty *object_property_add(Object *obj, const char *name,
 const char *type,
 ObjectPropertyAccessor *get,
@@ -1495,10 +1508,11 @@ Object *object_resolve_path_type(const char *path, 
const char *typename,
 Object *object_resolve_path_component(Object *parent, const char *part);
 
 /**
- * object_property_add_child:
+ * object_property_try_add_child:
  * @obj: the object to add a property to
  * @name: the name of the property
  * @child: the child object
+ * @errp: pointer to error object
  *
  * Child properties form the composition tree.  All objects need to be a child
  * of another object.  Objects can only be a child of one object.
@@ -1512,6 +1526,14 @@ Object *object_resolve_path_component(Object *parent, 
const char *part);
  *
  * Returns: The newly added property on success, or %NULL on failure.
  */
+ObjectProperty *object_property_try_add_child(Object *obj, const char *name,
+  Object *child, Error **errp);
+
+/**
+ * object_property_add_child:
+ * Same as object_property_try_add_child() with @errp hardcoded to
+ * _abort
+ */
 ObjectProperty *object_property_add_child(Object *obj, const char *name,
   Object *child);
 
diff --git a/qom/object.c b/qom/object.c
index 6ece96bc2b..dc10bb1889 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1132,7 +1132,7 @@ void object_unref(Object *obj)
 }
 }
 
-static ObjectProperty *
+ObjectProperty *
 object_property_try_add(Object *obj, const char *name, const char *type,
 ObjectPropertyAccessor *get,
 ObjectPropertyAccessor *set,
@@ -1651,8 +1651,8 @@