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 <mprivozn(a)redhat.com>
---
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 07a28335a..073d50723 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 b87e5af56..be569f3b3 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"
@@ -5522,10 +5523,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
@@ -6060,9 +6061,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 000000000..bfebfe42c
--- /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
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Michal Privoznik <mprivozn(a)redhat.com>
+ */
+
+#include <config.h>
+
+#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 000000000..88c53e765
--- /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
+ * <
http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Michal Privoznik <mprivozn(a)redhat.com>
+ */
+
+#ifndef __QEMU_SECURITY_H__
+# define __QEMU_SECURITY_H__
+
+# include <stdbool.h>
+
+# 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__ */
--
2.11.0