util: simplify virSetUIDGIDWithCaps

The need_prctl variable is not really needed.  If it is false,
capng_apply will be called twice with the same set, causing
a little extra work but no problem.  This keeps the code a bit
simpler.

It is also clearer to invoke capng_apply(CAPNG_SELECT_BOUNDS)
separately, to make sure it is done while we have CAP_SETPCAP.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2013-03-25 15:25:28 +01:00 committed by Eric Blake
parent f78266dfc2
commit 658718454a

View File

@ -3004,7 +3004,7 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits,
{ {
int ii, capng_ret, ret = -1; int ii, capng_ret, ret = -1;
bool need_setgid = false, need_setuid = false; bool need_setgid = false, need_setuid = false;
bool need_prctl = false, need_setpcap = false; bool need_setpcap = false;
/* First drop all caps (unless the requested uid is "unchanged" or /* First drop all caps (unless the requested uid is "unchanged" or
* root and clearExistingCaps wasn't requested), then add back * root and clearExistingCaps wasn't requested), then add back
@ -3044,17 +3044,15 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits,
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP); capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP);
# endif # endif
need_prctl = capBits || need_setgid || need_setuid || need_setpcap;
/* Tell system we want to keep caps across uid change */ /* Tell system we want to keep caps across uid change */
if (need_prctl && prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("prctl failed to set KEEPCAPS")); _("prctl failed to set KEEPCAPS"));
goto cleanup; goto cleanup;
} }
/* Change to the temp capabilities */ /* Change to the temp capabilities */
if ((capng_ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) { if ((capng_ret = capng_apply(CAPNG_SELECT_CAPS)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot apply process capabilities %d"), capng_ret); _("cannot apply process capabilities %d"), capng_ret);
goto cleanup; goto cleanup;
@ -3064,12 +3062,18 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits,
goto cleanup; goto cleanup;
/* Tell it we are done keeping capabilities */ /* Tell it we are done keeping capabilities */
if (need_prctl && prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0)) { if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0)) {
virReportSystemError(errno, "%s", virReportSystemError(errno, "%s",
_("prctl failed to reset KEEPCAPS")); _("prctl failed to reset KEEPCAPS"));
goto cleanup; goto cleanup;
} }
/* Set bounding set while we have CAP_SETPCAP. Unfortunately we cannot
* do this if we failed to get the capability above, so ignore the
* return value.
*/
capng_apply(CAPNG_SELECT_BOUNDS);
/* Drop the caps that allow setuid/gid (unless they were requested) */ /* Drop the caps that allow setuid/gid (unless they were requested) */
if (need_setgid) if (need_setgid)
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETGID); capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETGID);
@ -3079,7 +3083,7 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, unsigned long long capBits,
if (need_setpcap) if (need_setpcap)
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP); capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP);
if (need_prctl && ((capng_ret = capng_apply(CAPNG_SELECT_BOTH)) < 0)) { if (((capng_ret = capng_apply(CAPNG_SELECT_CAPS)) < 0)) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot apply process capabilities %d"), capng_ret); _("cannot apply process capabilities %d"), capng_ret);
ret = -1; ret = -1;