mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 22:55:23 +00:00
Workaround for broken kernel autofs mounts
The kernel automounter is mostly broken wrt to containers. Most notably if you start a new filesystem namespace and then attempt to unmount any autofs filesystem, it will typically fail with a weird error message like Failed to unmount '/.oldroot/sys/kernel/security':Too many levels of symbolic links Attempting to detach the autofs mount using umount2(MNT_DETACH) will also fail with the same error. Therefore if we get any error on unmount()ing a filesystem from the old root FS when starting a container, we must immediately break out and detach the entire old root filesystem (ignoring any mounts below it). This has the effect of making the old root filesystem inaccessible to anything inside the container, but at the cost that the mounts live on in the kernel until the container exits. Given that SystemD uses autofs by default, we need LXC to be robust this scenario and thus this tradeoff is worthwhile. * src/lxc/lxc_container.c: Detach root filesystem if any umount operation fails.
This commit is contained in:
parent
a02f57faa9
commit
878cc33a6a
@ -860,6 +860,9 @@ static int lxcContainerUnmountOldFS(void)
|
||||
FILE *procmnt;
|
||||
int i;
|
||||
char mntbuf[1024];
|
||||
int saveErrno;
|
||||
const char *failedUmount = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (!(procmnt = setmntent("/proc/mounts", "r"))) {
|
||||
virReportSystemError(errno, "%s",
|
||||
@ -872,17 +875,15 @@ static int lxcContainerUnmountOldFS(void)
|
||||
continue;
|
||||
|
||||
if (VIR_REALLOC_N(mounts, nmounts+1) < 0) {
|
||||
endmntent(procmnt);
|
||||
virReportOOMError();
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (!(mounts[nmounts++] = strdup(mntent.mnt_dir))) {
|
||||
endmntent(procmnt);
|
||||
virReportOOMError();
|
||||
return -1;
|
||||
goto cleanup;
|
||||
}
|
||||
VIR_DEBUG("Grabbed %s", mntent.mnt_dir);
|
||||
}
|
||||
endmntent(procmnt);
|
||||
|
||||
if (mounts)
|
||||
qsort(mounts, nmounts, sizeof(mounts[0]),
|
||||
@ -891,16 +892,42 @@ static int lxcContainerUnmountOldFS(void)
|
||||
for (i = 0 ; i < nmounts ; i++) {
|
||||
VIR_DEBUG("Umount %s", mounts[i]);
|
||||
if (umount(mounts[i]) < 0) {
|
||||
virReportSystemError(errno,
|
||||
_("Failed to unmount '%s'"),
|
||||
mounts[i]);
|
||||
return -1;
|
||||
char ebuf[1024];
|
||||
failedUmount = mounts[i];
|
||||
saveErrno = errno;
|
||||
VIR_WARN("Failed to unmount '%s', trying to detach root '%s': %s",
|
||||
failedUmount, mounts[nmounts-1],
|
||||
virStrerror(errno, ebuf, sizeof(ebuf)));
|
||||
break;
|
||||
}
|
||||
VIR_FREE(mounts[i]);
|
||||
}
|
||||
|
||||
if (failedUmount) {
|
||||
/* This detaches the old root filesystem */
|
||||
if (umount2(mounts[nmounts-1], MNT_DETACH) < 0) {
|
||||
virReportSystemError(saveErrno,
|
||||
_("Failed to unmount '%s' and could not detach old root '%s'"),
|
||||
failedUmount, mounts[nmounts-1]);
|
||||
goto cleanup;
|
||||
}
|
||||
/* This unmounts the tmpfs on which the old root filesystem was hosted */
|
||||
if (umount(mounts[nmounts-1]) < 0) {
|
||||
virReportSystemError(saveErrno,
|
||||
_("Failed to unmount '%s' and could not unmount old root '%s'"),
|
||||
failedUmount, mounts[nmounts-1]);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
for (i = 0 ; i < nmounts ; i++)
|
||||
VIR_FREE(mounts[i]);
|
||||
endmntent(procmnt);
|
||||
VIR_FREE(mounts);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user