From b9757fea30785a92aa95ea675b9bc371e4fb2e8c Mon Sep 17 00:00:00 2001
From: Jamie Strandboge <jamie@canonical.com>
Date: Mon, 20 Jun 2011 11:53:24 +0800
Subject: [PATCH] apparmor: implement AppArmorSetFDLabel()

During a savevm operation, libvirt will now use fd migration if qemu
supports it. When the AppArmor driver is enabled, AppArmorSetFDLabel()
is used but since this function simply returns '0', the dynamic AppArmor
profile is not updated and AppArmor blocks access to the save file. This
patch implements AppArmorSetFDLabel() to get the pathname of the file by
resolving the fd symlink in /proc, and then gives that pathname to
reload_profile(), which fixes 'virsh save' when AppArmor is enabled.

Reference: https://launchpad.net/bugs/795800
---
 src/security/security_apparmor.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index f47ded7c32..4d77643e24 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -757,11 +757,31 @@ AppArmorRestoreSavedStateLabel(virSecurityManagerPtr mgr,
 }
 
 static int
-AppArmorSetFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
-                   virDomainObjPtr vm ATTRIBUTE_UNUSED,
-                   int fd ATTRIBUTE_UNUSED)
+AppArmorSetFDLabel(virSecurityManagerPtr mgr,
+                   virDomainObjPtr vm,
+                   int fd)
 {
-    return 0;
+    int rc = -1;
+    char *proc = NULL;
+    char *fd_path = NULL;
+
+    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+
+    if (secdef->imagelabel == NULL)
+        return 0;
+
+    if (virAsprintf(&proc, "/proc/self/fd/%d", fd) == -1) {
+        virReportOOMError();
+        return rc;
+    }
+
+    if (virFileResolveLink(proc, &fd_path) < 0) {
+        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
+                               "%s", _("could not find path for descriptor"));
+        return rc;
+    }
+
+    return reload_profile(mgr, vm, fd_path, true);
 }
 
 virSecurityDriver virAppArmorSecurityDriver = {