]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
Add a function to the security driver API that sets the label of an open fd.
authorLaine Stump <laine@laine.org>
Sun, 23 Jan 2011 21:02:42 +0000 (16:02 -0500)
committerLaine Stump <laine@laine.org>
Wed, 26 Jan 2011 14:03:11 +0000 (09:03 -0500)
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
src/security/security_apparmor.c
src/security/security_dac.c
src/security/security_driver.h
src/security/security_manager.c
src/security/security_manager.h
src/security/security_nop.c
src/security/security_selinux.c
src/security/security_stack.c

index f60489ccb6683984bcd7fa434151f105b59c4977..c7e47722508f099db9e2953f5590cc2156727c8e 100644 (file)
@@ -723,6 +723,7 @@ virSecurityManagerRestoreAllLabel;
 virSecurityManagerRestoreHostdevLabel;
 virSecurityManagerRestoreSavedStateLabel;
 virSecurityManagerSetAllLabel;
+virSecurityManagerSetFDLabel;
 virSecurityManagerSetImageLabel;
 virSecurityManagerSetHostdevLabel;
 virSecurityManagerSetProcessLabel;
index d82ba73f65f51e68812cf8ec2885ebba32fa8d95..7dc01acbb94daea49abf207ff4fa3b4cd290ea6c 100644 (file)
@@ -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,
 };
index 0f24034995e8d0316e9f47474ce98997a94861a1..52353a3abb23044143afc7061fd475333f06fc0b 100644 (file)
@@ -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,
 };
index e5a8d41ffdd8205b9996738596cb2a85e1d9b4ef..42dfcb83838fd7765ceb4b954b5f207b623f6799 100644 (file)
@@ -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);
index 6406161cfa7304272d47eff2343190bcb6e47ed8..0246dd88bd3d23aa2be5ec8a5694a9a9ee752e55 100644 (file)
@@ -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;
+}
index 189b6b4d5d8d25e63f34f4ba83b25fb42917159d..3f88801870a4058437d2c2cbc6e455e23fd259e6 100644 (file)
@@ -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__ */
index 6d7cb4741941776d72bdbeb291f812b8299abb22..24d36fe1f572043c06e7b63084b90a54d97e30c5 100644 (file)
@@ -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,
 };
index 7b71fd9fdc48fd11d932c1a7beaddec8d729542d..24609bc2e8be95f28860278f9c0787164ba67fda 100644 (file)
@@ -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,
 };
index e8bb058090ee4eb83e0c4685807ee09e151766ca..79b3e1f30f4c008f4e1a0d65846bed4e4f5f1ecc 100644 (file)
@@ -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,
 };