]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virSetUIDGIDWithCaps: Don't drop CAP_SETPCAP right away
authorMichal Privoznik <mprivozn@redhat.com>
Thu, 24 Jun 2021 14:58:09 +0000 (16:58 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 29 Jun 2021 06:52:12 +0000 (08:52 +0200)
There are few cases where we execute a virCommand with all caps
cleared (virCommandClearCaps()). For instance
dnsmasqCapsRefreshInternal() does just that. This means, that
after fork() and before exec() the virSetUIDGIDWithCaps() is
called. But since the caller did not want to change anything,
just drop capabilities, these are the values of arguments:

  virSetUIDGIDWithCaps (uid=-1, gid=-1, groups=0x0, ngroups=0,
                        capBits=0, clearExistingCaps=true)

This means that indeed all capabilities will be dropped,
including CAP_SETPCAP. But this capability controls whether
capabilities can be set, IOW whether capng_apply() succeeds.

There are two calls of capng_apply() in the function. The
CAP_SETPCAP is dropped after the first call and thus the other
call (capng_apply(CAPNG_SELECT_BOUNDS);) fails.

The solution is to keep the capability for as long as needed
(just like CAP_SETGID and CAP_SETUID) and drop it only at the
very end (just like CAP_SETGID and CAP_SETUID).

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1949388
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
src/util/virutil.c

index 311cbbf93ac218066b9f3f69cd7081a627e68bf4..199d4052864e818d1f2f243ab43dc6245e51de00 100644 (file)
@@ -1184,12 +1184,10 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, gid_t *groups, int ngroups,
     }
 # ifdef PR_CAPBSET_DROP
     /* If newer kernel, we need also need setpcap to change the bounding set */
-    if ((capBits || need_setgid || need_setuid) &&
-        !capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
+    if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
         need_setpcap = true;
-    }
-    if (need_setpcap)
         capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP);
+    }
 # endif
 
     /* Tell system we want to keep caps across uid change */