Merge pull request #334 from brauner/2021-05-06.cap_setfcap

libmisc: retain CAP_SETFCAP when mapping uid 0
This commit is contained in:
Serge Hallyn 2021-05-06 14:45:50 -05:00 committed by GitHub
commit e9e8e3270f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -123,6 +123,25 @@ struct map_range *get_map_ranges(int ranges, int argc, char **argv)
*/
#define ULONG_DIGITS ((((sizeof(unsigned long) * CHAR_BIT) + 9)/10)*3)
#if HAVE_SYS_CAPABILITY_H
static inline bool maps_lower_root(int cap, int ranges, struct map_range *mappings)
{
int idx;
struct map_range *mapping;
if (cap != CAP_SETUID)
return false;
mapping = mappings;
for (idx = 0; idx < ranges; idx++, mapping++) {
if (mapping->lower == 0)
return true;
}
return false;
}
#endif
/*
* The ruid refers to the caller's uid and is used to reset the effective uid
* back to the callers real uid.
@ -177,6 +196,12 @@ void write_mapping(int proc_dir_fd, int ranges, struct map_range *mappings,
/* Lockdown new{g,u}idmap by dropping all unneeded capabilities. */
memset(data, 0, sizeof(data));
data[0].effective = CAP_TO_MASK(cap);
/*
* When uid 0 from the ancestor userns is supposed to be mapped into
* the child userns we need to retain CAP_SETFCAP.
*/
if (maps_lower_root(cap, ranges, mappings))
data[0].effective |= CAP_TO_MASK(CAP_SETFCAP);
data[0].permitted = data[0].effective;
if (capset(&hdr, data) < 0) {
fprintf(stderr, _("%s: Could not set caps\n"), Prog);