mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 14:45:24 +00:00
security_dac: compute supplemental groups before fork
https://bugzilla.redhat.com/show_bug.cgi?id=964358 Commit75c1256
states that virGetGroupList must not be called between fork and exec, then commitee777e99
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: Eric Blake <eblake@redhat.com> (cherry picked from commit29fe5d745f
) Conflicts: src/security/security_dac.c - virSecurityDACSetSecurityUSBLabel needed similar treatment; no virSecurityDACSetChildPrcessLabel
This commit is contained in:
parent
f8d1fb438f
commit
c061ff5e4a
@ -41,6 +41,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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,9 +124,10 @@ int virSecurityDACParseIds(virDomainDefPtr def, uid_t *uidPtr, gid_t *gidPtr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static int
|
||||||
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;
|
||||||
|
|
||||||
@ -135,8 +138,13 @@ int 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,
|
||||||
@ -149,6 +157,10 @@ int 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;
|
||||||
}
|
}
|
||||||
@ -233,8 +245,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +263,21 @@ static const char * virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNU
|
|||||||
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)
|
||||||
{
|
{
|
||||||
@ -437,7 +466,7 @@ virSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
|
|||||||
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);
|
||||||
@ -456,7 +485,7 @@ virSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
|
|||||||
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);
|
||||||
@ -602,7 +631,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) {
|
||||||
@ -838,25 +867,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", user, group);
|
VIR_DEBUG("Dropping privileges of DEF to %u:%u, %d supplemental groups",
|
||||||
|
(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1037,6 +1061,8 @@ virSecurityDriver virSecurityDriverDAC = {
|
|||||||
.getModel = virSecurityDACGetModel,
|
.getModel = virSecurityDACGetModel,
|
||||||
.getDOI = virSecurityDACGetDOI,
|
.getDOI = virSecurityDACGetDOI,
|
||||||
|
|
||||||
|
.preFork = virSecurityDACPreFork,
|
||||||
|
|
||||||
.domainSecurityVerify = virSecurityDACVerify,
|
.domainSecurityVerify = virSecurityDACVerify,
|
||||||
|
|
||||||
.domainSetSecurityImageLabel = virSecurityDACSetSecurityImageLabel,
|
.domainSetSecurityImageLabel = virSecurityDACSetSecurityImageLabel,
|
||||||
|
Loading…
Reference in New Issue
Block a user