execute: when we run as PID 1 the kernel doesn't give us CAP_SETPCAP by default. Get that temporarily when dropping capabilities for good
This commit is contained in:
+66
-7
@@ -904,6 +904,68 @@ fail:
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_capability_bounding_set_drop(uint64_t drop) {
|
||||
unsigned long i;
|
||||
cap_t old_cap = NULL, new_cap = NULL;
|
||||
cap_flag_value_t fv;
|
||||
int r;
|
||||
|
||||
/* If we are run as PID 1 we will lack CAP_SETPCAP by default
|
||||
* in the effective set (yes, the kernel drops that when
|
||||
* executing init!), so get it back temporarily so that we can
|
||||
* call PR_CAPBSET_DROP. */
|
||||
|
||||
old_cap = cap_get_proc();
|
||||
if (!old_cap)
|
||||
return -errno;
|
||||
|
||||
if (cap_get_flag(old_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (fv != CAP_SET) {
|
||||
static const cap_value_t v = CAP_SETPCAP;
|
||||
|
||||
new_cap = cap_dup(old_cap);
|
||||
if (!new_cap) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (cap_set_flag(new_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (cap_set_proc(new_cap) < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i <= CAP_LAST_CAP; i++)
|
||||
if (drop & ((uint64_t) 1ULL << (uint64_t) i)) {
|
||||
if (prctl(PR_CAPBSET_DROP, i) < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
if (new_cap)
|
||||
cap_free(new_cap);
|
||||
|
||||
if (old_cap) {
|
||||
cap_set_proc(old_cap);
|
||||
cap_free(old_cap);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int exec_spawn(ExecCommand *command,
|
||||
char **argv,
|
||||
const ExecContext *context,
|
||||
@@ -1251,13 +1313,10 @@ int exec_spawn(ExecCommand *command,
|
||||
}
|
||||
|
||||
if (context->capability_bounding_set_drop)
|
||||
for (i = 0; i <= CAP_LAST_CAP; i++)
|
||||
if (context->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) i)) {
|
||||
if (prctl(PR_CAPBSET_DROP, i) < 0) {
|
||||
r = EXIT_CAPABILITIES;
|
||||
goto fail_child;
|
||||
}
|
||||
}
|
||||
if (do_capability_bounding_set_drop(context->capability_bounding_set_drop) < 0) {
|
||||
r = EXIT_CAPABILITIES;
|
||||
goto fail_child;
|
||||
}
|
||||
|
||||
if (context->user)
|
||||
if (enforce_user(context, uid) < 0) {
|
||||
|
||||
Reference in New Issue
Block a user