The libvirt sanlock plugin is intentionally leaking a file descriptor to QEMU. To enable QEMU to use this FD under SELinux, it must be labelled correctly. We dont want to use the svirt_image_t for this, since QEMU must not be allowed to actually use the FD. So instead we label it with svirt_t using virSecurityManagerSetProcessFDLabel * src/locking/domain_lock.c, src/locking/domain_lock.h, src/locking/lock_driver.h, src/locking/lock_driver_nop.c, src/locking/lock_driver_sanlock.c, src/locking/lock_manager.c, src/locking/lock_manager.h: Optionally pass an FD back to the hypervisor for security driver labelling * src/qemu/qemu_process.c: label the lock manager plugin FD with the process label --- src/locking/domain_lock.c | 11 ++++++----- src/locking/domain_lock.h | 3 ++- src/locking/lock_driver.h | 9 ++++++++- src/locking/lock_driver_nop.c | 4 ++-- src/locking/lock_driver_sanlock.c | 6 +++++- src/locking/lock_manager.c | 10 +++++++--- src/locking/lock_manager.h | 3 ++- src/qemu/qemu_process.c | 12 ++++++++++-- 8 files changed, 42 insertions(+), 16 deletions(-) diff --git a/src/locking/domain_lock.c b/src/locking/domain_lock.c index feb3f98..4544500 100644 --- a/src/locking/domain_lock.c +++ b/src/locking/domain_lock.c @@ -155,7 +155,8 @@ error: int virDomainLockProcessStart(virLockManagerPluginPtr plugin, virDomainObjPtr dom, - bool paused) + bool paused, + int *fd) { virLockManagerPtr lock; int ret; @@ -167,7 +168,7 @@ int virDomainLockProcessStart(virLockManagerPluginPtr plugin, if (paused) flags |= VIR_LOCK_MANAGER_ACQUIRE_REGISTER_ONLY; - ret = virLockManagerAcquire(lock, NULL, flags); + ret = virLockManagerAcquire(lock, NULL, flags, fd); virLockManagerFree(lock); @@ -200,7 +201,7 @@ int virDomainLockProcessResume(virLockManagerPluginPtr plugin, if (!(lock = virDomainLockManagerNew(plugin, dom, true))) return -1; - ret = virLockManagerAcquire(lock, state, 0); + ret = virLockManagerAcquire(lock, state, 0, NULL); virLockManagerFree(lock); return ret; @@ -236,7 +237,7 @@ int virDomainLockDiskAttach(virLockManagerPluginPtr plugin, if (virDomainLockManagerAddDisk(lock, disk) < 0) goto cleanup; - if (virLockManagerAcquire(lock, NULL, 0) < 0) + if (virLockManagerAcquire(lock, NULL, 0, NULL) < 0) goto cleanup; ret = 0; @@ -285,7 +286,7 @@ int virDomainLockLeaseAttach(virLockManagerPluginPtr plugin, if (virDomainLockManagerAddLease(lock, lease) < 0) goto cleanup; - if (virLockManagerAcquire(lock, NULL, 0) < 0) + if (virLockManagerAcquire(lock, NULL, 0, NULL) < 0) goto cleanup; ret = 0; diff --git a/src/locking/domain_lock.h b/src/locking/domain_lock.h index 40fadd4..dd35c7c 100644 --- a/src/locking/domain_lock.h +++ b/src/locking/domain_lock.h @@ -28,7 +28,8 @@ int virDomainLockProcessStart(virLockManagerPluginPtr plugin, virDomainObjPtr dom, - bool paused); + bool paused, + int *fd); int virDomainLockProcessPause(virLockManagerPluginPtr plugin, virDomainObjPtr dom, char **state); diff --git a/src/locking/lock_driver.h b/src/locking/lock_driver.h index 3b90efa..94145cb 100644 --- a/src/locking/lock_driver.h +++ b/src/locking/lock_driver.h @@ -215,6 +215,7 @@ typedef int (*virLockDriverAddResource)(virLockManagerPtr man, * @manager: the lock manager context * @state: the current lock state * @flags: optional flags, currently unused + * @fd: optional return the leaked FD * * Start managing resources for the object. This * must be called from the PID that represents the @@ -223,11 +224,17 @@ typedef int (*virLockDriverAddResource)(virLockManagerPtr man, * The optional state contains information about the * locks previously held for the object. * + * The file descriptor returned in @fd is one that + * is intentionally leaked and should not be closed. + * It is returned so that it can be labelled by the + * security managers (if required). + * * Returns 0 on success, or -1 on failure */ typedef int (*virLockDriverAcquire)(virLockManagerPtr man, const char *state, - unsigned int flags); + unsigned int flags, + int *fd); /** * virLockDriverRelease: diff --git a/src/locking/lock_driver_nop.c b/src/locking/lock_driver_nop.c index 43374e4..0fab54c 100644 --- a/src/locking/lock_driver_nop.c +++ b/src/locking/lock_driver_nop.c @@ -67,9 +67,9 @@ static int virLockManagerNopAddResource(virLockManagerPtr lock ATTRIBUTE_UNUSED, static int virLockManagerNopAcquire(virLockManagerPtr lock ATTRIBUTE_UNUSED, const char *state ATTRIBUTE_UNUSED, - unsigned int flags ATTRIBUTE_UNUSED) + unsigned int flags ATTRIBUTE_UNUSED, + int *fd ATTRIBUTE_UNUSED) { - return 0; } diff --git a/src/locking/lock_driver_sanlock.c b/src/locking/lock_driver_sanlock.c index ad3a65a..76e6ddc 100644 --- a/src/locking/lock_driver_sanlock.c +++ b/src/locking/lock_driver_sanlock.c @@ -667,7 +667,8 @@ static int virLockManagerSanlockAddResource(virLockManagerPtr lock, static int virLockManagerSanlockAcquire(virLockManagerPtr lock, const char *state, - unsigned int flags) + unsigned int flags, + int *fd) { virLockManagerSanlockPrivatePtr priv = lock->privateData; struct sanlk_options *opt; @@ -788,6 +789,9 @@ static int virLockManagerSanlockAcquire(virLockManagerPtr lock, VIR_FREE(res_args); } + if (fd) + *fd = sock; + return 0; error: diff --git a/src/locking/lock_manager.c b/src/locking/lock_manager.c index c28ca86..4ee7f44 100644 --- a/src/locking/lock_manager.c +++ b/src/locking/lock_manager.c @@ -329,13 +329,17 @@ int virLockManagerAddResource(virLockManagerPtr lock, int virLockManagerAcquire(virLockManagerPtr lock, const char *state, - unsigned int flags) + unsigned int flags, + int *fd) { - VIR_DEBUG("lock=%p state='%s' flags=%u", lock, NULLSTR(state), flags); + VIR_DEBUG("lock=%p state='%s' flags=%u fd=%p", lock, NULLSTR(state), flags, fd); CHECK_MANAGER(drvAcquire, -1); - return lock->driver->drvAcquire(lock, state, flags); + if (fd) + *fd = -1; + + return lock->driver->drvAcquire(lock, state, flags, fd); } diff --git a/src/locking/lock_manager.h b/src/locking/lock_manager.h index 315c798..0fb3bb7 100644 --- a/src/locking/lock_manager.h +++ b/src/locking/lock_manager.h @@ -53,7 +53,8 @@ int virLockManagerAddResource(virLockManagerPtr manager, int virLockManagerAcquire(virLockManagerPtr manager, const char *state, - unsigned int flags); + unsigned int flags, + int *fd); int virLockManagerRelease(virLockManagerPtr manager, char **state, unsigned int flags); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index e00d5a8..445dac9 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -2119,6 +2119,7 @@ static int qemuProcessHook(void *data) { struct qemuProcessHookData *h = data; int ret = -1; + int fd; /* Some later calls want pid present */ h->vm->pid = getpid(); @@ -2127,7 +2128,8 @@ static int qemuProcessHook(void *data) if (virDomainLockProcessStart(h->driver->lockManager, h->vm, /* QEMU is always pased initially */ - true) < 0) + true, + &fd) < 0) goto cleanup; if (qemuProcessLimits(h->driver) < 0) @@ -2149,10 +2151,16 @@ static int qemuProcessHook(void *data) if (qemuProcessInitNumaMemoryPolicy(h->vm) < 0) return -1; - VIR_DEBUG("Setting up security labeling"); + VIR_DEBUG("Setting up security labelling"); if (virSecurityManagerSetProcessLabel(h->driver->securityManager, h->vm) < 0) goto cleanup; + if (fd != -1) { + VIR_DEBUG("Setting up lock manager FD labelling"); + if (virSecurityManagerSetProcessFDLabel(h->driver->securityManager, h->vm, fd) < 0) + goto cleanup; + } + ret = 0; cleanup: -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list