From eadaa975480d10eb057eb72bf833888e88e948e8 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Wed, 23 Nov 2016 11:52:57 +0100 Subject: [PATCH] qemu: Enter the namespace on relabelling Instead of trying to fix our security drivers, we can use a simple trick to relabel paths in both namespace and the host. I mean, if we enter the namespace some paths are still shared with the host so any change done to them is visible from the host too. Therefore, we can just enter the namespace and call SetAllLabel()/RestoreAllLabel() from there. Yes, it has slight overhead because we have to fork in order to enter the namespace. But on the other hand, no complexity is added to our code. Signed-off-by: Michal Privoznik --- src/Makefile.am | 3 +- src/qemu/qemu_process.c | 15 ++--- src/qemu/qemu_security.c | 132 +++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_security.h | 39 ++++++++++++ 4 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 src/qemu/qemu_security.c create mode 100644 src/qemu/qemu_security.h diff --git a/src/Makefile.am b/src/Makefile.am index 92006eef19..b713787288 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -838,7 +838,8 @@ QEMU_DRIVER_SOURCES = \ qemu/qemu_monitor_json.h \ qemu/qemu_driver.c qemu/qemu_driver.h \ qemu/qemu_interface.c qemu/qemu_interface.h \ - qemu/qemu_capspriv.h + qemu/qemu_capspriv.h \ + qemu/qemu_security.c qemu/qemu_security.h XENAPI_DRIVER_SOURCES = \ xenapi/xenapi_driver.c xenapi/xenapi_driver.h \ diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 08859b8880..721ad6370f 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -45,6 +45,7 @@ #include "qemu_hotplug.h" #include "qemu_migration.h" #include "qemu_interface.h" +#include "qemu_security.h" #include "cpu/cpu.h" #include "datatypes.h" @@ -5591,10 +5592,10 @@ qemuProcessLaunch(virConnectPtr conn, goto cleanup; VIR_DEBUG("Setting domain security labels"); - if (virSecurityManagerSetAllLabel(driver->securityManager, - vm->def, - incoming ? incoming->path : NULL) < 0) - goto cleanup; + if (qemuSecuritySetAllLabel(driver, + vm, + incoming ? incoming->path : NULL) < 0) + goto cleanup; /* Security manager labeled all devices, therefore * if any operation from now on fails, we need to ask the caller to @@ -6131,9 +6132,9 @@ void qemuProcessStop(virQEMUDriverPtr driver, /* Reset Security Labels unless caller don't want us to */ if (!(flags & VIR_QEMU_PROCESS_STOP_NO_RELABEL)) - virSecurityManagerRestoreAllLabel(driver->securityManager, - vm->def, - !!(flags & VIR_QEMU_PROCESS_STOP_MIGRATED)); + qemuSecurityRestoreAllLabel(driver, vm, + !!(flags & VIR_QEMU_PROCESS_STOP_MIGRATED)); + virSecurityManagerReleaseLabel(driver->securityManager, vm->def); for (i = 0; i < vm->def->ndisks; i++) { diff --git a/src/qemu/qemu_security.c b/src/qemu/qemu_security.c new file mode 100644 index 0000000000..bfebfe42c3 --- /dev/null +++ b/src/qemu/qemu_security.c @@ -0,0 +1,132 @@ +/* + * qemu_security.c: QEMU security management + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Michal Privoznik + */ + +#include + +#include "qemu_domain.h" +#include "qemu_security.h" +#include "virlog.h" + +#define VIR_FROM_THIS VIR_FROM_QEMU + +VIR_LOG_INIT("qemu.qemu_process"); + +struct qemuSecuritySetRestoreAllLabelData { + bool set; + virQEMUDriverPtr driver; + virDomainObjPtr vm; + const char *stdin_path; + bool migrated; +}; + + +static int +qemuSecuritySetRestoreAllLabelHelper(pid_t pid, + void *opaque) +{ + struct qemuSecuritySetRestoreAllLabelData *data = opaque; + + virSecurityManagerPostFork(data->driver->securityManager); + + if (data->set) { + VIR_DEBUG("Setting up security labels inside namespace pid=%lld", + (long long) pid); + if (virSecurityManagerSetAllLabel(data->driver->securityManager, + data->vm->def, + data->stdin_path) < 0) + return -1; + } else { + VIR_DEBUG("Restoring security labels inside namespace pid=%lld", + (long long) pid); + if (virSecurityManagerRestoreAllLabel(data->driver->securityManager, + data->vm->def, + data->migrated) < 0) + return -1; + } + + return 0; +} + + +int +qemuSecuritySetAllLabel(virQEMUDriverPtr driver, + virDomainObjPtr vm, + const char *stdin_path) +{ + struct qemuSecuritySetRestoreAllLabelData data; + + memset(&data, 0, sizeof(data)); + + data.set = true; + data.driver = driver; + data.vm = vm; + data.stdin_path = stdin_path; + + if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) { + if (virSecurityManagerPreFork(driver->securityManager) < 0) + return -1; + if (virProcessRunInMountNamespace(vm->pid, + qemuSecuritySetRestoreAllLabelHelper, + &data) < 0) { + virSecurityManagerPostFork(driver->securityManager); + return -1; + } + virSecurityManagerPostFork(driver->securityManager); + + } else { + if (virSecurityManagerSetAllLabel(driver->securityManager, + vm->def, + stdin_path) < 0) + return -1; + } + return 0; +} + + +void +qemuSecurityRestoreAllLabel(virQEMUDriverPtr driver, + virDomainObjPtr vm, + bool migrated) +{ + struct qemuSecuritySetRestoreAllLabelData data; + + memset(&data, 0, sizeof(data)); + + data.driver = driver; + data.vm = vm; + data.migrated = migrated; + + if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) { + if (virSecurityManagerPreFork(driver->securityManager) < 0) + return; + + virProcessRunInMountNamespace(vm->pid, + qemuSecuritySetRestoreAllLabelHelper, + &data); + virSecurityManagerPostFork(driver->securityManager); + } else { + virSecurityManagerRestoreAllLabel(driver->securityManager, + vm->def, + migrated); + } +} diff --git a/src/qemu/qemu_security.h b/src/qemu/qemu_security.h new file mode 100644 index 0000000000..88c53e765e --- /dev/null +++ b/src/qemu/qemu_security.h @@ -0,0 +1,39 @@ +/* + * qemu_security.h: QEMU security management + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Authors: + * Michal Privoznik + */ + +#ifndef __QEMU_SECURITY_H__ +# define __QEMU_SECURITY_H__ + +# include + +# include "qemu_conf.h" +# include "domain_conf.h" + +int qemuSecuritySetAllLabel(virQEMUDriverPtr driver, + virDomainObjPtr vm, + const char *stdin_path); + +void qemuSecurityRestoreAllLabel(virQEMUDriverPtr driver, + virDomainObjPtr vm, + bool migrated); +#endif /* __QEMU_SECURITY_H__ */ -- GitLab