提交 47d520cd 编写于 作者: E Eric Blake

security_dac: compute supplemental groups before fork

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

Commit 75c12564 states that virGetGroupList must not be called
between fork and exec, then commit ee777e99 promptly violated
that for lxc's use of virSecurityManagerSetProcessLabel.  Hoist
the supplemental group detection to the time that the security
manager needs to fork.  Qemu is safe, as it uses
virSecurityManagerSetChildProcessLabel which in turn uses
virCommand to determine supplemental groups.

This does not fix the fact that virSecurityManagerSetProcessLabel
calls virSecurityDACParseIds calls parseIds which eventually
calls getpwnam_r, which also violates fork/exec async-signal-safe
safety rules, but so far no one has complained of hitting
deadlock in that case.

* src/security/security_dac.c (_virSecurityDACData): Track groups
in private data.
(virSecurityDACPreFork): New function, to set them.
(virSecurityDACClose): Clean up new fields.
(virSecurityDACGetIds): Alter signature.
(virSecurityDACSetSecurityHostdevLabelHelper)
(virSecurityDACSetChardevLabel, virSecurityDACSetProcessLabel)
(virSecurityDACSetChildProcessLabel): Update callers.
Signed-off-by: NEric Blake <eblake@redhat.com>
(cherry picked from commit 29fe5d74)
上级 6a47028a
...@@ -43,6 +43,8 @@ typedef virSecurityDACData *virSecurityDACDataPtr; ...@@ -43,6 +43,8 @@ typedef virSecurityDACData *virSecurityDACDataPtr;
struct _virSecurityDACData { struct _virSecurityDACData {
uid_t user; uid_t user;
gid_t group; gid_t group;
gid_t *groups;
int ngroups;
bool dynamicOwnership; bool dynamicOwnership;
}; };
...@@ -146,7 +148,8 @@ virSecurityDACParseIds(virDomainDefPtr def, uid_t *uidPtr, gid_t *gidPtr) ...@@ -146,7 +148,8 @@ virSecurityDACParseIds(virDomainDefPtr def, uid_t *uidPtr, gid_t *gidPtr)
static int static int
virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv, virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv,
uid_t *uidPtr, gid_t *gidPtr) uid_t *uidPtr, gid_t *gidPtr,
gid_t **groups, int *ngroups)
{ {
int ret; int ret;
...@@ -157,8 +160,13 @@ virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv, ...@@ -157,8 +160,13 @@ virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv,
return -1; return -1;
} }
if ((ret = virSecurityDACParseIds(def, uidPtr, gidPtr)) <= 0) if ((ret = virSecurityDACParseIds(def, uidPtr, gidPtr)) <= 0) {
if (groups)
*groups = NULL;
if (ngroups)
*ngroups = 0;
return ret; return ret;
}
if (!priv) { if (!priv) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
...@@ -171,6 +179,10 @@ virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv, ...@@ -171,6 +179,10 @@ virSecurityDACGetIds(virDomainDefPtr def, virSecurityDACDataPtr priv,
*uidPtr = priv->user; *uidPtr = priv->user;
if (gidPtr) if (gidPtr)
*gidPtr = priv->group; *gidPtr = priv->group;
if (groups)
*groups = priv->groups;
if (ngroups)
*ngroups = priv->ngroups;
return 0; return 0;
} }
...@@ -250,8 +262,10 @@ virSecurityDACOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) ...@@ -250,8 +262,10 @@ virSecurityDACOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
} }
static int static int
virSecurityDACClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) virSecurityDACClose(virSecurityManagerPtr mgr)
{ {
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
VIR_FREE(priv->groups);
return 0; return 0;
} }
...@@ -268,6 +282,21 @@ virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED) ...@@ -268,6 +282,21 @@ virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
return "0"; return "0";
} }
static int
virSecurityDACPreFork(virSecurityManagerPtr mgr)
{
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int ngroups;
VIR_FREE(priv->groups);
priv->ngroups = 0;
if ((ngroups = virGetGroupList(priv->user, priv->group,
&priv->groups)) < 0)
return -1;
priv->ngroups = ngroups;
return 0;
}
static int static int
virSecurityDACSetOwnership(const char *path, uid_t uid, gid_t gid) virSecurityDACSetOwnership(const char *path, uid_t uid, gid_t gid)
{ {
...@@ -448,7 +477,7 @@ virSecurityDACSetSecurityHostdevLabelHelper(const char *file, ...@@ -448,7 +477,7 @@ virSecurityDACSetSecurityHostdevLabelHelper(const char *file,
uid_t user; uid_t user;
gid_t group; gid_t group;
if (virSecurityDACGetIds(def, priv, &user, &group)) if (virSecurityDACGetIds(def, priv, &user, &group, NULL, NULL))
return -1; return -1;
return virSecurityDACSetOwnership(file, user, group); return virSecurityDACSetOwnership(file, user, group);
...@@ -702,7 +731,7 @@ virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr, ...@@ -702,7 +731,7 @@ virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
uid_t user; uid_t user;
gid_t group; gid_t group;
if (virSecurityDACGetIds(def, priv, &user, &group)) if (virSecurityDACGetIds(def, priv, &user, &group, NULL, NULL))
return -1; return -1;
switch (dev->type) { switch (dev->type) {
...@@ -1000,26 +1029,20 @@ virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr, ...@@ -1000,26 +1029,20 @@ virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
{ {
uid_t user; uid_t user;
gid_t group; gid_t group;
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
gid_t *groups; gid_t *groups;
int ngroups; int ngroups;
int ret = -1; virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
if (virSecurityDACGetIds(def, priv, &user, &group)) if (virSecurityDACGetIds(def, priv, &user, &group, &groups, &ngroups))
return -1;
ngroups = virGetGroupList(user, group, &groups);
if (ngroups < 0)
return -1; return -1;
VIR_DEBUG("Dropping privileges of DEF to %u:%u", VIR_DEBUG("Dropping privileges of DEF to %u:%u, %d supplemental groups",
(unsigned int) user, (unsigned int) group); (unsigned int) user, (unsigned int) group, ngroups);
if (virSetUIDGID(user, group, groups, ngroups) < 0) if (virSetUIDGID(user, group, groups, ngroups) < 0)
goto cleanup; return -1;
ret = 0;
cleanup: return 0;
VIR_FREE(groups);
return ret;
} }
...@@ -1032,7 +1055,7 @@ virSecurityDACSetChildProcessLabel(virSecurityManagerPtr mgr, ...@@ -1032,7 +1055,7 @@ virSecurityDACSetChildProcessLabel(virSecurityManagerPtr mgr,
gid_t group; gid_t group;
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr); virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
if (virSecurityDACGetIds(def, priv, &user, &group)) if (virSecurityDACGetIds(def, priv, &user, &group, NULL, NULL))
return -1; return -1;
VIR_DEBUG("Setting child to drop privileges of DEF to %u:%u", VIR_DEBUG("Setting child to drop privileges of DEF to %u:%u",
...@@ -1212,6 +1235,8 @@ virSecurityDriver virSecurityDriverDAC = { ...@@ -1212,6 +1235,8 @@ virSecurityDriver virSecurityDriverDAC = {
.getModel = virSecurityDACGetModel, .getModel = virSecurityDACGetModel,
.getDOI = virSecurityDACGetDOI, .getDOI = virSecurityDACGetDOI,
.preFork = virSecurityDACPreFork,
.domainSecurityVerify = virSecurityDACVerify, .domainSecurityVerify = virSecurityDACVerify,
.domainSetSecurityImageLabel = virSecurityDACSetSecurityImageLabel, .domainSetSecurityImageLabel = virSecurityDACSetSecurityImageLabel,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册