[libvirt] [PATCH 1/3] Add a function to the security driver API that sets the label of an open fd.

Laine Stump laine at laine.org
Tue Jan 25 09:24:18 UTC 2011


A need was found to set the SELinux context label on an open fd (a
pipe, as a matter of fact). This patch adds a function to the security
driver API that will set the label on an open fd to secdef.label. For
all drivers other than the SELinux driver, it's a NOP. For the SElinux
driver, it calls fsetfilecon().

If the return is a failure, it only returns error up to the caller if
1) the desired label is different from the existing label, 2) the
destination fd is of a type that supports setting the selinux context,
and 3) selinux is in enforcing mode. Otherwise it will return
success. This follows the pattern of the existing function
SELinuxSetFilecon().
---
 src/libvirt_private.syms         |    1 +
 src/security/security_apparmor.c |   10 +++++++
 src/security/security_dac.c      |   10 +++++++
 src/security/security_driver.h   |    6 +++-
 src/security/security_manager.c  |   11 +++++++
 src/security/security_manager.h  |    3 ++
 src/security/security_nop.c      |    9 ++++++
 src/security/security_selinux.c  |   54 ++++++++++++++++++++++++++++++++++++++
 src/security/security_stack.c    |   18 ++++++++++++
 9 files changed, 121 insertions(+), 1 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f60489c..c7e4772 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -723,6 +723,7 @@ virSecurityManagerRestoreAllLabel;
 virSecurityManagerRestoreHostdevLabel;
 virSecurityManagerRestoreSavedStateLabel;
 virSecurityManagerSetAllLabel;
+virSecurityManagerSetFDLabel;
 virSecurityManagerSetImageLabel;
 virSecurityManagerSetHostdevLabel;
 virSecurityManagerSetProcessLabel;
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index d82ba73..7dc01ac 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -798,6 +798,14 @@ AppArmorRestoreSavedStateLabel(virSecurityManagerPtr mgr,
     return reload_profile(mgr, vm, NULL, false);
 }
 
+static int
+AppArmorSetFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                   virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                   int fd ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
 virSecurityDriver virAppArmorSecurityDriver = {
     0,
     SECURITY_APPARMOR_NAME,
@@ -831,4 +839,6 @@ virSecurityDriver virAppArmorSecurityDriver = {
 
     AppArmorSetSavedStateLabel,
     AppArmorRestoreSavedStateLabel,
+
+    AppArmorSetFDLabel,
 };
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 0f24034..52353a3 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -675,6 +675,14 @@ virSecurityDACClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
     return 0;
 }
 
+static int
+virSecurityDACSetFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                         virDomainObjPtr vm ATTRIBUTE_UNUSED,
+                         int fd ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
 
 virSecurityDriver virSecurityDriverDAC = {
     sizeof(virSecurityDACData),
@@ -710,4 +718,6 @@ virSecurityDriver virSecurityDriverDAC = {
 
     virSecurityDACSetSavedStateLabel,
     virSecurityDACRestoreSavedStateLabel,
+
+    virSecurityDACSetFDLabel,
 };
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
index e5a8d41..42dfcb8 100644
--- a/src/security/security_driver.h
+++ b/src/security/security_driver.h
@@ -79,7 +79,9 @@ typedef int (*virSecurityDomainSetProcessLabel) (virSecurityManagerPtr mgr,
                                                  virDomainObjPtr vm);
 typedef int (*virSecurityDomainSecurityVerify) (virSecurityManagerPtr mgr,
                                                 virDomainDefPtr def);
-
+typedef int (*virSecurityDomainSetFDLabel) (virSecurityManagerPtr mgr,
+                                            virDomainObjPtr vm,
+                                            int fd);
 
 struct _virSecurityDriver {
     size_t privateDataLen;
@@ -114,6 +116,8 @@ struct _virSecurityDriver {
 
     virSecurityDomainSetSavedStateLabel domainSetSavedStateLabel;
     virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel;
+
+    virSecurityDomainSetFDLabel domainSetSecurityFDLabel;
 };
 
 virSecurityDriverPtr virSecurityDriverLookup(const char *name);
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index 6406161..0246dd8 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -323,3 +323,14 @@ int virSecurityManagerVerify(virSecurityManagerPtr mgr,
     virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
     return -1;
 }
+
+int virSecurityManagerSetFDLabel(virSecurityManagerPtr mgr,
+                                 virDomainObjPtr vm,
+                                 int fd)
+{
+    if (mgr->drv->domainSetSecurityFDLabel)
+        return mgr->drv->domainSetSecurityFDLabel(mgr, vm, fd);
+
+    virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+    return -1;
+}
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index 189b6b4..3f88801 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -91,5 +91,8 @@ int virSecurityManagerSetProcessLabel(virSecurityManagerPtr mgr,
                                       virDomainObjPtr vm);
 int virSecurityManagerVerify(virSecurityManagerPtr mgr,
                              virDomainDefPtr def);
+int virSecurityManagerSetFDLabel(virSecurityManagerPtr mgr,
+                                 virDomainObjPtr vm,
+                                 int fd);
 
 #endif /* VIR_SECURITY_MANAGER_H__ */
diff --git a/src/security/security_nop.c b/src/security/security_nop.c
index 6d7cb47..24d36fe 100644
--- a/src/security/security_nop.c
+++ b/src/security/security_nop.c
@@ -149,6 +149,13 @@ static int virSecurityDomainVerifyNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED
     return 0;
 }
 
+static int virSecurityDomainSetFDLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                                          virDomainObjPtr sec ATTRIBUTE_UNUSED,
+                                          int fd ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
 virSecurityDriver virSecurityDriverNop = {
     0,
     "none",
@@ -182,4 +189,6 @@ virSecurityDriver virSecurityDriverNop = {
 
     virSecurityDomainSetSavedStateLabelNop,
     virSecurityDomainRestoreSavedStateLabelNop,
+
+    virSecurityDomainSetFDLabelNop,
 };
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 7b71fd9..24609bc 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -371,6 +371,45 @@ SELinuxSetFilecon(const char *path, char *tcon)
     return 0;
 }
 
+static int
+SELinuxFSetFilecon(int fd, char *tcon)
+{
+    security_context_t econ;
+
+    VIR_INFO("Setting SELinux context on fd %d to '%s'", fd, tcon);
+
+    if (fsetfilecon(fd, tcon) < 0) {
+        int fsetfilecon_errno = errno;
+
+        if (fgetfilecon(fd, &econ) >= 0) {
+            if (STREQ(tcon, econ)) {
+                freecon(econ);
+                /* It's alright, there's nothing to change anyway. */
+                return 0;
+            }
+            freecon(econ);
+        }
+
+        /* if the error complaint is related to an image hosted on
+         * an nfs mount, or a usbfs/sysfs filesystem not supporting
+         * labelling, then just ignore it & hope for the best.
+         * The user hopefully set one of the necessary SELinux
+         * virt_use_{nfs,usb,pci}  boolean tunables to allow it...
+         */
+        if (fsetfilecon_errno != EOPNOTSUPP) {
+            virReportSystemError(fsetfilecon_errno,
+                                 _("unable to set security context '%s' on fd %d"),
+                                 tcon, fd);
+            if (security_getenforce() == 1)
+                return -1;
+        } else {
+            VIR_INFO("Setting security context '%s' on fd %d not supported",
+                     tcon, fd);
+        }
+    }
+    return 0;
+}
+
 /* Set fcon to the appropriate label for path and mode, or return -1.  */
 static int
 getContext(const char *newpath, mode_t mode, security_context_t *fcon)
@@ -1087,6 +1126,19 @@ SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
     return 0;
 }
 
+static int
+SELinuxSetFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+                  virDomainObjPtr vm,
+                  int fd)
+{
+    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
+
+    if (secdef->imagelabel == NULL)
+        return 0;
+
+    return SELinuxFSetFilecon(fd, secdef->imagelabel);
+}
+
 virSecurityDriver virSecurityDriverSELinux = {
     0,
     SECURITY_SELINUX_NAME,
@@ -1120,4 +1172,6 @@ virSecurityDriver virSecurityDriverSELinux = {
 
     SELinuxSetSavedStateLabel,
     SELinuxRestoreSavedStateLabel,
+
+    SELinuxSetFDLabel,
 };
diff --git a/src/security/security_stack.c b/src/security/security_stack.c
index e8bb058..79b3e1f 100644
--- a/src/security/security_stack.c
+++ b/src/security/security_stack.c
@@ -364,6 +364,22 @@ virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
     return rc;
 }
 
+static int
+virSecurityStackSetFDLabel(virSecurityManagerPtr mgr,
+                           virDomainObjPtr vm,
+                           int fd)
+{
+    virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+    int rc = 0;
+
+    if (virSecurityManagerSetFDLabel(priv->secondary, vm, fd) < 0)
+        rc = -1;
+    if (virSecurityManagerSetFDLabel(priv->primary, vm, fd) < 0)
+        rc = -1;
+
+    return rc;
+}
+
 
 virSecurityDriver virSecurityDriverStack = {
     sizeof(virSecurityStackData),
@@ -398,4 +414,6 @@ virSecurityDriver virSecurityDriverStack = {
 
     virSecurityStackSetSavedStateLabel,
     virSecurityStackRestoreSavedStateLabel,
+
+    virSecurityStackSetFDLabel,
 };
-- 
1.7.3.4




More information about the libvir-list mailing list