Merge pull request #9762 from poettering/nspawn-oci

OCI runtime support for nspawn
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2019-03-21 11:01:53 +01:00
committed by GitHub
18 changed files with 3423 additions and 210 deletions
+69 -11
View File
@@ -47,6 +47,13 @@ unsigned long cap_last_cap(void) {
if (r >= 0) {
r = safe_atolu(content, &p);
if (r >= 0) {
if (p > 63) /* Safety for the future: if one day the kernel learns more than 64 caps,
* then we are in trouble (since we, as much userspace and kernel space
* store capability masks in uint64_t types. Let's hence protect
* ourselves against that and always cap at 63 for now. */
p = 63;
saved = p;
valid = true;
return p;
@@ -58,17 +65,15 @@ unsigned long cap_last_cap(void) {
if (prctl(PR_CAPBSET_READ, p) < 0) {
/* Hmm, look downwards, until we find one that
* works */
/* Hmm, look downwards, until we find one that works */
for (p--; p > 0; p --)
if (prctl(PR_CAPBSET_READ, p) >= 0)
break;
} else {
/* Hmm, look upwards, until we find one that doesn't
* work */
for (;; p++)
/* Hmm, look upwards, until we find one that doesn't work */
for (; p < 63; p++)
if (prctl(PR_CAPBSET_READ, p+1) < 0)
break;
}
@@ -363,6 +368,7 @@ bool ambient_capabilities_supported(void) {
int capability_quintet_enforce(const CapabilityQuintet *q) {
_cleanup_cap_free_ cap_t c = NULL;
bool need_set_proc_again = false;
int r;
if (q->ambient != (uint64_t) -1) {
@@ -393,7 +399,6 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
if (cap_set_flag(c, CAP_INHERITABLE, 1, &cv, CAP_SET) < 0)
return -errno;
if (cap_set_flag(c, CAP_PERMITTED, 1, &cv, CAP_SET) < 0)
return -errno;
@@ -426,8 +431,15 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
if (q->inheritable != (uint64_t) -1) {
cap_flag_value_t old_value, new_value;
if (cap_get_flag(c, cv, CAP_INHERITABLE, &old_value) < 0)
if (cap_get_flag(c, cv, CAP_INHERITABLE, &old_value) < 0) {
if (errno == EINVAL) /* If the kernel knows more caps than this
* version of libcap, then this will return
* EINVAL. In that case, simply ignore it,
* pretend it doesn't exist. */
continue;
return -errno;
}
new_value = (q->inheritable & m) ? CAP_SET : CAP_CLEAR;
@@ -442,8 +454,12 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
if (q->permitted != (uint64_t) -1) {
cap_flag_value_t old_value, new_value;
if (cap_get_flag(c, cv, CAP_PERMITTED, &old_value) < 0)
if (cap_get_flag(c, cv, CAP_PERMITTED, &old_value) < 0) {
if (errno == EINVAL)
continue;
return -errno;
}
new_value = (q->permitted & m) ? CAP_SET : CAP_CLEAR;
@@ -458,8 +474,12 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
if (q->effective != (uint64_t) -1) {
cap_flag_value_t old_value, new_value;
if (cap_get_flag(c, cv, CAP_EFFECTIVE, &old_value) < 0)
if (cap_get_flag(c, cv, CAP_EFFECTIVE, &old_value) < 0) {
if (errno == EINVAL)
continue;
return -errno;
}
new_value = (q->effective & m) ? CAP_SET : CAP_CLEAR;
@@ -472,9 +492,39 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
}
}
if (changed)
if (cap_set_proc(c) < 0)
if (changed) {
_cleanup_cap_free_ cap_t modified = NULL;
/* In order to change the bounding caps, we need to keep CAP_SETPCAP for a bit
* longer. Let's add it to our list hence for now. */
if (q->bounding != (uint64_t) -1) {
cap_value_t cv = CAP_SETPCAP;
modified = cap_dup(c);
if (!modified)
return -ENOMEM;
if (cap_set_flag(modified, CAP_PERMITTED, 1, &cv, CAP_SET) < 0)
return -errno;
if (cap_set_flag(modified, CAP_EFFECTIVE, 1, &cv, CAP_SET) < 0)
return -errno;
if (cap_compare(modified, c) == 0) {
/* No change? then drop this nonsense again */
cap_free(modified);
modified = NULL;
}
}
/* Now, let's enforce the caps for the first time. Note that this is where we acquire
* caps in any of the sets we currently don't have. We have to do this before
* droppoing the bounding caps below, since at that point we can never acquire new
* caps in inherited/permitted/effective anymore, but only lose them.*/
if (cap_set_proc(modified ?: c) < 0)
return -errno;
need_set_proc_again = !!modified;
}
}
if (q->bounding != (uint64_t) -1) {
@@ -483,5 +533,13 @@ int capability_quintet_enforce(const CapabilityQuintet *q) {
return r;
}
/* If needed, let's now set the caps again, this time in the final version, which differs from what
* we have already set only in the CAP_SETPCAP bit, which we needed for dropping the bounding
* bits. This call only undoes bits and doesn't acquire any which means the bounding caps don't
* matter. */
if (need_set_proc_again)
if (cap_set_proc(c) < 0)
return -errno;
return 0;
}
+5 -3
View File
@@ -33,10 +33,12 @@ static inline void cap_free_charpp(char **p) {
}
#define _cleanup_cap_free_charp_ _cleanup_(cap_free_charpp)
static inline uint64_t all_capabilities(void) {
return UINT64_MAX >> (63 - cap_last_cap());
}
static inline bool cap_test_all(uint64_t caps) {
uint64_t m;
m = (UINT64_C(1) << (cap_last_cap() + 1)) - 1;
return FLAGS_SET(caps, m);
return FLAGS_SET(caps, all_capabilities());
}
bool ambient_capabilities_supported(void);