mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-10 14:57:42 +00:00
Fix startup of LXC containers with filesystems containing symlinks
Given an LXC guest with a root filesystem path of /export/lxc/roots/helloworld/root During startup, we will pivot the root filesystem to end up at /.oldroot/export/lxc/roots/helloworld/root We then try to open /.oldroot/export/lxc/roots/helloworld/root/dev/pts Now consider if '/export/lxc' is an absolute symlink pointing to '/media/lxc'. The kernel will try to open /media/lxc/roots/helloworld/root/dev/pts whereas it should be trying to open /.oldroot//media/lxc/roots/helloworld/root/dev/pts To deal with the fact that the root filesystem can be moved, we need to resolve symlinks in *any* part of the filesystem source path. * src/libvirt_private.syms, src/util/util.c, src/util/util.h: Add virFileResolveAllLinks to resolve all symlinks in a path * src/lxc/lxc_container.c: Resolve all symlinks in filesystem paths during startup
This commit is contained in:
parent
7aeb9794d2
commit
c53ba61b21
@ -1101,6 +1101,7 @@ virFileOpenAs;
|
||||
virFileOpenTty;
|
||||
virFileReadAll;
|
||||
virFileReadLimFD;
|
||||
virFileResolveAllLinks;
|
||||
virFileResolveLink;
|
||||
virFileSanitizePath;
|
||||
virFileStripSuffix;
|
||||
|
@ -1111,11 +1111,34 @@ static int lxcContainerSetupExtraMounts(virDomainDefPtr vmDef)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int lxcContainerResolveSymlinks(virDomainDefPtr vmDef)
|
||||
{
|
||||
char *newroot;
|
||||
size_t i;
|
||||
|
||||
for (i = 0 ; i < vmDef->nfss ; i++) {
|
||||
virDomainFSDefPtr fs = vmDef->fss[i];
|
||||
if (virFileResolveAllLinks(fs->src, &newroot) < 0)
|
||||
return -1;
|
||||
|
||||
VIR_DEBUG("Resolved '%s' to %s", fs->src, newroot);
|
||||
|
||||
VIR_FREE(fs->src);
|
||||
fs->src = newroot;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lxcContainerSetupMounts(virDomainDefPtr vmDef,
|
||||
virDomainFSDefPtr root,
|
||||
char **ttyPaths,
|
||||
size_t nttyPaths)
|
||||
{
|
||||
if (lxcContainerResolveSymlinks(vmDef) < 0)
|
||||
return -1;
|
||||
|
||||
if (root)
|
||||
return lxcContainerSetupPivotRoot(vmDef, root, ttyPaths, nttyPaths);
|
||||
else
|
||||
|
@ -536,16 +536,10 @@ int virFileLinkPointsTo(const char *checkLink,
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Attempt to resolve a symbolic link, returning an
|
||||
* absolute path where only the last component is guaranteed
|
||||
* not to be a symlink.
|
||||
*
|
||||
* Return 0 if path was not a symbolic, or the link was
|
||||
* resolved. Return -1 with errno set upon error
|
||||
*/
|
||||
int virFileResolveLink(const char *linkpath,
|
||||
char **resultpath)
|
||||
static int
|
||||
virFileResolveLinkHelper(const char *linkpath,
|
||||
bool intermediatePaths,
|
||||
char **resultpath)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
@ -554,7 +548,7 @@ int virFileResolveLink(const char *linkpath,
|
||||
/* We don't need the full canonicalization of intermediate
|
||||
* directories, if linkpath is absolute and the basename is
|
||||
* already a non-symlink. */
|
||||
if (IS_ABSOLUTE_FILE_NAME(linkpath)) {
|
||||
if (IS_ABSOLUTE_FILE_NAME(linkpath) && !intermediatePaths) {
|
||||
if (lstat(linkpath, &st) < 0)
|
||||
return -1;
|
||||
|
||||
@ -570,6 +564,33 @@ int virFileResolveLink(const char *linkpath,
|
||||
return *resultpath == NULL ? -1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to resolve a symbolic link, returning an
|
||||
* absolute path where only the last component is guaranteed
|
||||
* not to be a symlink.
|
||||
*
|
||||
* Return 0 if path was not a symbolic, or the link was
|
||||
* resolved. Return -1 with errno set upon error
|
||||
*/
|
||||
int virFileResolveLink(const char *linkpath,
|
||||
char **resultpath)
|
||||
{
|
||||
return virFileResolveLinkHelper(linkpath, false, resultpath);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to resolve a symbolic link, returning an
|
||||
* absolute path where every component is guaranteed
|
||||
* not to be a symlink.
|
||||
*
|
||||
* Return 0 if path was not a symbolic, or the link was
|
||||
* resolved. Return -1 with errno set upon error
|
||||
*/
|
||||
int virFileResolveAllLinks(const char *linkpath,
|
||||
char **resultpath)
|
||||
{
|
||||
return virFileResolveLinkHelper(linkpath, true, resultpath);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the given file is a link.
|
||||
|
@ -77,6 +77,8 @@ int virFileLinkPointsTo(const char *checkLink,
|
||||
|
||||
int virFileResolveLink(const char *linkpath,
|
||||
char **resultpath) ATTRIBUTE_RETURN_CHECK;
|
||||
int virFileResolveAllLinks(const char *linkpath,
|
||||
char **resultpath) ATTRIBUTE_RETURN_CHECK;
|
||||
|
||||
int virFileIsLink(const char *linkpath)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
|
||||
|
Loading…
Reference in New Issue
Block a user