diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 025816ab1b..d4038b21f2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1209,6 +1209,7 @@ virFileFclose; virFileFdopen; virFileRewrite; virFileTouch; +virFileUpdatePerm; # virkeycode.h diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 349274b251..78899a4734 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -456,6 +456,8 @@ qemudStartup(int privileged) { int rc; virConnectPtr conn = NULL; char ebuf[1024]; + char *membase = NULL; + char *mempath = NULL; if (VIR_ALLOC(qemu_driver) < 0) return -1; @@ -660,23 +662,26 @@ qemudStartup(int privileged) { */ if (qemu_driver->hugetlbfs_mount && qemu_driver->hugetlbfs_mount[0] == '/') { - char *mempath = NULL; - if (virAsprintf(&mempath, "%s/libvirt/qemu", qemu_driver->hugetlbfs_mount) < 0) + if (virAsprintf(&membase, "%s/libvirt", + qemu_driver->hugetlbfs_mount) < 0 || + virAsprintf(&mempath, "%s/qemu", membase) < 0) goto out_of_memory; if (virFileMakePath(mempath) < 0) { virReportSystemError(errno, _("unable to create hugepage path %s"), mempath); - VIR_FREE(mempath); goto error; } - if (qemu_driver->privileged && - chown(mempath, qemu_driver->user, qemu_driver->group) < 0) { - virReportSystemError(errno, - _("unable to set ownership on %s to %d:%d"), - mempath, qemu_driver->user, qemu_driver->group); - VIR_FREE(mempath); - goto error; + if (qemu_driver->privileged) { + if (virFileUpdatePerm(membase, 0, S_IXGRP | S_IXOTH) < 0) + goto error; + if (chown(mempath, qemu_driver->user, qemu_driver->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership on %s to %d:%d"), + mempath, qemu_driver->user, + qemu_driver->group); + goto error; + } } qemu_driver->hugepage_path = mempath; @@ -737,6 +742,8 @@ error: virConnectClose(conn); VIR_FREE(base); VIR_FREE(driverConf); + VIR_FREE(membase); + VIR_FREE(mempath); qemudShutdown(); return -1; } diff --git a/src/util/virfile.c b/src/util/virfile.c index 66160dc902..db3d737d96 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -437,3 +437,40 @@ int virFileTouch(const char *path, mode_t mode) return 0; } + + +#define MODE_BITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) + +int virFileUpdatePerm(const char *path, + mode_t mode_remove, + mode_t mode_add) +{ + struct stat sb; + mode_t mode; + + if (mode_remove & ~MODE_BITS || mode_add & ~MODE_BITS) { + virFileError(VIR_ERR_INVALID_ARG, "%s", _("invalid mode")); + return -1; + } + + if (stat(path, &sb) < 0) { + virReportSystemError(errno, _("cannot stat '%s'"), path); + return -1; + } + + mode = sb.st_mode & MODE_BITS; + + if ((mode & mode_remove) == 0 && (mode & mode_add) == mode_add) + return 0; + + mode &= MODE_BITS ^ mode_remove; + mode |= mode_add; + + if (chmod(path, mode) < 0) { + virReportSystemError(errno, _("cannot change permission of '%s'"), + path); + return -1; + } + + return 0; +} diff --git a/src/util/virfile.h b/src/util/virfile.h index 184677c597..05f50480e6 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -83,4 +83,8 @@ int virFileRewrite(const char *path, int virFileTouch(const char *path, mode_t mode); +int virFileUpdatePerm(const char *path, + mode_t mode_remove, + mode_t mode_add); + #endif /* __VIR_FILES_H */