[libvirt] [PATCH] lxc: Add virCgroupSetOwner()

Martin Kletzander mkletzan at redhat.com
Fri Feb 14 08:59:45 UTC 2014


On Fri, Feb 14, 2014 at 08:47:37AM +0100, Richard Weinberger wrote:
> Am 14.02.2014 08:10, schrieb Martin Kletzander:
> > On Thu, Feb 13, 2014 at 05:15:22PM +0000, Daniel P. Berrange wrote:
> >> From: Richard Weinberger <richard at nod.at>
> >>
> >> Add a new helper function to change the permissions of a control
> >> group. This function is needed for user namespaces, we need to
> >> chmod() the cgroup to the initial uid/gid such that systemd is
> >> allowed to use the cgroup.
> >>
> >> Only the systemd controller is made accessible to the container.
> >> Others must remain read-only since it is generally not safe
> >> to delegate resource controller write access to unprivileged
> >> processes.
> >>
> >> Signed-off-by: Richard Weinberger <richard at nod.at>
> >> ---
> >>  src/libvirt_private.syms |  1 +
> >>  src/lxc/lxc_cgroup.c     |  9 ++++++++
> >>  src/util/vircgroup.c     | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
> >>  src/util/vircgroup.h     |  5 +++++
> >>  4 files changed, 69 insertions(+)
> >>
> >> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> >> index 0b28bac..cfa9f75 100644
> >> --- a/src/libvirt_private.syms
> >> +++ b/src/libvirt_private.syms
> >> @@ -1056,6 +1056,7 @@ virCgroupSetMemory;
> >>  virCgroupSetMemoryHardLimit;
> >>  virCgroupSetMemorySoftLimit;
> >>  virCgroupSetMemSwapHardLimit;
> >> +virCgroupSetOwner;
> >>  virCgroupSupportsCpuBW;
> >>
> >>
> >> diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
> >> index cc0d5e8..0d0d9c0 100644
> >> --- a/src/lxc/lxc_cgroup.c
> >> +++ b/src/lxc/lxc_cgroup.c
> >> @@ -484,6 +484,15 @@ virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def)
> >>                              &cgroup) < 0)
> >>          goto cleanup;
> >>
> >> +    /* setup control group permissions for user namespace */
> >> +    if (def->idmap.uidmap) {
> >> +        if (virCgroupSetOwner(cgroup,
> >> +                              def->idmap.uidmap[0].target,
> >> +                              def->idmap.gidmap[0].target,
> >> +                              (1 << VIR_CGROUP_CONTROLLER_SYSTEMD)))
> >
> > This should be "if (virCgroupSetOwner() < 0)" to go with the rest.
>
> Ok.
>
> >> +            goto cleanup;
> >> +    }
> >> +
> >
> > virCgroupNewMachine() guarantees that the cgroup is NULL in case of an
> > error, but you don't guarantee that in virCgroupSetOwner(), so the
> > errors from it won't propagate anywhere, because you don't return NULL
> > from this function.
>
> Do we really want to treat a failed chown() as fatal error?
>

I'm not saying either way, but if you're not using the error (or you
don't want that error to be used, than don't report it with
virReportError() and use VIR_WARN() for example.  However, if the
called function should report an error and this is the only case
which should not do it (an exception), then reset the error at least.

> >>  cleanup:
> >>      return cgroup;
> >>  }
> >> diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
> >> index a6d60c5..2dc6986 100644
> >> --- a/src/util/vircgroup.c
> >> +++ b/src/util/vircgroup.c
> >> @@ -3253,6 +3253,60 @@ cleanup:
> >>  }
> >>
> >>
> >> +int virCgroupSetOwner(virCgroupPtr cgroup,
> >> +                      uid_t uid,
> >> +                      gid_t gid,
> >> +                      int controllers)
> >> +{
> >> +    size_t i;
> >> +
> >> +    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
> >> +        char *base, *entry;
> >> +        DIR *dh;
> >> +        struct dirent *de;
> >> +
> >> +        if (!((1 << i) & controllers))
> >> +            continue;
> >> +
> >> +        if (!cgroup->controllers[i].mountPoint)
> >> +            continue;
> >> +
> >> +        if (virAsprintf(&base, "%s%s", cgroup->controllers[i].mountPoint,
> >> +            cgroup->controllers[i].placement) < 0) {
> >> +                virReportOOMError();
> >
> > Double OOM reporting.
>
> Ahh, virAsprintf() already reports the error...
>
> >> +                return -1;
> >> +        }
> >> +
> >> +        dh = opendir(base);
> >> +        while ((de = readdir(dh)) != NULL) {
> >> +            if (STREQ(de->d_name, ".") ||
> >> +                STREQ(de->d_name, ".."))
> >> +                continue;
> >> +
> >> +            if (virAsprintf(&entry, "%s/%s", base, de->d_name) < 0) {
> >> +                VIR_FREE(base);
> >> +                virReportOOMError();
> >
> > Same here, plus you continue the loop and don't return -1.
>
> Ok!
>
> >> +            }
> >> +
> >> +            if (chown(entry, uid, gid) < 0)
> >> +                virReportSystemError(errno, _("cannot chown '%s' to (%u, %u)"),
> >> +                    entry, uid, gid);
> >
> > Indentation's off and you continue the loop again.
>
> I continue here by design because I don't treat a failed chown() as fatal error.
>
> >> +
> >> +            VIR_FREE(entry);
> >> +        }
> >> +        closedir(dh);
> >> +
> >> +        if (chown(base, uid, gid) < 0)
> >> +            virReportSystemError(errno, _("cannot chown '%s' to (%u, %u)"),
> >> +                base, uid, gid);
> >
> > Again reporting an error, but returning 0 even in case of an error.
>
> Same here.
>
> Thanks,
> //richard
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140214/64ee6a07/attachment-0001.sig>


More information about the libvir-list mailing list