]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: fix use after free in virChrdevOpen
authorJán Tomko <jtomko@redhat.com>
Wed, 22 May 2013 10:56:23 +0000 (12:56 +0200)
committerJán Tomko <jtomko@redhat.com>
Thu, 23 May 2013 15:55:34 +0000 (17:55 +0200)
Don't free the stream on error if we've successfully added it
to the hash table, since it will be freed by virChrdevHashEntryFree
callback.

Preserve the error message before calling virStreamFree, since it
resets the error.

Introduced by 4716138, crashing since 6921892.

Reported by Sergey Fionov on libvir-list.

src/conf/virchrdev.c

index d15d861d945b8efa3396d0798c71a0f6f93c7575..17b1f05f8669f488a161156a2607dff81cafe848 100644 (file)
@@ -341,6 +341,8 @@ int virChrdevOpen(virChrdevsPtr devs,
     virStreamPtr savedStream;
     char *path;
     int ret;
+    bool added = false;
+    virErrorPtr savedError;
 
     switch (source->type) {
     case VIR_DOMAIN_CHR_TYPE_PTY:
@@ -397,6 +399,7 @@ int virChrdevOpen(virChrdevsPtr devs,
 
     if (virHashAddEntry(devs->hash, path, st) < 0)
         goto error;
+    added = true;
 
     cbdata->devs = devs;
     if (VIR_STRDUP(cbdata->path, path) < 0)
@@ -429,8 +432,16 @@ int virChrdevOpen(virChrdevsPtr devs,
     return 0;
 
 error:
-    virStreamFree(st);
-    virHashRemoveEntry(devs->hash, path);
+    savedError = virSaveLastError();
+
+    if (added)
+        virHashRemoveEntry(devs->hash, path);
+    else
+        virStreamFree(st);
+
+    virSetError(savedError);
+    virFreeError(savedError);
+
     if (cbdata)
         VIR_FREE(cbdata->path);
     VIR_FREE(cbdata);