mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +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;
|
||||
char *type = NULL;
|
||||
char *uuid = NULL;
|
||||
char *tmppath;
|
||||
|
||||
if (VIR_ALLOC(ret) < 0) {
|
||||
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,
|
||||
"%s", _("missing storage pool target path"));
|
||||
goto cleanup;
|
||||
}
|
||||
ret->target.path = virFileSanitizePath(tmppath);
|
||||
VIR_FREE(tmppath);
|
||||
if (!ret->target.path)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
if (virStorageDefParsePerms(ctxt, &ret->target.perms,
|
||||
"./target/permissions", 0700) < 0)
|
||||
|
@ -675,6 +675,7 @@ virFileReadLimFD;
|
||||
virFilePid;
|
||||
virFileReadPid;
|
||||
virFileLinkPointsTo;
|
||||
virFileSanitizePath;
|
||||
virParseNumber;
|
||||
virParseVersionString;
|
||||
virPipeReadUntilEOF;
|
||||
|
@ -1204,6 +1204,11 @@ storageVolumeLookupByPath(virConnectPtr conn,
|
||||
virStorageDriverStatePtr driver = conn->storagePrivateData;
|
||||
unsigned int i;
|
||||
virStorageVolPtr ret = NULL;
|
||||
char *cleanpath;
|
||||
|
||||
cleanpath = virFileSanitizePath(path);
|
||||
if (!cleanpath)
|
||||
return NULL;
|
||||
|
||||
storageDriverLock(driver);
|
||||
for (i = 0 ; i < driver->pools.count && !ret ; i++) {
|
||||
@ -1213,7 +1218,7 @@ storageVolumeLookupByPath(virConnectPtr conn,
|
||||
const char *stable_path;
|
||||
|
||||
stable_path = virStorageBackendStablePath(driver->pools.objs[i],
|
||||
path);
|
||||
cleanpath);
|
||||
/*
|
||||
* virStorageBackendStablePath already does
|
||||
* virStorageReportError if it fails; we just need to keep
|
||||
@ -1242,6 +1247,7 @@ storageVolumeLookupByPath(virConnectPtr conn,
|
||||
"%s", _("no storage vol with matching path"));
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(cleanpath);
|
||||
storageDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1921,6 +1921,55 @@ int virFileAbsPath(const char *path, char **abspath)
|
||||
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.
|
||||
Return 0 upon success; return -1 to indicate failure.
|
||||
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);
|
||||
|
||||
char *virFileSanitizePath(const char *path);
|
||||
|
||||
enum {
|
||||
VIR_FILE_OP_NONE = 0,
|
||||
VIR_FILE_OP_AS_UID = (1 << 0),
|
||||
|
@ -7,7 +7,7 @@
|
||||
<source>
|
||||
</source>
|
||||
<target>
|
||||
<path>/var/lib/libvirt/images</path>
|
||||
<path>///var/////lib/libvirt/images//</path>
|
||||
<permissions>
|
||||
<mode>0700</mode>
|
||||
<owner>0</owner>
|
||||
|
Loading…
Reference in New Issue
Block a user