mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 11:35:19 +00:00
storage: Sanitize pool target paths
Spurious / in a pool target path makes life difficult for apps using the GetVolByPath, and doing other path based comparisons with pools. This has caused a few issues for virt-manager users: https://bugzilla.redhat.com/show_bug.cgi?id=494005 https://bugzilla.redhat.com/show_bug.cgi?id=593565 Add a new util API which removes spurious /, virFileSanitizePath. Sanitize target paths when parsing pool XML, and for paths passed to GetVolByPath. v2: Leading // must be preserved, properly sanitize path=/, sanitize away /./ -> / v3: Properly handle starting ./ and ending /. v4: Drop all '.' handling, just sanitize / for now.
This commit is contained in:
parent
60881161ea
commit
a7fb2258ca
@ -602,6 +602,7 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) {
|
|||||||
xmlNodePtr source_node;
|
xmlNodePtr source_node;
|
||||||
char *type = NULL;
|
char *type = NULL;
|
||||||
char *uuid = NULL;
|
char *uuid = NULL;
|
||||||
|
char *tmppath;
|
||||||
|
|
||||||
if (VIR_ALLOC(ret) < 0) {
|
if (VIR_ALLOC(ret) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
@ -699,11 +700,16 @@ virStoragePoolDefParseXML(xmlXPathContextPtr ctxt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret->target.path = virXPathString("string(./target/path)", ctxt)) == NULL) {
|
if ((tmppath = virXPathString("string(./target/path)", ctxt)) == NULL) {
|
||||||
virStorageReportError(VIR_ERR_XML_ERROR,
|
virStorageReportError(VIR_ERR_XML_ERROR,
|
||||||
"%s", _("missing storage pool target path"));
|
"%s", _("missing storage pool target path"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
ret->target.path = virFileSanitizePath(tmppath);
|
||||||
|
VIR_FREE(tmppath);
|
||||||
|
if (!ret->target.path)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
|
||||||
if (virStorageDefParsePerms(ctxt, &ret->target.perms,
|
if (virStorageDefParsePerms(ctxt, &ret->target.perms,
|
||||||
"./target/permissions", 0700) < 0)
|
"./target/permissions", 0700) < 0)
|
||||||
|
@ -675,6 +675,7 @@ virFileReadLimFD;
|
|||||||
virFilePid;
|
virFilePid;
|
||||||
virFileReadPid;
|
virFileReadPid;
|
||||||
virFileLinkPointsTo;
|
virFileLinkPointsTo;
|
||||||
|
virFileSanitizePath;
|
||||||
virParseNumber;
|
virParseNumber;
|
||||||
virParseVersionString;
|
virParseVersionString;
|
||||||
virPipeReadUntilEOF;
|
virPipeReadUntilEOF;
|
||||||
|
@ -1204,6 +1204,11 @@ storageVolumeLookupByPath(virConnectPtr conn,
|
|||||||
virStorageDriverStatePtr driver = conn->storagePrivateData;
|
virStorageDriverStatePtr driver = conn->storagePrivateData;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
virStorageVolPtr ret = NULL;
|
virStorageVolPtr ret = NULL;
|
||||||
|
char *cleanpath;
|
||||||
|
|
||||||
|
cleanpath = virFileSanitizePath(path);
|
||||||
|
if (!cleanpath)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
storageDriverLock(driver);
|
storageDriverLock(driver);
|
||||||
for (i = 0 ; i < driver->pools.count && !ret ; i++) {
|
for (i = 0 ; i < driver->pools.count && !ret ; i++) {
|
||||||
@ -1213,7 +1218,7 @@ storageVolumeLookupByPath(virConnectPtr conn,
|
|||||||
const char *stable_path;
|
const char *stable_path;
|
||||||
|
|
||||||
stable_path = virStorageBackendStablePath(driver->pools.objs[i],
|
stable_path = virStorageBackendStablePath(driver->pools.objs[i],
|
||||||
path);
|
cleanpath);
|
||||||
/*
|
/*
|
||||||
* virStorageBackendStablePath already does
|
* virStorageBackendStablePath already does
|
||||||
* virStorageReportError if it fails; we just need to keep
|
* virStorageReportError if it fails; we just need to keep
|
||||||
@ -1242,6 +1247,7 @@ storageVolumeLookupByPath(virConnectPtr conn,
|
|||||||
"%s", _("no storage vol with matching path"));
|
"%s", _("no storage vol with matching path"));
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
VIR_FREE(cleanpath);
|
||||||
storageDriverUnlock(driver);
|
storageDriverUnlock(driver);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1921,6 +1921,55 @@ int virFileAbsPath(const char *path, char **abspath)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove spurious / characters from a path. The result must be freed */
|
||||||
|
char *
|
||||||
|
virFileSanitizePath(const char *path)
|
||||||
|
{
|
||||||
|
const char *cur = path;
|
||||||
|
char *cleanpath;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
cleanpath = strdup(path);
|
||||||
|
if (!cleanpath) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need to sanitize:
|
||||||
|
* // -> //
|
||||||
|
* /// -> /
|
||||||
|
* /../foo -> /../foo
|
||||||
|
* /foo///bar/ -> /foo/bar
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Starting with // is valid posix, but ///foo == /foo */
|
||||||
|
if (cur[0] == '/' && cur[1] == '/' && cur[2] != '/') {
|
||||||
|
idx = 2;
|
||||||
|
cur += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanitize path in place */
|
||||||
|
while (*cur != '\0') {
|
||||||
|
if (*cur != '/') {
|
||||||
|
cleanpath[idx++] = *cur++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip all extra / */
|
||||||
|
while (*++cur == '/')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Don't add a trailing / */
|
||||||
|
if (idx != 0 && *cur == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
cleanpath[idx++] = '/';
|
||||||
|
}
|
||||||
|
cleanpath[idx] = '\0';
|
||||||
|
|
||||||
|
return cleanpath;
|
||||||
|
}
|
||||||
|
|
||||||
/* Like strtol, but produce an "int" result, and check more carefully.
|
/* Like strtol, but produce an "int" result, and check more carefully.
|
||||||
Return 0 upon success; return -1 to indicate failure.
|
Return 0 upon success; return -1 to indicate failure.
|
||||||
When END_PTR is NULL, the byte after the final valid digit must be NUL.
|
When END_PTR is NULL, the byte after the final valid digit must be NUL.
|
||||||
|
@ -118,6 +118,8 @@ char *virFindFileInPath(const char *file);
|
|||||||
|
|
||||||
int virFileExists(const char *path);
|
int virFileExists(const char *path);
|
||||||
|
|
||||||
|
char *virFileSanitizePath(const char *path);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
VIR_FILE_OP_NONE = 0,
|
VIR_FILE_OP_NONE = 0,
|
||||||
VIR_FILE_OP_AS_UID = (1 << 0),
|
VIR_FILE_OP_AS_UID = (1 << 0),
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<source>
|
<source>
|
||||||
</source>
|
</source>
|
||||||
<target>
|
<target>
|
||||||
<path>/var/lib/libvirt/images</path>
|
<path>///var/////lib/libvirt/images//</path>
|
||||||
<permissions>
|
<permissions>
|
||||||
<mode>0700</mode>
|
<mode>0700</mode>
|
||||||
<owner>0</owner>
|
<owner>0</owner>
|
||||||
|
Loading…
Reference in New Issue
Block a user