]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: add security label setting to virCommand
authorLaine Stump <laine@laine.org>
Fri, 1 Feb 2013 19:32:37 +0000 (14:32 -0500)
committerLaine Stump <laine@laine.org>
Wed, 13 Feb 2013 21:11:15 +0000 (16:11 -0500)
virCommand gets two new APIs: virCommandSetSELinuxLabel() and
virCommandSetAppArmorProfile(), which both save a copy of a
null-terminated string in the virCommand. During virCommandRun, if the
string is non-NULL and we've been compiled with AppArmor and/or
SELinux security driver support, the appropriate security library
function is called for the child process, using the string that was
previously set. In the case of SELinux, setexeccon_raw() is called,
and for AppArmor, aa_change_profile() is called.

This functionality has been added so that users of virCommand can use
the upcoming virSecurityManagerSetChildProcessLabel() prior to running
a child process, rather than needing to setup a hook function to be
called (and in turn call virSecurityManagerSetProcessLabel()) *during*
the setup of the child process.

src/Makefile.am
src/libvirt_private.syms
src/util/vircommand.c
src/util/vircommand.h

index 12319e094c9a115590a4a88d7c08ee5fef8095e4..0d2f2f8365fb6ccefcd06fdee5d2b697e984e40b 100644 (file)
@@ -765,7 +765,8 @@ libvirt_util_la_CFLAGS = $(CAPNG_CFLAGS) $(YAJL_CFLAGS) $(LIBNL_CFLAGS) \
                $(DBUS_CFLAGS) $(LDEXP_LIBM)
 libvirt_util_la_LIBADD = $(CAPNG_LIBS) $(YAJL_LIBS) $(LIBNL_LIBS) \
                $(THREAD_LIBS) $(AUDIT_LIBS) $(DEVMAPPER_LIBS) \
-               $(LIB_CLOCK_GETTIME) $(DBUS_LIBS) $(MSCOM_LIBS) $(LIBXML_LIBS)
+               $(LIB_CLOCK_GETTIME) $(DBUS_LIBS) $(MSCOM_LIBS) $(LIBXML_LIBS) \
+               $(SECDRIVER_LIBS)
 
 
 noinst_LTLIBRARIES += libvirt_conf.la
index 511a686f0f13d129889940e3766e88b4ae49d6c7..8241e6f81ff24ba8c3afccb07ce72290dd108cd0 100644 (file)
@@ -156,6 +156,7 @@ virCommandPreserveFD;
 virCommandRequireHandshake;
 virCommandRun;
 virCommandRunAsync;
+virCommandSetAppArmorProfile;
 virCommandSetErrorBuffer;
 virCommandSetErrorFD;
 virCommandSetGID;
@@ -165,6 +166,7 @@ virCommandSetOutputBuffer;
 virCommandSetOutputFD;
 virCommandSetPidFile;
 virCommandSetPreExecHook;
+virCommandSetSELinuxLabel;
 virCommandSetUID;
 virCommandSetWorkingDirectory;
 virCommandToString;
index dd442abc54cf7ee3bec55e375f94c80f8e310e9d..0699fdbae1839cbf37d70f27839c55a7eb2bd5af 100644 (file)
 # include <cap-ng.h>
 #endif
 
+#if defined(WITH_SECDRIVER_SELINUX)
+# include <selinux/selinux.h>
+#endif
+#if defined(WITH_SECDRIVER_APPARMOR)
+# include <sys/apparmor.h>
+#endif
+
 #include "vircommand.h"
 #include "viralloc.h"
 #include "virerror.h"
@@ -103,6 +110,12 @@ struct _virCommand {
     uid_t uid;
     gid_t gid;
     unsigned long long capabilities;
+#if defined(WITH_SECDRIVER_SELINUX)
+    char *seLinuxLabel;
+#endif
+#if defined(WITH_SECDRIVER_APPARMOR)
+    char *appArmorProfile;
+#endif
 };
 
 static int virCommandHandshakeChild(virCommandPtr cmd);
@@ -606,6 +619,32 @@ virExec(virCommandPtr cmd)
            goto fork_error;
     }
 
+# if defined(WITH_SECDRIVER_SELINUX)
+    if (cmd->seLinuxLabel) {
+        VIR_DEBUG("Setting child security label to %s", cmd->seLinuxLabel);
+        if (setexeccon_raw(cmd->seLinuxLabel) == -1) {
+            virReportSystemError(errno,
+                                 _("unable to set SELinux security context "
+                                   "'%s' for '%s'"),
+                                 cmd->seLinuxLabel, cmd->args[0]);
+            if (security_getenforce() == 1)
+                goto fork_error;
+        }
+    }
+# endif
+# if defined(WITH_SECDRIVER_APPARMOR)
+    if (cmd->appArmorProfile) {
+        VIR_DEBUG("Setting child AppArmor profile to %s", cmd->appArmorProfile);
+        if (aa_change_profile(cmd->appArmorProfile) < 0) {
+            virReportSystemError(errno,
+                                 _("unable to set AppArmor profile '%s' "
+                                   "for '%s'"),
+                                 cmd->appArmorProfile, cmd->args[0]);
+            goto fork_error;
+        }
+    }
+# endif
+
     if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1) {
         VIR_DEBUG("Setting child uid:gid to %d:%d",
                   (int)cmd->uid, (int)cmd->gid);
@@ -965,6 +1004,56 @@ virCommandAllowCap(virCommandPtr cmd,
 }
 
 
+/**
+ * virCommandSetSELinuxLabel:
+ * @cmd: the command to modify
+ * @label: the SELinux label to use for the child process
+ *
+ * Saves a copy of @label to use when setting the SELinux context
+ * label (with setexeccon_raw()) after the child process has been
+ * started. If SELinux isn't compiled into libvirt, or if label is
+ * NULL, nothing will be done.
+ */
+void
+virCommandSetSELinuxLabel(virCommandPtr cmd,
+                          const char *label ATTRIBUTE_UNUSED)
+{
+    if (!cmd || cmd->has_error)
+        return;
+
+#if defined(WITH_SECDRIVER_SELINUX)
+    VIR_FREE(cmd->seLinuxLabel);
+    if (label && !(cmd->seLinuxLabel = strdup(label)))
+        cmd->has_error = ENOMEM;
+#endif
+    return;
+}
+
+
+/**
+ * virCommandSetAppArmorProfile:
+ * @cmd: the command to modify
+ * @profile: the AppArmor profile to use
+ *
+ * Saves a copy of @profile to use when aa_change_profile() after the
+ * child process has been started. If AppArmor support isn't
+ * configured into libvirt, or if profile is NULL, nothing will be done.
+ */
+void
+virCommandSetAppArmorProfile(virCommandPtr cmd,
+                             const char *profile ATTRIBUTE_UNUSED)
+{
+    if (!cmd || cmd->has_error)
+        return;
+
+#if defined(WITH_SECDRIVER_APPARMOR)
+    VIR_FREE(cmd->appArmorProfile);
+    if (profile && !(cmd->appArmorProfile = strdup(profile)))
+        cmd->has_error = ENOMEM;
+#endif
+    return;
+}
+
 
 /**
  * virCommandDaemonize:
@@ -2525,6 +2614,12 @@ virCommandFree(virCommandPtr cmd)
 
     VIR_FREE(cmd->transfer);
     VIR_FREE(cmd->preserve);
+#if defined(WITH_SECDRIVER_SELINUX)
+    VIR_FREE(cmd->seLinuxLabel);
+#endif
+#if defined(WITH_SECDRIVER_APPARMOR)
+    VIR_FREE(cmd->appArmorProfile);
+#endif
 
     VIR_FREE(cmd);
 }
index a4022fa0f1d1963f8393b8a508f68c6fc7b01b61..6c13795b3ad706067df7e5e89101467e3c800b95 100644 (file)
@@ -70,6 +70,12 @@ void virCommandClearCaps(virCommandPtr cmd);
 void virCommandAllowCap(virCommandPtr cmd,
                         int capability);
 
+void virCommandSetSELinuxLabel(virCommandPtr cmd,
+                               const char *label);
+
+void virCommandSetAppArmorProfile(virCommandPtr cmd,
+                                  const char *profile);
+
 void virCommandDaemonize(virCommandPtr cmd);
 
 void virCommandNonblockingFDs(virCommandPtr cmd);