[libvirt] [PATCH v2 1/2] security: also parse user/group names instead of just IDs for DAC labels

Peter Krempa pkrempa at redhat.com
Tue Sep 25 09:25:22 UTC 2012


On 09/20/12 23:07, Marcelo Cerri wrote:
> The DAC driver is missing parsing of group and user names for DAC labels
> and currently just parses uid and gid. This patch extends it to support
> names, so the following security label definition is now valid:
>
>    <seclabel type='static' model='dac' relabel='yes'>
>        <label>qemu:qemu</label>
>        <imagelabel>qemu:qemu</imagelabel>
>    </seclabel>
>
> When it tries to parse an owner or a group, it first tries to resolve it as
> a name, if it fails or it's an invalid user/group name then it tries to
> parse it as an UID or GID. A leading '+' can also be used for both owner and
> group to force it to be parsed as IDs, so the following example is also
> valid:
>
>    <seclabel type='static' model='dac' relabel='yes'>
>        <label>+101:+101</label>
>        <imagelabel>+101:+101</imagelabel>
>    </seclabel>
>
> This ensures that UID 101 and GUI 101 will be used instead of an user or
> group named "101".
> ---
>   src/security/security_dac.c | 62 +++++++++++++++++++++++++++++++++++++++------
>   1 file changed, 54 insertions(+), 8 deletions(-)
>
> diff --git a/src/security/security_dac.c b/src/security/security_dac.c
> index 5f30f0f..00cbb8a 100644
> --- a/src/security/security_dac.c
> +++ b/src/security/security_dac.c
> @@ -68,26 +68,72 @@ void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
>   static
>   int parseIds(const char *label, uid_t *uidPtr, gid_t *gidPtr)
>   {
> +    int rc = -1;
>       unsigned int theuid;
>       unsigned int thegid;
> -    char *endptr = NULL;
> +    char *tmp_label = NULL;
> +    char *sep = NULL;
> +    char *owner = NULL;
> +    char *group = NULL;
>
>       if (label == NULL)
> -        return -1;
> +        goto cleanup;

"label" is guaranteed to be non-null here. Removing this condition will 
prevent you from inventing a new error message for this while changing 
to proper error reporting (see below.).

>
> -    if (virStrToLong_ui(label, &endptr, 10, &theuid) ||
> -        endptr == NULL || *endptr != ':') {
> -        return -1;
> +    tmp_label = strdup(label);
> +    if (tmp_label == NULL) {
> +        virReportOOMError();
> +        goto cleanup;
>       }
>
> -    if (virStrToLong_ui(endptr + 1, NULL, 10, &thegid))
> -        return -1;
> +    /* Split label */
> +    sep = strchr(tmp_label, ':');
> +    if (sep == NULL) {
> +        VIR_DEBUG("Missgin separator ':' in DAC label \"%s\"", label);

s/Missgin/Missing/

Also now when this function has a lot of more detail to report about the 
problems with the security label, I'd change it back to reporting a 
proper error and removing the error in the function that calls this that 
would mas errors from here.

I think a good error code here would be VIR_ERR_INVALID_ARG.

> +        goto cleanup;
> +    }
> +    *sep = '\0';
> +    owner = tmp_label;
> +    group = sep + 1;
> +
> +    /* Parse owner */
> +    if (*owner == '+') {
> +        if (virStrToLong_ui(++owner, NULL, 10, &theuid) < 0) {
> +            VIR_DEBUG("Invalid uid \"%s\" in DAC label \"%s\"", owner, label);

Also this is a nice proper error message.

> +            goto cleanup;
> +        }
> +    } else {
> +        if (virGetUserID(owner, &theuid) < 0 &&
> +            virStrToLong_ui(owner, NULL, 10, &theuid) < 0) {
> +            VIR_DEBUG("Invalid owner \"%s\" in DAC label \"%s\"", owner, label);

Here too.

> +            goto cleanup;
> +        }
> +    }
> +
> +    /* Parse group */
> +    if (*group == '+') {
> +        if (virStrToLong_ui(++group, NULL, 10, &thegid) < 0) {
> +            VIR_DEBUG("Invalid gid \"%s\" in DAC label \"%s\"", group, label);

Here.

> +            goto cleanup;
> +        }
> +    } else {
> +        if (virGetGroupID(group, &thegid) < 0 &&
> +            virStrToLong_ui(group, NULL, 10, &thegid) < 0) {
> +            VIR_DEBUG("Invalid group \"%s\" in DAC label \"%s\"", group, label);

And here :)

> +            goto cleanup;
> +        }
> +    }
>
>       if (uidPtr)
>           *uidPtr = theuid;
>       if (gidPtr)
>           *gidPtr = thegid;
> -    return 0;
> +
> +    rc = 0;
> +
> +cleanup:
> +    VIR_FREE(tmp_label);
> +
> +    return rc;
>   }
>
>   /* returns 1 if label isn't found, 0 on success, -1 on error */
>

When changing the the error messages as I suggest, you will have to 
squash in the attached patch to avoid masking the errors. Otherwise the 
code looks fine and I'm looking forward to review v3.

Peter

-------------- next part --------------
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 1268f13..8e72aff 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -153,12 +153,8 @@ int virSecurityDACParseIds(virDomainDefPtr def, uid_t *uidPtr, gid_t *gidPtr)
         return 1;
     }

-    if (seclabel->label && parseIds(seclabel->label, &uid, &gid)) {
-       virReportError(VIR_ERR_INVALID_ARG,
-                       _("failed to parse DAC seclabel '%s' for domain '%s'"),
-                       seclabel->label, def->name);
+    if (parseIds(seclabel->label, &uid, &gid) < 0)
         return -1;
-    }

     if (uidPtr)
         *uidPtr = uid;
@@ -218,13 +214,8 @@ int virSecurityDACParseImageIds(virDomainDefPtr def,
         return 1;
     }

-    if (seclabel->imagelabel
-        && parseIds(seclabel->imagelabel, &uid, &gid)) {
-       virReportError(VIR_ERR_INVALID_ARG,
-                       _("failed to parse DAC imagelabel '%s' for domain '%s'"),
-                       seclabel->imagelabel, def->name);
+    if (parseIds(seclabel->imagelabel, &uid, &gid) < 0)
         return -1;
-    }

     if (uidPtr)
         *uidPtr = uid;


More information about the libvir-list mailing list