virCommandDaemonize(cmd);
virCommandRequireHandshake(cmd);
- virSecurityManagerPreFork(driver->securityManager);
+ if (virSecurityManagerPreFork(driver->securityManager) < 0)
+ goto cleanup;
ret = virCommandRun(cmd, NULL);
virSecurityManagerPostFork(driver->securityManager);
typedef const char *(*virSecurityDriverGetModel) (virSecurityManagerPtr mgr);
typedef const char *(*virSecurityDriverGetDOI) (virSecurityManagerPtr mgr);
+typedef int (*virSecurityDriverPreFork) (virSecurityManagerPtr mgr);
+
typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityManagerPtr mgr,
virDomainDefPtr def,
virDomainDiskDefPtr disk);
virSecurityDriverGetModel getModel;
virSecurityDriverGetDOI getDOI;
+ virSecurityDriverPreFork preFork;
+
virSecurityDomainSecurityVerify domainSecurityVerify;
virSecurityDomainSetImageLabel domainSetSecurityImageLabel;
/*
* Must be called before fork()'ing to ensure mutex state
- * is sane for the child to use
+ * is sane for the child to use. A negative return means the
+ * child must not be forked; a successful return must be
+ * followed by a call to virSecurityManagerPostFork() in both
+ * parent and child.
*/
-void virSecurityManagerPreFork(virSecurityManagerPtr mgr)
+int virSecurityManagerPreFork(virSecurityManagerPtr mgr)
{
+ int ret = 0;
+
virObjectLock(mgr);
+ if (mgr->drv->preFork) {
+ ret = mgr->drv->preFork(mgr);
+ if (ret < 0)
+ virObjectUnlock(mgr);
+ }
+
+ return ret;
}
bool requireConfined,
bool dynamicOwnership);
-void virSecurityManagerPreFork(virSecurityManagerPtr mgr);
+int virSecurityManagerPreFork(virSecurityManagerPtr mgr);
void virSecurityManagerPostFork(virSecurityManagerPtr mgr);
void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr);
return virSecurityManagerGetDOI(virSecurityStackGetPrimary(mgr));
}
+static int
+virSecurityStackPreFork(virSecurityManagerPtr mgr)
+{
+ virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
+ virSecurityStackItemPtr item = priv->itemsHead;
+ int rc = 0;
+
+ /* XXX For now, we rely on no driver having any state that requires
+ * rollback if a later driver in the stack fails; if this changes,
+ * we'd need to split this into transaction semantics by dividing
+ * the work into prepare/commit/abort. */
+ for (; item; item = item->next) {
+ if (virSecurityManagerPreFork(item->securityManager) < 0) {
+ rc = -1;
+ break;
+ }
+ }
+
+ return rc;
+}
+
static int
virSecurityStackVerify(virSecurityManagerPtr mgr,
virDomainDefPtr def)
.getModel = virSecurityStackGetModel,
.getDOI = virSecurityStackGetDOI,
+ .preFork = virSecurityStackPreFork,
+
.domainSecurityVerify = virSecurityStackVerify,
.domainSetSecurityImageLabel = virSecurityStackSetSecurityImageLabel,