提交 4391b522 编写于 作者: M Michal Privoznik

virstorageobj: Check for duplicates from virStoragePoolObjAssignDef

Even though we do some checking it is not as thorough as it
should be. We already have virStoragePoolObjIsDuplicate but the
way we use it is a typical TOCTOU. Imagine two threads trying to
define two pools with the same name but different UUIDs. With the
current code neither of them finds a duplicate and thus proceed
to virStoragePoolObjAssignDef where only names are compared.
Therefore both threads succeed which is obviously wrong.

We should check for duplicates where we care for them.
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
Reviewed-by: NJohn Ferlan <jferlan@redhat.com>
上级 db867c6b
...@@ -1052,22 +1052,28 @@ virStoragePoolObjVolumeListExport(virConnectPtr conn, ...@@ -1052,22 +1052,28 @@ virStoragePoolObjVolumeListExport(virConnectPtr conn,
* @doms : virStoragePoolObjListPtr to search * @doms : virStoragePoolObjListPtr to search
* @def : virStoragePoolDefPtr definition of pool to lookup * @def : virStoragePoolDefPtr definition of pool to lookup
* @check_active: If true, ensure that pool is not active * @check_active: If true, ensure that pool is not active
* @objRet: returned pool object
* *
* Returns: -1 on error * Assumes @pools is locked by caller already.
*
* Returns: -1 on error (name/uuid mismatch or check_active failure)
* 0 if pool is new * 0 if pool is new
* 1 if pool is a duplicate * 1 if pool is a duplicate (name and UUID match)
*/ */
int static int
virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools, virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
virStoragePoolDefPtr def, virStoragePoolDefPtr def,
bool check_active) bool check_active,
virStoragePoolObjPtr *objRet)
{ {
int ret = -1; int ret = -1;
virStoragePoolObjPtr obj = NULL; virStoragePoolObjPtr obj = NULL;
/* See if a Pool with matching UUID already exists */ /* See if a Pool with matching UUID already exists */
obj = virStoragePoolObjFindByUUID(pools, def->uuid); obj = virStoragePoolObjFindByUUIDLocked(pools, def->uuid);
if (obj) { if (obj) {
virObjectLock(obj);
/* UUID matches, but if names don't match, refuse it */ /* UUID matches, but if names don't match, refuse it */
if (STRNEQ(obj->def->name, def->name)) { if (STRNEQ(obj->def->name, def->name)) {
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
...@@ -1088,11 +1094,14 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools, ...@@ -1088,11 +1094,14 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
} }
} }
VIR_STEAL_PTR(*objRet, obj);
ret = 1; ret = 1;
} else { } else {
/* UUID does not match, but if a name matches, refuse it */ /* UUID does not match, but if a name matches, refuse it */
obj = virStoragePoolObjFindByName(pools, def->name); obj = virStoragePoolObjFindByNameLocked(pools, def->name);
if (obj) { if (obj) {
virObjectLock(obj);
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(obj->def->uuid, uuidstr); virUUIDFormat(obj->def->uuid, uuidstr);
virReportError(VIR_ERR_OPERATION_FAILED, virReportError(VIR_ERR_OPERATION_FAILED,
...@@ -1113,6 +1122,7 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools, ...@@ -1113,6 +1122,7 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
* virStoragePoolObjAssignDef: * virStoragePoolObjAssignDef:
* @pools: Storage Pool object list pointer * @pools: Storage Pool object list pointer
* @def: Storage pool definition to add or update * @def: Storage pool definition to add or update
* @check_active: If true, ensure that pool is not active
* *
* Lookup the @def to see if it already exists in the @pools in order * Lookup the @def to see if it already exists in the @pools in order
* to either update or add if it does not exist. * to either update or add if it does not exist.
...@@ -1121,15 +1131,20 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools, ...@@ -1121,15 +1131,20 @@ virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
*/ */
virStoragePoolObjPtr virStoragePoolObjPtr
virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools, virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
virStoragePoolDefPtr def) virStoragePoolDefPtr def,
bool check_active)
{ {
virStoragePoolObjPtr obj; virStoragePoolObjPtr obj = NULL;
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
int rc;
virObjectRWLockWrite(pools); virObjectRWLockWrite(pools);
if ((obj = virStoragePoolObjFindByNameLocked(pools, def->name))) { rc = virStoragePoolObjIsDuplicate(pools, def, check_active, &obj);
virObjectLock(obj);
if (rc < 0)
goto error;
if (rc > 0) {
if (!virStoragePoolObjIsActive(obj)) { if (!virStoragePoolObjIsActive(obj)) {
virStoragePoolDefFree(obj->def); virStoragePoolDefFree(obj->def);
obj->def = def; obj->def = def;
...@@ -1186,7 +1201,7 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools, ...@@ -1186,7 +1201,7 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
return NULL; return NULL;
} }
if (!(obj = virStoragePoolObjAssignDef(pools, def))) { if (!(obj = virStoragePoolObjAssignDef(pools, def, false))) {
virStoragePoolDefFree(def); virStoragePoolDefFree(def);
return NULL; return NULL;
} }
...@@ -1248,7 +1263,7 @@ virStoragePoolObjLoadState(virStoragePoolObjListPtr pools, ...@@ -1248,7 +1263,7 @@ virStoragePoolObjLoadState(virStoragePoolObjListPtr pools,
} }
/* create the object */ /* create the object */
if (!(obj = virStoragePoolObjAssignDef(pools, def))) if (!(obj = virStoragePoolObjAssignDef(pools, def, true)))
goto error; goto error;
/* XXX: future handling of some additional useful status data, /* XXX: future handling of some additional useful status data,
......
...@@ -189,7 +189,8 @@ virStoragePoolObjVolumeListExport(virConnectPtr conn, ...@@ -189,7 +189,8 @@ virStoragePoolObjVolumeListExport(virConnectPtr conn,
virStoragePoolObjPtr virStoragePoolObjPtr
virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools, virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
virStoragePoolDefPtr def); virStoragePoolDefPtr def,
bool check_active);
int int
virStoragePoolObjSaveDef(virStorageDriverStatePtr driver, virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
...@@ -244,11 +245,6 @@ void ...@@ -244,11 +245,6 @@ void
virStoragePoolObjRemove(virStoragePoolObjListPtr pools, virStoragePoolObjRemove(virStoragePoolObjListPtr pools,
virStoragePoolObjPtr obj); virStoragePoolObjPtr obj);
int
virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools,
virStoragePoolDefPtr def,
bool check_active);
int int
virStoragePoolObjSourceFindDuplicate(virConnectPtr conn, virStoragePoolObjSourceFindDuplicate(virConnectPtr conn,
virStoragePoolObjListPtr pools, virStoragePoolObjListPtr pools,
......
...@@ -1143,7 +1143,6 @@ virStoragePoolObjGetVolumesCount; ...@@ -1143,7 +1143,6 @@ virStoragePoolObjGetVolumesCount;
virStoragePoolObjIncrAsyncjobs; virStoragePoolObjIncrAsyncjobs;
virStoragePoolObjIsActive; virStoragePoolObjIsActive;
virStoragePoolObjIsAutostart; virStoragePoolObjIsAutostart;
virStoragePoolObjIsDuplicate;
virStoragePoolObjListExport; virStoragePoolObjListExport;
virStoragePoolObjListForEach; virStoragePoolObjListForEach;
virStoragePoolObjListNew; virStoragePoolObjListNew;
......
...@@ -705,16 +705,13 @@ storagePoolCreateXML(virConnectPtr conn, ...@@ -705,16 +705,13 @@ storagePoolCreateXML(virConnectPtr conn,
if (virStoragePoolCreateXMLEnsureACL(conn, newDef) < 0) if (virStoragePoolCreateXMLEnsureACL(conn, newDef) < 0)
goto cleanup; goto cleanup;
if (virStoragePoolObjIsDuplicate(driver->pools, newDef, true) < 0)
goto cleanup;
if (virStoragePoolObjSourceFindDuplicate(conn, driver->pools, newDef) < 0) if (virStoragePoolObjSourceFindDuplicate(conn, driver->pools, newDef) < 0)
goto cleanup; goto cleanup;
if ((backend = virStorageBackendForType(newDef->type)) == NULL) if ((backend = virStorageBackendForType(newDef->type)) == NULL)
goto cleanup; goto cleanup;
if (!(obj = virStoragePoolObjAssignDef(driver->pools, newDef))) if (!(obj = virStoragePoolObjAssignDef(driver->pools, newDef, true)))
goto cleanup; goto cleanup;
newDef = NULL; newDef = NULL;
def = virStoragePoolObjGetDef(obj); def = virStoragePoolObjGetDef(obj);
...@@ -799,16 +796,13 @@ storagePoolDefineXML(virConnectPtr conn, ...@@ -799,16 +796,13 @@ storagePoolDefineXML(virConnectPtr conn,
if (virStoragePoolDefineXMLEnsureACL(conn, newDef) < 0) if (virStoragePoolDefineXMLEnsureACL(conn, newDef) < 0)
goto cleanup; goto cleanup;
if (virStoragePoolObjIsDuplicate(driver->pools, newDef, false) < 0)
goto cleanup;
if (virStoragePoolObjSourceFindDuplicate(conn, driver->pools, newDef) < 0) if (virStoragePoolObjSourceFindDuplicate(conn, driver->pools, newDef) < 0)
goto cleanup; goto cleanup;
if (virStorageBackendForType(newDef->type) == NULL) if (virStorageBackendForType(newDef->type) == NULL)
goto cleanup; goto cleanup;
if (!(obj = virStoragePoolObjAssignDef(driver->pools, newDef))) if (!(obj = virStoragePoolObjAssignDef(driver->pools, newDef, false)))
goto cleanup; goto cleanup;
newDef = virStoragePoolObjGetNewDef(obj); newDef = virStoragePoolObjGetNewDef(obj);
def = virStoragePoolObjGetDef(obj); def = virStoragePoolObjGetDef(obj);
......
...@@ -1108,7 +1108,7 @@ testParseStorage(testDriverPtr privconn, ...@@ -1108,7 +1108,7 @@ testParseStorage(testDriverPtr privconn,
if (!def) if (!def)
goto error; goto error;
if (!(obj = virStoragePoolObjAssignDef(privconn->pools, def))) { if (!(obj = virStoragePoolObjAssignDef(privconn->pools, def, false))) {
virStoragePoolDefFree(def); virStoragePoolDefFree(def);
goto error; goto error;
} }
...@@ -4515,10 +4515,7 @@ testStoragePoolCreateXML(virConnectPtr conn, ...@@ -4515,10 +4515,7 @@ testStoragePoolCreateXML(virConnectPtr conn,
if (!(newDef = virStoragePoolDefParseString(xml))) if (!(newDef = virStoragePoolDefParseString(xml)))
goto cleanup; goto cleanup;
if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, true) < 0) if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef, true)))
goto cleanup;
if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef)))
goto cleanup; goto cleanup;
newDef = NULL; newDef = NULL;
def = virStoragePoolObjGetDef(obj); def = virStoragePoolObjGetDef(obj);
...@@ -4589,10 +4586,7 @@ testStoragePoolDefineXML(virConnectPtr conn, ...@@ -4589,10 +4586,7 @@ testStoragePoolDefineXML(virConnectPtr conn,
newDef->allocation = defaultPoolAlloc; newDef->allocation = defaultPoolAlloc;
newDef->available = defaultPoolCap - defaultPoolAlloc; newDef->available = defaultPoolCap - defaultPoolAlloc;
if (virStoragePoolObjIsDuplicate(privconn->pools, newDef, false) < 0) if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef, false)))
goto cleanup;
if (!(obj = virStoragePoolObjAssignDef(privconn->pools, newDef)))
goto cleanup; goto cleanup;
newDef = NULL; newDef = NULL;
def = virStoragePoolObjGetDef(obj); def = virStoragePoolObjGetDef(obj);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册