提交 6a47028a 编写于 作者: E Eric Blake

security: framework for driver PreFork handler

https://bugzilla.redhat.com/show_bug.cgi?id=964358

A future patch wants the DAC security manager to be able to safely
get the supplemental group list for a given uid, but at the time
of a fork rather than during initialization so as to pick up on
live changes to the system's group database.  This patch adds the
framework, including the possibility of a pre-fork callback
failing.

For now, any driver that implements a prefork callback must be
robust against the possibility of being part of a security stack
where a later element in the chain fails prefork.  This means
that drivers cannot do any action that requires a call to postfork
for proper cleanup (no grabbing a mutex, for example).  If this
is too prohibitive in the future, we would have to switch to a
transactioning sequence, where each driver has (up to) 3 callbacks:
PreForkPrepare, PreForkCommit, and PreForkAbort, to either clean
up or commit changes made during prepare.

* src/security/security_driver.h (virSecurityDriverPreFork): New
callback.
* src/security/security_manager.h (virSecurityManagerPreFork):
Change signature.
* src/security/security_manager.c (virSecurityManagerPreFork):
Optionally call into driver, and allow returning failure.
* src/security/security_stack.c (virSecurityDriverStack):
Wrap the handler for the stack driver.
* src/qemu/qemu_process.c (qemuProcessStart): Adjust caller.
Signed-off-by: NEric Blake <eblake@redhat.com>
(cherry picked from commit fdb3bde3)
上级 97565e96
...@@ -3693,7 +3693,8 @@ int qemuProcessStart(virConnectPtr conn, ...@@ -3693,7 +3693,8 @@ int qemuProcessStart(virConnectPtr conn,
virCommandDaemonize(cmd); virCommandDaemonize(cmd);
virCommandRequireHandshake(cmd); virCommandRequireHandshake(cmd);
virSecurityManagerPreFork(driver->securityManager); if (virSecurityManagerPreFork(driver->securityManager) < 0)
goto cleanup;
ret = virCommandRun(cmd, NULL); ret = virCommandRun(cmd, NULL);
virSecurityManagerPostFork(driver->securityManager); virSecurityManagerPostFork(driver->securityManager);
......
...@@ -47,6 +47,8 @@ typedef int (*virSecurityDriverClose) (virSecurityManagerPtr mgr); ...@@ -47,6 +47,8 @@ typedef int (*virSecurityDriverClose) (virSecurityManagerPtr mgr);
typedef const char *(*virSecurityDriverGetModel) (virSecurityManagerPtr mgr); typedef const char *(*virSecurityDriverGetModel) (virSecurityManagerPtr mgr);
typedef const char *(*virSecurityDriverGetDOI) (virSecurityManagerPtr mgr); typedef const char *(*virSecurityDriverGetDOI) (virSecurityManagerPtr mgr);
typedef int (*virSecurityDriverPreFork) (virSecurityManagerPtr mgr);
typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityManagerPtr mgr, typedef int (*virSecurityDomainRestoreImageLabel) (virSecurityManagerPtr mgr,
virDomainDefPtr def, virDomainDefPtr def,
virDomainDiskDefPtr disk); virDomainDiskDefPtr disk);
...@@ -119,6 +121,8 @@ struct _virSecurityDriver { ...@@ -119,6 +121,8 @@ struct _virSecurityDriver {
virSecurityDriverGetModel getModel; virSecurityDriverGetModel getModel;
virSecurityDriverGetDOI getDOI; virSecurityDriverGetDOI getDOI;
virSecurityDriverPreFork preFork;
virSecurityDomainSecurityVerify domainSecurityVerify; virSecurityDomainSecurityVerify domainSecurityVerify;
virSecurityDomainSetImageLabel domainSetSecurityImageLabel; virSecurityDomainSetImageLabel domainSetSecurityImageLabel;
......
...@@ -195,11 +195,23 @@ virSecurityManagerPtr virSecurityManagerNew(const char *name, ...@@ -195,11 +195,23 @@ virSecurityManagerPtr virSecurityManagerNew(const char *name,
/* /*
* Must be called before fork()'ing to ensure mutex state * 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); virObjectLock(mgr);
if (mgr->drv->preFork) {
ret = mgr->drv->preFork(mgr);
if (ret < 0)
virObjectUnlock(mgr);
}
return ret;
} }
......
...@@ -47,7 +47,7 @@ virSecurityManagerPtr virSecurityManagerNewDAC(const char *virtDriver, ...@@ -47,7 +47,7 @@ virSecurityManagerPtr virSecurityManagerNewDAC(const char *virtDriver,
bool requireConfined, bool requireConfined,
bool dynamicOwnership); bool dynamicOwnership);
void virSecurityManagerPreFork(virSecurityManagerPtr mgr); int virSecurityManagerPreFork(virSecurityManagerPtr mgr);
void virSecurityManagerPostFork(virSecurityManagerPtr mgr); void virSecurityManagerPostFork(virSecurityManagerPtr mgr);
void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr); void *virSecurityManagerGetPrivateData(virSecurityManagerPtr mgr);
......
...@@ -113,6 +113,27 @@ virSecurityStackGetDOI(virSecurityManagerPtr mgr) ...@@ -113,6 +113,27 @@ virSecurityStackGetDOI(virSecurityManagerPtr mgr)
return virSecurityManagerGetDOI(virSecurityStackGetPrimary(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 static int
virSecurityStackVerify(virSecurityManagerPtr mgr, virSecurityStackVerify(virSecurityManagerPtr mgr,
virDomainDefPtr def) virDomainDefPtr def)
...@@ -542,6 +563,8 @@ virSecurityDriver virSecurityDriverStack = { ...@@ -542,6 +563,8 @@ virSecurityDriver virSecurityDriverStack = {
.getModel = virSecurityStackGetModel, .getModel = virSecurityStackGetModel,
.getDOI = virSecurityStackGetDOI, .getDOI = virSecurityStackGetDOI,
.preFork = virSecurityStackPreFork,
.domainSecurityVerify = virSecurityStackVerify, .domainSecurityVerify = virSecurityStackVerify,
.domainSetSecurityImageLabel = virSecurityStackSetSecurityImageLabel, .domainSetSecurityImageLabel = virSecurityStackSetSecurityImageLabel,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册