Some programs want to change some values for the network interfaces configuration in /proc/sys/net/ipv[46] folders. Giving RW access on them allows wicked to work on openSUSE 13.2+. In order to mount those folders RW but keep the rest of /proc/sys RO, we add temporary mounts for these folders before bind-mounting /proc/sys. --- src/lxc/lxc_container.c | 97 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 3b08b86..8eb2547 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -800,15 +800,20 @@ typedef struct { int mflags; bool skipUserNS; bool skipUnmounted; + bool temporary; } virLXCBasicMountInfo; static const virLXCBasicMountInfo lxcBasicMounts[] = { - { "proc", "/proc", "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, false, false }, - { "/proc/sys", "/proc/sys", NULL, MS_BIND|MS_RDONLY, false, false }, - { "sysfs", "/sys", "sysfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, false, false }, - { "securityfs", "/sys/kernel/security", "securityfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, true, true }, + { "proc", "/proc", "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, false, false, false }, + { "/proc/sys/net/ipv4", "TMP1", NULL, MS_BIND, false, false, true }, + { "/proc/sys/net/ipv6", "TMP2", NULL, MS_BIND, false, false, true }, + { "/proc/sys", "/proc/sys", NULL, MS_BIND|MS_RDONLY, false, false, false }, + { "TMP1", "/proc/sys/net/ipv4", NULL, MS_BIND, false, false, false }, + { "TMP2", "/proc/sys/net/ipv6", NULL, MS_BIND, false, false, false }, + { "sysfs", "/sys", "sysfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, false, false, false }, + { "securityfs", "/sys/kernel/security", "securityfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, true, true, false }, #if WITH_SELINUX - { SELINUX_MOUNT, SELINUX_MOUNT, "selinuxfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, true, true }, + { SELINUX_MOUNT, SELINUX_MOUNT, "selinuxfs", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, true, true, false }, #endif }; @@ -885,14 +890,23 @@ static int lxcContainerSetReadOnly(void) static int lxcContainerMountBasicFS(bool userns_enabled, bool netns_disabled) { - size_t i; + size_t i, j; int rc = -1; char* mnt_src = NULL; + char* mnt_dst = NULL; int mnt_mflags; + char **tmpkeys = NULL; + char **tmppaths = NULL; + size_t nmounts = ARRAY_CARDINALITY(lxcBasicMounts); VIR_DEBUG("Mounting basic filesystems"); - for (i = 0; i < ARRAY_CARDINALITY(lxcBasicMounts); i++) { + if (VIR_ALLOC_N(tmpkeys, nmounts) < 0 || + VIR_ALLOC_N(tmppaths, nmounts) < 0) { + goto cleanup; + } + + for (i = 0; i < nmounts; i++) { bool bindOverReadonly; virLXCBasicMountInfo const *mnt = &lxcBasicMounts[i]; @@ -906,11 +920,36 @@ static int lxcContainerMountBasicFS(bool userns_enabled, goto cleanup; mnt_mflags = MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY|MS_BIND; } else { - if (VIR_STRDUP(mnt_src, mnt->src) < 0) + /* Look for potential temporary folder match */ + for (j = 0; j < i; j++) { + if (STREQ_NULLABLE(mnt->src, tmpkeys[j])) { + if (VIR_STRDUP(mnt_src, tmppaths[j]) < 0) + goto cleanup; + break; + } + } + if (!mnt_src && VIR_STRDUP(mnt_src, mnt->src) < 0) goto cleanup; mnt_mflags = mnt->mflags; } + if (mnt->temporary) { + char tmppath[] = "/tmp/mount-XXXXXX"; + if (mkdtemp(tmppath) == NULL) { + virReportSystemError(errno, + _("Failed to create temporary folder %s"), + tmppath); + } + if (VIR_STRDUP(tmppaths[i], tmppath) < 0 || + VIR_STRDUP(tmpkeys[i], mnt->dst) < 0 || + VIR_STRDUP(mnt_dst, tmppath) < 0) { + goto cleanup; + } + } else { + if (VIR_STRDUP(mnt_dst, mnt->dst) < 0) + goto cleanup; + } + VIR_DEBUG("Processing %s -> %s", mnt_src, mnt->dst); @@ -940,10 +979,18 @@ static int lxcContainerMountBasicFS(bool userns_enabled, continue; } - if (virFileMakePath(mnt->dst) < 0) { + /* Some source files or folders may not exist like /proc/sys/net/ipv6 + * as they may depend on a kernel module being loaded. */ + if (STRPREFIX(mnt_src, "/") && virFileExists(mnt_src)) { + VIR_DEBUG("Skipping: missing %s", mnt_src); + VIR_FREE(mnt_src); + continue; + } + + if (virFileMakePath(mnt_dst) < 0) { virReportSystemError(errno, _("Failed to mkdir %s"), - mnt_src); + mnt_dst); goto cleanup; } @@ -957,32 +1004,52 @@ static int lxcContainerMountBasicFS(bool userns_enabled, bindOverReadonly = !!(mnt_mflags & MS_RDONLY); VIR_DEBUG("Mount %s on %s type=%s flags=%x", - mnt_src, mnt->dst, mnt->type, mnt_mflags & ~MS_RDONLY); - if (mount(mnt_src, mnt->dst, mnt->type, mnt_mflags & ~MS_RDONLY, NULL) < 0) { + mnt_src, mnt_dst, mnt->type, mnt_mflags & ~MS_RDONLY); + if (mount(mnt_src, mnt_dst, mnt->type, mnt_mflags & ~MS_RDONLY, NULL) < 0) { virReportSystemError(errno, _("Failed to mount %s on %s type %s flags=%x"), - mnt_src, mnt->dst, NULLSTR(mnt->type), + mnt_src, mnt_dst, NULLSTR(mnt->type), mnt_mflags & ~MS_RDONLY); goto cleanup; } if (bindOverReadonly && - mount(mnt_src, mnt->dst, NULL, + mount(mnt_src, mnt_dst, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) { virReportSystemError(errno, _("Failed to re-mount %s on %s flags=%x"), - mnt_src, mnt->dst, + mnt_src, mnt_dst, MS_BIND|MS_REMOUNT|MS_RDONLY); goto cleanup; } VIR_FREE(mnt_src); + VIR_FREE(mnt_dst); } rc = 0; cleanup: + /* Cleanup temporary mounts */ + for (i = 0; i < nmounts; i++) { + virLXCBasicMountInfo const *mnt = &lxcBasicMounts[i]; + if (mnt->temporary) { + if (umount(tmppaths[i]) < 0) { + virReportSystemError(errno, + _("Failed to un-mount temporary %s"), + tmppaths[i]); + } + if (virFileDeleteTree(tmppaths[i]) < 0) + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to remove temporary folder %s"), + tmppaths[i]); + } + } + + virStringFreeList(tmpkeys); + virStringFreeList(tmppaths); VIR_FREE(mnt_src); + VIR_FREE(mnt_dst); VIR_DEBUG("rc=%d", rc); return rc; } -- 2.1.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list