The problem is in the way how the list item is created prior to
appending it to the transaction list - the @path argument is just a
shallow copy instead of deep copy of the hostdev device's path.
Unfortunately, the hostdev devices from which the @path is extracted, in
order to add them into the transaction list, are only temporary and
freed before the buildup of the qemu namespace, thus making the @path
attribute in the transaction list NULL, causing 'permission denied' or
'double free' or 'unknown cause' errors.
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1413773
Signed-off-by: Erik Skultety <eskultet(a)redhat.com>
---
src/security/security_selinux.c | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index f229b51..c799056 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -81,7 +81,7 @@ struct _virSecuritySELinuxCallbackData {
typedef struct _virSecuritySELinuxContextItem virSecuritySELinuxContextItem;
typedef virSecuritySELinuxContextItem *virSecuritySELinuxContextItemPtr;
struct _virSecuritySELinuxContextItem {
- const char *path;
+ char *path;
const char *tcon;
bool optional;
};
@@ -111,21 +111,31 @@ virSecuritySELinuxContextListAppend(virSecuritySELinuxContextListPtr
list,
const char *tcon,
bool optional)
{
- virSecuritySELinuxContextItemPtr item;
+ int ret = -1;
+ char *tmp = NULL;
+ virSecuritySELinuxContextItemPtr item = NULL;
if (VIR_ALLOC(item) < 0)
return -1;
- item->path = path;
+ if (VIR_STRDUP(tmp, path) < 0)
+ goto cleanup;
+
+ item->path = tmp;
item->tcon = tcon;
item->optional = optional;
- if (VIR_APPEND_ELEMENT(list->items, list->nItems, item) < 0) {
- VIR_FREE(item);
- return -1;
- }
+ if (VIR_APPEND_ELEMENT(list->items, list->nItems, item) < 0)
+ goto cleanup;
- return 0;
+ tmp = NULL;
+ item = NULL;
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(tmp);
+ VIR_FREE(item);
+ return ret;
}
static void
@@ -137,8 +147,10 @@ virSecuritySELinuxContextListFree(void *opaque)
if (!list)
return;
- for (i = 0; i < list->nItems; i++)
+ for (i = 0; i < list->nItems; i++) {
+ VIR_FREE(list->items[i]->path);
VIR_FREE(list->items[i]);
+ }
VIR_FREE(list);
}
--
2.10.2