diff --git a/include/qemu/object.h b/include/qemu/object.h
index 8bc9935..5bb62dd 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -907,6 +907,9 @@ Object *object_resolve_path_component(Object *parent, gchar *part);
 void object_property_add_child(Object *obj, const char *name,
                                Object *child, struct Error **errp);
 
+void object_property_add_nullable_child(Object *obj, const char *name,
+                                        Object *child, struct Error **errp);
+
 /**
  * object_property_add_link:
  * @obj: the object to add a property to
@@ -925,6 +928,12 @@ void object_property_add_link(Object *obj, const char *name,
                               const char *type, Object **child,
                               struct Error **errp);
 
+void object_get_link_property(Object *obj, struct Visitor *v, void *opaque,
+                              const char *name, struct Error **errp);
+
+void object_set_link_property(Object *obj, struct Visitor *v, void *opaque,
+                              const char *name, struct Error **errp);
+
 /**
  * object_property_add_str:
  * @obj: the object to add a property to
diff --git a/qom/object.c b/qom/object.c
index 1144f79..61fa40f 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -744,8 +744,17 @@ char *object_property_get_str(Object *obj, const char *name,
 void object_property_set_link(Object *obj, Object *value,
                               const char *name, Error **errp)
 {
-    object_property_set_str(obj, object_get_canonical_path(value),
-                            name, errp);
+    char *str;
+
+    if (value == NULL) {
+        str = g_strdup("");
+    } else {
+        str = object_get_canonical_path(value);
+    }
+
+    object_property_set_str(obj, str, name, errp);
+
+    g_free(str);
 }
 
 Object *object_property_get_link(Object *obj, const char *name,
@@ -882,6 +891,27 @@ static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
     g_free(path);
 }
 
+static void object_set_child_property(Object *obj, Visitor *v, void *opaque,
+                                      const char *name, Error **errp)
+{
+    gchar *path = NULL;
+    Error *local_err = NULL;
+
+    visit_type_str(v, &path, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    if (path && *path) {
+        error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+                  "Cannot set child properties to anything but empty string");
+        return;
+    }
+
+    object_property_del(obj, name, errp);
+}
+
 static void object_finalize_child_property(Object *obj, const char *name,
                                            void *opaque)
 {
@@ -890,15 +920,17 @@ static void object_finalize_child_property(Object *obj, const char *name,
     object_unref(child);
 }
 
-void object_property_add_child(Object *obj, const char *name,
-                               Object *child, Error **errp)
+static void object_property_add_child_full(Object *obj, const char *name,
+                                           Object *child, bool writable,
+                                           Error **errp)
 {
     gchar *type;
 
     type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
 
     object_property_add(obj, name, type, object_get_child_property,
-                        NULL, object_finalize_child_property, child, errp);
+                        writable ? object_set_child_property : NULL,
+                        object_finalize_child_property, child, errp);
 
     object_ref(child);
     g_assert(child->parent == NULL);
@@ -907,8 +939,20 @@ void object_property_add_child(Object *obj, const char *name,
     g_free(type);
 }
 
-static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
-                                     const char *name, Error **errp)
+void object_property_add_child(Object *obj, const char *name,
+                               Object *child, Error **errp)
+{
+    object_property_add_child_full(obj, name, child, false, errp);
+}
+
+void object_property_add_nullable_child(Object *obj, const char *name,
+                                        Object *child, Error **errp)
+{
+    object_property_add_child_full(obj, name, child, true, errp);
+}
+
+void object_get_link_property(Object *obj, Visitor *v, void *opaque,
+                              const char *name, Error **errp)
 {
     Object **child = opaque;
     gchar *path;
@@ -923,8 +967,8 @@ static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
     }
 }
 
-static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
-                                     const char *name, Error **errp)
+void object_set_link_property(Object *obj, Visitor *v, void *opaque,
+                              const char *name, Error **errp)
 {
     Object **child = opaque;
     Object *old_target;
@@ -970,6 +1014,16 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
     }
 }
 
+static void object_finalize_link_property(Object *obj, const char *name,
+                                           void *opaque)
+{
+    Object **child = opaque;
+
+    if (*child != NULL) {
+        object_unref(*child);
+    }
+}
+
 void object_property_add_link(Object *obj, const char *name,
                               const char *type, Object **child,
                               Error **errp)
@@ -981,7 +1035,11 @@ void object_property_add_link(Object *obj, const char *name,
     object_property_add(obj, name, full_type,
                         object_get_link_property,
                         object_set_link_property,
-                        NULL, child, errp);
+                        object_finalize_link_property, child, errp);
+
+    if (*child) {
+        object_ref(*child);
+    }
 
     g_free(full_type);
 }
